Home > Blockchain >  Sprite not showing up in flutter application using flame
Sprite not showing up in flutter application using flame

Time:11-06

I am following the flame tutorial for flutter here and was able to get my code to compile and run on a simulator (both iOS and chrome) however nothing appears when the app runs. I assume that an image of my crate.png should show up but all I see is a black screen.

Here is my main.dart:

import 'dart:math' as math;
import 'dart:ui';

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

class MyCrate extends SpriteComponent {
  // creates a component that renders the crate.png sprite, with size 16 x 16
  MyCrate() : super(size: Vector2.all(16));

  Future<void> onl oad() async {
    sprite = await Sprite.load('crate.png');
    anchor = Anchor.center;
  }

  @override
  void onGameResize(Vector2 gameSize) {
    // We don't need to set the position in the constructor, we can it directly here since it will
    // be called once before the first time it is rendered.
    position = gameSize / 2;
  }
}

class MyGame extends FlameGame {
  MyGame() {
    add(MyCrate());
  }
}

main() {
  final myGame = MyGame();
  runApp(
    GameWidget(
      game: myGame,
    ),
  );
}

and here is my pubspec.yaml:

name: boxgame
description: A new Flutter project.

publish_to: 'none'

version: 1.0.0 1

environment:
  sdk: ">=2.12.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^1.0.2
  flame: ^1.0.0-releasecandidate.16
  dashbook: ^0.1.5

dev_dependencies:
  flutter_test:
    sdk: flutter

  flutter_lints: ^1.0.0

flutter:

  # To add assets to your application, add an assets section, like this:
  assets:
    - assets/images/crate.png

I created my assets folder in the project root directory and placed it in a folder called images.

Edit

I just realized there is some error output:

Error: Assertion failed:
../…/components/component.dart:323
parentGame.hasLayout
"\"prepare/add\" called before the game is ready. Did you try to access it on the Game constructor? Use the \"onLoad\" ot \"onParentMethod\" method instead."
    at Object.throw_ [as throw] (http://localhost:53993/dart_sdk.js:5083:11)
    at Object.assertFailed (http://localhost:53993/dart_sdk.js:5008:15)
at main.MyCrate.new.prepare (http://localhost:53993/packages/flame/src/game/mixins/fps_counter.dart.lib.js:2509:41)
at component_set.ComponentSet.new.addChild (http://localhost:53993/packages/flame/src/game/mixins/fps_counter.dart.lib.js:7041:19)
    at addChild.next (<anonymous>)
    at runBody (http://localhost:53993/dart_sdk.js:40127:34)
    at Object._async [as async] (http://localhost:53993/dart_sdk.js:40158:7)
at component_set.ComponentSet.new.addChild (http://localhost:53993/packages/flame/src/game/mixins/fps_counter.dart.lib.js:7040:20)
at main.MyGame.new.add (http://localhost:53993/packages/flame/src/game/mixins/fps_counter.dart.lib.js:2453:28)
at new main.MyGame.new (http://localhost:53993/packages/boxgame/main.dart.lib.js:74:10)
at main$ (http://localhost:53993/packages/boxgame/main.dart.lib.js:84:18)
at main (http://localhost:53993/web_entrypoint.dart.lib.js:36:29)
    at main.next (<anonymous>)
    at http://localhost:53993/dart_sdk.js:40108:33
    at _RootZone.runUnary (http://localhost:53993/dart_sdk.js:39979:59)
    at _FutureListener.thenAwait.handleValue (http://localhost:53993/dart_sdk.js:34926:29)
    at handleValueCallback (http://localhost:53993/dart_sdk.js:35493:49)
    at Function._propagateToListeners (http://localhost:53993/dart_sdk.js:35531:17)
    at _Future.new.[_completeWithValue] (http://localhost:53993/dart_sdk.js:35379:23)
    at http://localhost:53993/dart_sdk.js:34563:46
    at _RootZone.runUnary (http://localhost:53993/dart_sdk.js:39979:59)
    at _FutureListener.then.handleValue (http://localhost:53993/dart_sdk.js:34926:29)
    at handleValueCallback (http://localhost:53993/dart_sdk.js:35493:49)
    at Function._propagateToListeners (http://localhost:53993/dart_sdk.js:35531:17)
    at _Future.new.[_completeWithValue] (http://localhost:53993/dart_sdk.js:35379:23)
    at async._AsyncCallbackEntry.new.callback (http://localhost:53993/dart_sdk.js:35400:35)
    at Object._microtaskLoop (http://localhost:53993/dart_sdk.js:40246:13)
    at _startMicrotaskLoop (http://localhost:53993/dart_sdk.js:40252:13)
    at http://localhost:53993/dart_sdk.js:35751:9

I tried running on load before calling add but I got the same error:

class MyGame extends FlameGame {
  MyGame() {
    MyCrate crate = MyCrate();
    crate.onLoad();
    add(crate);
  }
}

CodePudding user response:

You should fix address of assets. Check below sample :

  Future<void> onl oad() async {
        sprite = await Sprite.load('assets/images/crate.png');
        anchor = Anchor.center;
      }

CodePudding user response:

I am not sure why this worked but the following made the image show up:

class MyGame extends FlameGame {
  late final SpriteComponent player;

  @override
  Future<void> onl oad() async {
    final sprite = await Sprite.load('crate.png');
    final size = Vector2.all(16.0);
    final player = SpriteComponent(size: size, sprite: sprite);

    // screen coordinates
    player.position = Vector2(0.0, 0.0);
    player.angle = 0; // 0 by default, can also be set in the constructor
    add(player); // Adds the component
  }
}

main() {
  final myGame = MyGame();
  runApp(
    GameWidget(
      game: myGame,
    ),
  );
}

CodePudding user response:

The solution that you found works fine, if you want to fix the original code you have to follow the slightly cryptic message in the stack trace:

"prepare/add" called before the game is ready. Did you try to access it on the Game constructor? Use the "onLoad" or "onMount" method instead.

Which means that you have to move the adding of the components to onLoad instead of having them in the game constructor like you do now. So it would look like this:

class MyCrate extends SpriteComponent {
  // creates a component that renders the crate.png sprite, with size 16 x 16
  MyCrate() : super(size: Vector2.all(16));

  Future<void> onl oad() async {
    sprite = await Sprite.load('crate.png');
    anchor = Anchor.center;
  }

  @override
  void onGameResize(Vector2 gameSize) {
    // We don't need to set the position in the constructor, we can it directly here since it will
    // be called once before the first time it is rendered.
    position = gameSize / 2;
  }
}

class MyGame extends FlameGame {
  Future<void> onl oad() async {
    await super.onLoad();
    add(MyCrate());
  }
}

main() {
  final myGame = MyGame();
  runApp(
    GameWidget(
      game: myGame,
    ),
  );
}
  • Related