Search code examples
flutterdartflame

How to detect tap on Flame components?


I am using Flutter and flame (0.29.3) to build a simple mobile game. I am trying to detect taps on PositionComponent/SpriteComponent. However, I fail to do so. References/tutorials are using addGestureRecognizer but it is deprecated.

I define my PositionComponent is as follows;

class Enemy extends PositionComponent with Tapable {
  Rect enemyRect;

  Enemy(double x, double y) {
    enemyRect = Rect.fromLTWH(x, y, 50, 50);
  }

  @override
  void render(Canvas c) {
    Color color = Color(0XFFFF0000);
    Paint enemyColor = Paint()..color = color;
    c.drawRect(enemyRect, enemyColor);
  }

  void update(double t) {}

  @override
  void onTapUp(TapUpDetails details) {
    print("tap up");
  }

  @override
  void onTapDown(TapDownDetails details) {
    print("tap down");
  }

  @override
  void onTapCancel() {
    print("tap cancel");
  }
}

And, I add PositionComponent to my game.

class GameController extends BaseGame with HasTapableComponents {
  Size screenSize;
  double tileSize;
  Player player;
  Enemy enemy;
  TapableComponent a;

  GameController() {
    initialize();
  }

  void initialize() async {
    resize(await Flame.util.initialDimensions());
    add(enemy = Enemy(200, 200));
  }

  @override
  void render(Canvas c) {
    Rect background = Rect.fromLTWH(0, 0, screenSize.width, screenSize.height);
    Paint backgroundPaint = Paint()..color = Color(0xFFFAFAFA);
    enemy.render(c);
  }

  @override
  void update(double t) {}

  @override
  void resize(Size size) {
    screenSize = size;
    tileSize = screenSize.width / 10;
  }
}

However, it's not working, am I missing something?


Solution

  • I think your example code is a mix between v1 code and 0.29.3, if you try with the latest release candidate of Flame: 1.0.0-rc8 then the following should work:

    class TapableSquare extends PositionComponent with Tapable {
      static final Paint _white = Paint()..color = const Color(0xFFFFFFFF);
      static final Paint _grey = Paint()..color = const Color(0xFFA5A5A5);
    
    
      TapableSquare({Vector2 position})
          : super(
              position: position ?? Vector2.all(100),
              size: Vector2.all(100),
            );
    
      @override
      void render(Canvas canvas) {
        super.render(canvas);
        canvas.drawRect(size.toRect());
      }
    
      @override
      bool onTapUp(TapUpDetails details) {...}
    
      @override
      bool onTapDown(TapDownDetails details) {...}
    
      @override
      bool onTapCancel() {...}
    }
    
    class TapablesGame extends BaseGame with HasTapableComponents {
      @override
      Future<void> onLoad() async {
        add(TapableSquare());
      }
    }
    

    Extracted from this example.

    EDIT: To make it work for 0.29.3 you should be setting position and size in your Enemy class instead of building your own rect, Tapable can't know about that rect.