Why onTap is not working in my flame game (Flutter)? - flutter

I am working on a simple game using Flame and Flutter. I am following this tutorial:
Create a Mobile Game with Flutter and Flame – Beginner Tutorial
But after I added some code following tutorial line:
flameUtil.addGestureRecognizer(tapper);
appears underlined and onTap function is not working.

API of flutter-flame library is constantly evolving and the solution from tutorial above might not work anymore.
I had some hard times to re-implement example from this presentation: https://www.youtube.com/watch?v=sFpjEH-ok2s, so you're not alone :-)
Newer versions of flutter-flame like 0.23.0, requires to make it work to add TapDetector mixin to your BaseGame class like below:
class MyBaseGame extends BaseGame with TapDetector, DoubleTapDetector {
#override
void onTapDown(_) {
add(RenderedTimeComponent(Timer(1)..start()));
}
#override
void onDoubleTap() {
add(RenderedTimeComponent(Timer(5)..start()));
}
}
Source: https://github.com/flame-engine/flame/blob/00ad86eb63aa54b411f1d080fec501dd7b671a81/doc/examples/timer/lib/main.dart
Thanks to this your code of BoxGame initialization is just:
BoxGame game = BoxGame();
runApp(game.widget);
without declarations of Util and TapGestureRecognizer.

You can use TapDetector mixin:
class WarriorGirlGame extends FlameGame with TapDetector {
#override
void onTapDown(TapDownInfo info) {
...
}
}

Related

why camera from my doc is different to the example

I followed a tutorial and code looks like this:
class MyGame extends Forge2DGame{
#override
Future<void> onLoad() async {
camera.toString(); // <= this camera is a Vector2
}
}
But what I learned from another tutorial is like this:
class SpacescapeGame extends FlameGame{
#override
Future<void> onLoad() async {
camera.shake(); // <= this camera is a Camera class
}
}
What I understand is Forge2DGame extends BaseGame, BaseGame extends FlameGame https://pub.dev/documentation/bonfire/latest/base_base_game/BaseGame-class.html
but why I cant use camera.shake as second tutorial showed? thank you for your explanation!
I recommend that you read the Flame documentation instead of the bonfire documentation if you want to write a Flame game that is not involving bonfire.
The camera for Forge2DGame is the same camera as is used for FlameGame, you have most likely added some other variable that is also called camera which is shadowing the real camera.
Also make sure that you are on the latest version of flame (1.4.0) and the latest version of flame_forge2d (0.12.3).

Flutter Flame: proper Viewport to match the screen size

How can I find out the screen size and place my game item according to screen resolution? I want to run my game on the web client.
I want to resize my red game component so fit in the screen and position in center.
LibGdx has some good java class for this concept: Link
You can use the FixedResolutionViewport and set it to the smallest edge if you always want it as a square:
class MyGame extends FlameGame {
Future<void> onLoad() async {
double maxSide = min(size.x, size.y);
camera.viewport = FixedResolutionViewport(Vector2.all(maxSide));
}
}
If you want the game's (viewport) size inside of another component you can add the HasGameRef mixin and use the game's size variable in the same way:
class MyComponent extends Component with HasGameRef {
MyComponent() : super(anchor: Anchor.center);
Future<void> onLoad() async {
final gameSize = gameRef.size;
// To add a position component in the center of the screen for example:
// (when the camera isn't moved)
position = gameSize/2;
}
}
If you want other sizes I recommend to look at game.camera and game.camera.viewport which offers a few other options too.

How to detect a swipe in a game with flutter/flame

I want to create a game in flutter with flame. For this game I want to detect swipes.
I could implement a tap recognition with the help of a tutorial. But I could not implement it with swipe detection.
my main with Taprecognition looks like this:
My main function is
void main() async{
Util flameUtil = Util();
await flameUtil.fullScreen();
await flameUtil.setOrientation(DeviceOrientation.portraitUp);
GameManager game = GameManager();
runApp(game.widget);
TapGestureRecognizer tapper = TapGestureRecognizer();
tapper.onTapDown = game.onTapDown;
flameUtil.addGestureRecognizer(tapper);
}
In my GameManager class I do have:
class GameMAnager extends Game{
// a few methods like update, render and constructor
void onTapDown(TapDownDetails d) {
if (bgRect.contains(d.globalPosition)) { //bgRect is the background rectangle, so the tap works on the whole screen
player.onTapDown();
}
}
And my player class contains:
void onTapDown(){
rotate();
}
Now I want to change this to rotate in the direction of the swipe instead of onTapDown.
I tried to somehow add
GestureDetector swiper = GestureDetector();
swiper.onPanUpdate = game.onPanUpdate;
to my main and
void onPanUpdate() {
}
to my gameManager class. But I cannot find anything similar to TapDownDetails for panning.
Any suggestions on this?
I saw some help for this to wrap the widget in a GestureDetector and use it like this:
GestureDetector(onPanUpdate: (details) {
if (details.delta.dx > 0) {
// swiping in right direction
}
});
But I couldn't make it work on my project.
You can use the HorizontalDragGestureDetector (or PanGestureRecognizer if you need both axes)
use the following in your main method
HorizontalDragGestureRecognizer tapper = HorizontalDragGestureRecognizer();
tapper.onUpdate = game.dragUpdate;
and then the following in your GameManager
void dragUpdate(DragUpdateDetails d) {
// using d.delta you can then track the movement and implement your rotation updade here
}
That should do the trick :D
If you need both axes, you can use PanGestureRecognizer (as #Marco Papula said).
Use this in your main method:
PanGestureRecognizer panGestureRecognizer = PanGestureRecognizer();
panGestureRecognizer.onEnd = game.onPanUpdate;
flameUtil.addGestureRecognizer(panGestureRecognizer);
and your onPanUpdate method:
void onPanUpdate(DragEndDeatils d) {
if(d.velocity.pixelsPerSecond.dx.abs()>d.velocity.pixelsPerSecond.dy.abs()) {
// X Axis
snake.velocity = d.velocity.pixelsPerSecond.dx<0 ? LeftSwipe : RightSwipe;
} else {
// Y Axis
snake.velocity = d.velocity.pixelsPerSecond.dy<0 ? UpSwipe : DownSwipe;
}
}
If you are using a newer (v1) version of Flame, you no longer need to wrap it in your own GestureDetector (thought you can). Now Flame has built in wrappers for all events, including panning! You can mix your game with:
class MyGame extends BaseGame with PanDetector {
// ...
}
And implement onPanUpdate to get the desired behaviour; or use a myriad of any other detectors (check the documentation for more options and details on how to use it).

Setting a textfield in a class in but displaying a number?

I'm learn as3, and building some exercises from the adobe online tutorials. I'm trying to do a very simple task and I think my code is exactly the same as the tutoriala nd it's not working! I just can't work it out...
I'm trying to change the textfield in a button from that buttons class.
The button is called GameButton, the textfield is called blabel and is classic text and dynamic text. Here is the code for the GameButton class. Instead of displaying "Click" as below it just changes the label to the number 1. The trace statement is working etc it is going there, but the text isn't passing through or something. Please help!!!
package {
import flash.display.MovieClip;
public class GameButton extends MovieClip {
public function GameButton() {
trace("Gamebutton has been created");
this.blabel.text = "Click";
stop();
}
}
}
The long and short of it is you can create the button in code, or else you can try listening for added to stage events coming from the parent object you're adding the children to (maybe the stage, maybe another DisplayObjectContainer). The problem with the listening method is I'm not sure how you would know which child just dispatched the event without making some messy code. I think the first option is generally easier and makes more sense, the only caveat is that you have to place the instances using x/y coordinates or apply scaleX, scaleY to stretch or shrink objects instead of doing it using the authoring tool. You can still use the drag and drop parts of flash to figure out coordinates and build individual movie clips etc.
Enough talk on to some code:
package
{
import flash.display.MovieClip;
public class GameButton extends MovieClip {
private var blabel:TextField; //This can be any display object class or a class that extends from a display object class (Sprite, MovieClip, MyCustomButton etc.)
public function GameButton() {
blabel = new TextField(); //The type after new, should be the same, or a sub-class (extension) of the type used in the variable declaration above
addChild(blabel);
//blabel.x=10; //optional over ten pixels from left
//blabel.y=10; //optional down ten pixels from top
//blabel.scaleX=.5; //optional half the width
//blabel.scaleY=2; //optional 2 times taller
trace("Gamebutton has been created");
blabel.text = "Click";
stop();
}
}
}

Android Frame animation does not proceed more than one image

I have created a folder called anim inside res folder. I have put 9 consequtive images in a folder called drawable inside res folder. Now I have created this:
public class AndroidAnimationActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.about_screen);
ImageView myAnimation = (ImageView)findViewById(R.id.myanimation);
final AnimationDrawable myAnimationDrawable= (AnimationDrawable)myAnimation.getDrawable();
myAnimation.post(new Runnable(){
public void run() {
myAnimationDrawable.start();
}
});
}
}
As you see I am trying to display this animation on a page called about_screen. It only shows the first frame and the rest of the frames are not shown (as animation). I have seen several people having similar problem like me but not exactly the same. I hope someone can help me with this. Please be specific. I am a new android learner. Thanks
Even I faced this problem, and the solution is simple.
The problem is, you are calling myAnimationDrawable.start() inside the onCreate() function.
You have two possible alternatives...
First one, make the animation interactive, so that you can call myAnimationDrawable.start()
inside some onClick() function.
Second option is to call myAnimationDrawable.start() inside View.OnFocusChangeListener(). In this case you don't have to make it interactive.