Search code examples
fluttergame-engineflame

Flutter Flame SpriteComponent with Tapable does not recognize onTapDown Method


I am creating some UI buttons for a menu in flame. The button itself is able to render just fine apart from changing sprites on the onTapDown event. After adding the class to the basegame component, the application is unable to find the ontapdown event. I only receive the error 'NoSuchMethod'.

EDIT: I'm using flame releasecandidate.11 and flame audio rc.1. The full error message is:

The following NoSuchMethodError was thrown while handling a gesture:
The method '+' was called on null.
Receiver: null
Tried calling: +(Instance of 'Vector2')

When the exception was thrown, this was the stack: 
#0      Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
#1      Anchor.toOtherAnchorPosition (package:flame/src/anchor.dart:61:23)
#2      PositionComponent.topLeftPosition (package:flame/src/components/position_component.dart:57:19)
#3      PositionComponent.absoluteTopLeftPosition (package:flame/src/components/position_component.dart:75:14)
#4      PositionComponent.toAbsoluteRect (package:flame/src/components/position_component.dart:125:28)
...
Handler: "onTapDown"
Recognizer: MultiTapGestureRecognizer#13ffa
class ScrollGame extends BaseGame with HasTapableComponents {
  @override
  Future<void> onLoad() async {

    // Buttons
    add(StartButton(Vector2(canvasSize.x/2, canvasSize.y/2)));
  }
}

class StartButton extends PositionComponent with Tapable {
  bool isDown = false;
  Sprite untappedSpr;
  Sprite tappedSpr;
  Vector2 position;

  StartButton(Vector2 position) : super(position: position);

  @override
  Future<void> onLoad() async {
    final untapped = await Flame.images.load('Untapped.png');
    final tapped = await Flame.images.load('Tapped.png');

    untappedSpr = Sprite(untapped);
    tappedSpr = Sprite(tapped);

    this.size = Vector2(80, 25);
    this.position = position;
    this.anchor = Anchor.center;
  }

  @override
  void render(Canvas canvas) {
    super.render(canvas);
    final buttonSpr = isDown ? tappedSpr : untappedSpr;
    buttonSpr.render(canvas);
  }

  @override
  bool onTapUp(_) {
    isDown = false;
    return true;
  }

  @override
  bool onTapDown(_) {
    isDown = true;
    return true;
  }
}

Solution

  • You have defined position in your StartButton component, position is already defined in PositionComponent. Simply remove the definition:

    Vector2 position;
    

    and the line where you set it (this.position = position;), since it is already set when you pass it to super with super(position: position).