flutterflame

How to build a selectable cell grid?


So currently I''m trying to learn the flame framework to build game with flutter. My use case involves creating a grid and listening to clicks on that grid. Once a cell is tapped inside the grid, I need to highlight that cell. Something like this can be achieved as follows in flutter:

import 'package:equatable/equatable.dart';
import 'package:flame/game.dart';
import 'package:flutter/material.dart';

import './src/my_game.dart';

void main() {
  // final game = MyGame();
  // runApp(GameWidget(game: game));
  runApp(Grid());
}

class Grid extends StatefulWidget {
  const Grid({super.key});

  @override
  State<Grid> createState() => _GridState();
}

class Position extends Equatable {
  final int rowIndex;
  final int colIndex;

  const Position(this.rowIndex, this.colIndex);
  
  @override
  List<Object?> get props => [rowIndex, colIndex];
}

class _GridState extends State<Grid> {
  final List<Position> selectedPositions = [];

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Grid'),
        ),
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: List.generate(8, (rowIndex) {
            return Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: List.generate(8, (colIndex) {
                return GestureDetector(
                  onTap: () {
                    setState(() {
                      selectedPositions.add(Position(rowIndex, colIndex));
                    });
                  },
                  child: Container(
                    height: 20,
                    width: 20,
                    decoration: BoxDecoration(
                      border: Border.all(width: 1, color: Colors.black),
                      color: selectedPositions
                              .contains(Position(rowIndex, colIndex))
                          ? Colors.red
                          : null,
                    ),
                  ),
                );
              }),
            );
          }),
        ),
      ),
    );
  }
}

But I've no idea how to get the same thing in Flame via the render() method. Can someone please guide me or maybe provide a sample code on how to get this done? Thank you so much.

I couldn't really try anything to be honest. I gave it a deep though on how to do something like this but couldn't figure it out. I tried checking other resources like Youtube, articles etc. but couldn't understand.


Solution

  • Create a RectangleComponent with TapCallbacks and lay them out in a grid using a nested for-loop for example.

    Something like this:

    class MyTile extends RectangleComponent with TapCallbacks {
      MyTile({required super.position}) : super(size: Vector2(tileWidth, tileHeight));
    
      @override
      void onTapDown(TapDownEvent event) {
        ...
      }
    }
    
    ...
    
    for(var y = 0; y * tileHeight < size.y; y++) {
      for(var x = 0; x * tileWidth < size.x; x++) {
        add(
          MyTile(
            position: Vector2(x * tileWidth, y * tileHeight),
          ),
        );
      }
    }