Adding images on Game, auto clear on game detach, fixing some examples

This commit is contained in:
Erick Zanardo
2020-09-23 22:21:56 -03:00
parent 585b440d0b
commit 2ea5001506
8 changed files with 66 additions and 87 deletions

View File

@ -5,14 +5,16 @@ import 'package:flame/components/sprite_component.dart';
import 'package:flame/components/mixins/resizable.dart';
import 'package:flame/text_config.dart';
import 'package:flutter/material.dart';
import 'package:flutter/material.dart' hide Image;
import 'dart:ui';
void main() async {
Flame.initializeWidget();
await Flame.util.initialDimensions();
final myGame = MyGame();
runApp(myGame.widget);
myGame.start();
}
class AndroidComponent extends SpriteComponent with Resizable {
@ -20,7 +22,7 @@ class AndroidComponent extends SpriteComponent with Resizable {
int xDirection = 1;
int yDirection = 1;
AndroidComponent() : super.square(100, 'android.png');
AndroidComponent(Image image) : super.square(100, image);
@override
void update(double dt) {
@ -56,17 +58,20 @@ class MyGame extends BaseGame {
@override
bool recordFps() => true;
void start() {
final android = AndroidComponent();
@override
Future<void> onLoad() async {
final androidImage = await images.load('android.png');
final android = AndroidComponent(androidImage);
android.x = 100;
android.y = 400;
final android2 = AndroidComponent();
final android2 = AndroidComponent(androidImage);
android2.x = 100;
android2.y = 400;
android2.yDirection = -1;
final android3 = AndroidComponent();
final android3 = AndroidComponent(androidImage);
android3.x = 100;
android3.y = 400;
android3.xDirection = -1;

View File

@ -7,15 +7,11 @@ import 'package:flame/flame.dart';
import 'dart:ui';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
Flame.initializeWidget();
await Flame.util.fullScreen();
final playerSprite = await Sprite.loadSprite('player.png');
final enemySprite = await Sprite.loadSprite('enemy.png');
final backgroundSprite = await Sprite.loadSprite('background.png');
runApp(LayerGame(playerSprite, enemySprite, backgroundSprite).widget);
runApp(LayerGame().widget);
}
class GameLayer extends DynamicLayer {
@ -56,14 +52,15 @@ class BackgroundLayer extends PreRenderedLayer {
}
class LayerGame extends Game {
Sprite playerSprite;
Sprite enemySprite;
Sprite backgroundSprite;
Layer gameLayer;
Layer backgroundLayer;
LayerGame(this.playerSprite, this.enemySprite, this.backgroundSprite) {
@override
Future<void> onLoad() async {
final playerSprite = Sprite(await images.load('player.png'));
final enemySprite = Sprite(await images.load('enemy.png'));
final backgroundSprite = Sprite(await images.load('background.png'));
gameLayer = GameLayer(playerSprite, enemySprite);
backgroundLayer = BackgroundLayer(backgroundSprite);
}

View File

@ -17,8 +17,11 @@ class MyGame extends Game {
Size size;
NineTileBox nineTileBox;
MyGame(this.size) {
final sprite = Sprite('nine-box.png');
MyGame(this.size);
@override
Future<void> onLoad() async {
final sprite = Sprite(await images.load('nine-box.png'));
nineTileBox = NineTileBox(sprite, tileSize: 8, destTileSize: 24);
}

View File

@ -65,6 +65,12 @@ class MyGame extends BaseGame {
Timer.periodic(sceneDuration, (_) => spawnParticles());
}
@override
Future<void> onLoad() async {
await images.load('zap.png');
await images.load('boom3.png');
}
/// Showcases various different uses of [Particle]
/// and its derivatives
void spawnParticles() {
@ -295,7 +301,7 @@ class MyGame extends BaseGame {
Particle imageParticle() {
return ImageParticle(
size: const Size.square(24),
image: Flame.images.loadedFiles['zap.png'].loadedImage,
image: images.fromCache('zap.png'),
);
}
@ -385,7 +391,7 @@ class MyGame extends BaseGame {
/// Flame's [Sprite] into the effect.
Particle spriteParticle() {
return SpriteParticle(
sprite: Sprite('zap.png'),
sprite: Sprite(images.fromCache('zap.png')),
size: Position.fromOffset(cellSize * .5),
);
}
@ -524,12 +530,11 @@ class MyGame extends BaseGame {
const columns = 8;
const rows = 8;
const frames = columns * rows;
const imagePath = 'boom3.png';
final spriteImage = Flame.images.loadedFiles[imagePath].loadedImage;
final spriteImage = images.fromCache('boom3.png');
final spritesheet = SpriteSheet(
rows: rows,
columns: columns,
imageName: imagePath,
image: spriteImage,
textureWidth: spriteImage.width ~/ columns,
textureHeight: spriteImage.height ~/ rows,
);
@ -543,19 +548,8 @@ class MyGame extends BaseGame {
}
Future<BaseGame> loadGame() async {
Size gameSize;
WidgetsFlutterBinding.ensureInitialized();
await Future.wait([
Flame.util.initialDimensions().then((size) => gameSize = size),
Flame.images.loadAll(const [
'zap.png',
/// Credits to Stumpy Strust from
/// https://opengameart.org/content/explosion-sheet
'boom3.png',
]),
]);
Flame.initializeWidget();
final gameSize = await Flame.util.initialDimensions();
return MyGame(screenSize: gameSize);
}

View File

@ -6,14 +6,21 @@ import 'dart:convert' show base64;
import 'package:flame/flame.dart';
class Images {
Map<String, ImageAssetLoader> loadedFiles = {};
final Map<String, _ImageAssetLoader> _loadedFiles = {};
void clear(String fileName) {
loadedFiles.remove(fileName);
_loadedFiles.remove(fileName);
}
void clearCache() {
loadedFiles.clear();
_loadedFiles.clear();
}
Image fromCache(String fileName) {
final image = _loadedFiles[fileName];
assert(image?.loadedImage != null,
'Tried to access an inexistent entry on cache "$fileName"');
return image.loadedImage;
}
Future<List<Image>> loadAll(List<String> fileNames) async {
@ -21,17 +28,17 @@ class Images {
}
Future<Image> load(String fileName) async {
if (!loadedFiles.containsKey(fileName)) {
loadedFiles[fileName] = ImageAssetLoader(_fetchToMemory(fileName));
if (!_loadedFiles.containsKey(fileName)) {
_loadedFiles[fileName] = _ImageAssetLoader(_fetchToMemory(fileName));
}
return await loadedFiles[fileName].retreive();
return await _loadedFiles[fileName].retreive();
}
Future<Image> fromBase64(String fileName, String base64) async {
if (!loadedFiles.containsKey(fileName)) {
loadedFiles[fileName] = ImageAssetLoader(_fetchFromBase64(base64));
if (!_loadedFiles.containsKey(fileName)) {
_loadedFiles[fileName] = _ImageAssetLoader(_fetchFromBase64(base64));
}
return await loadedFiles[fileName].retreive();
return await _loadedFiles[fileName].retreive();
}
Future<Image> _fetchFromBase64(String base64Data) async {
@ -53,8 +60,8 @@ class Images {
}
}
class ImageAssetLoader {
ImageAssetLoader(this.future);
class _ImageAssetLoader {
_ImageAssetLoader(this.future);
Image loadedImage;
Future<Image> future;

View File

@ -6,7 +6,7 @@ import 'package:flutter/widgets.dart';
import 'flame_audio.dart';
import 'bgm.dart';
import 'images.dart';
import 'assets/images.dart';
import 'assets_cache.dart';
import 'util.dart';

View File

@ -7,10 +7,11 @@ import 'package:flutter/widgets.dart' hide WidgetBuilder;
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import '../keyboard.dart';
import 'widget_builder.dart';
import '../keyboard.dart';
import '../assets/images.dart';
/// Represents a generic game.
///
/// Subclass this to implement the [update] and [render] methods.
@ -19,6 +20,8 @@ abstract class Game {
// Widget Builder for this Game
final builder = WidgetBuilder();
final images = Images();
/// Returns the game background color.
/// By default it will return a black color.
/// It cannot be changed at runtime, because the game widget does not get rebuild when this value changes.
@ -78,6 +81,8 @@ abstract class Game {
if (this is KeyboardEvents) {
RawKeyboard.instance.removeListener(_handleKeyEvent);
}
images.clearCache();
}
/// Flag to tell the game loop if it should start running upon creation

View File

@ -14,38 +14,6 @@ class SpriteSheet {
List<List<Sprite>> _sprites;
SpriteSheet({
@required String imageName,
@required this.textureWidth,
@required this.textureHeight,
@required this.columns,
@required this.rows,
}) {
_sprites = List.generate(
rows,
(y) => List.generate(
columns,
(x) => _mapImagePath(imageName, textureWidth, textureHeight, x, y),
),
);
}
Sprite _mapImagePath(
String imageName,
int textureWidth,
int textureHeight,
int x,
int y,
) {
return Sprite(
imageName,
x: (x * textureWidth).toDouble(),
y: (y * textureHeight).toDouble(),
width: textureWidth.toDouble(),
height: textureHeight.toDouble(),
);
}
SpriteSheet.fromImage({
@required Image image,
@required this.textureWidth,
@required this.textureHeight,
@ -56,19 +24,19 @@ class SpriteSheet {
rows,
(y) => List.generate(
columns,
(x) => _mapImage(image, textureWidth, textureHeight, x, y),
(x) => _mapImagePath(image, textureWidth, textureHeight, x, y),
),
);
}
Sprite _mapImage(
Sprite _mapImagePath(
Image image,
int textureWidth,
int textureHeight,
int x,
int y,
) {
return Sprite.fromImage(
return Sprite(
image,
x: (x * textureWidth).toDouble(),
y: (y * textureHeight).toDouble(),