mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-01 10:38:17 +08:00
Adding images on Game, auto clear on game detach, fixing some examples
This commit is contained in:
@ -5,14 +5,16 @@ import 'package:flame/components/sprite_component.dart';
|
|||||||
import 'package:flame/components/mixins/resizable.dart';
|
import 'package:flame/components/mixins/resizable.dart';
|
||||||
import 'package:flame/text_config.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 {
|
void main() async {
|
||||||
|
Flame.initializeWidget();
|
||||||
await Flame.util.initialDimensions();
|
await Flame.util.initialDimensions();
|
||||||
|
|
||||||
final myGame = MyGame();
|
final myGame = MyGame();
|
||||||
runApp(myGame.widget);
|
runApp(myGame.widget);
|
||||||
myGame.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class AndroidComponent extends SpriteComponent with Resizable {
|
class AndroidComponent extends SpriteComponent with Resizable {
|
||||||
@ -20,7 +22,7 @@ class AndroidComponent extends SpriteComponent with Resizable {
|
|||||||
int xDirection = 1;
|
int xDirection = 1;
|
||||||
int yDirection = 1;
|
int yDirection = 1;
|
||||||
|
|
||||||
AndroidComponent() : super.square(100, 'android.png');
|
AndroidComponent(Image image) : super.square(100, image);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void update(double dt) {
|
void update(double dt) {
|
||||||
@ -56,17 +58,20 @@ class MyGame extends BaseGame {
|
|||||||
@override
|
@override
|
||||||
bool recordFps() => true;
|
bool recordFps() => true;
|
||||||
|
|
||||||
void start() {
|
@override
|
||||||
final android = AndroidComponent();
|
Future<void> onLoad() async {
|
||||||
|
final androidImage = await images.load('android.png');
|
||||||
|
|
||||||
|
final android = AndroidComponent(androidImage);
|
||||||
android.x = 100;
|
android.x = 100;
|
||||||
android.y = 400;
|
android.y = 400;
|
||||||
|
|
||||||
final android2 = AndroidComponent();
|
final android2 = AndroidComponent(androidImage);
|
||||||
android2.x = 100;
|
android2.x = 100;
|
||||||
android2.y = 400;
|
android2.y = 400;
|
||||||
android2.yDirection = -1;
|
android2.yDirection = -1;
|
||||||
|
|
||||||
final android3 = AndroidComponent();
|
final android3 = AndroidComponent(androidImage);
|
||||||
android3.x = 100;
|
android3.x = 100;
|
||||||
android3.y = 400;
|
android3.y = 400;
|
||||||
android3.xDirection = -1;
|
android3.xDirection = -1;
|
||||||
|
|||||||
@ -7,15 +7,11 @@ import 'package:flame/flame.dart';
|
|||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
Flame.initializeWidget();
|
||||||
|
|
||||||
await Flame.util.fullScreen();
|
await Flame.util.fullScreen();
|
||||||
|
|
||||||
final playerSprite = await Sprite.loadSprite('player.png');
|
runApp(LayerGame().widget);
|
||||||
final enemySprite = await Sprite.loadSprite('enemy.png');
|
|
||||||
final backgroundSprite = await Sprite.loadSprite('background.png');
|
|
||||||
|
|
||||||
runApp(LayerGame(playerSprite, enemySprite, backgroundSprite).widget);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class GameLayer extends DynamicLayer {
|
class GameLayer extends DynamicLayer {
|
||||||
@ -56,14 +52,15 @@ class BackgroundLayer extends PreRenderedLayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class LayerGame extends Game {
|
class LayerGame extends Game {
|
||||||
Sprite playerSprite;
|
|
||||||
Sprite enemySprite;
|
|
||||||
Sprite backgroundSprite;
|
|
||||||
|
|
||||||
Layer gameLayer;
|
Layer gameLayer;
|
||||||
Layer backgroundLayer;
|
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);
|
gameLayer = GameLayer(playerSprite, enemySprite);
|
||||||
backgroundLayer = BackgroundLayer(backgroundSprite);
|
backgroundLayer = BackgroundLayer(backgroundSprite);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,8 +17,11 @@ class MyGame extends Game {
|
|||||||
Size size;
|
Size size;
|
||||||
NineTileBox nineTileBox;
|
NineTileBox nineTileBox;
|
||||||
|
|
||||||
MyGame(this.size) {
|
MyGame(this.size);
|
||||||
final sprite = Sprite('nine-box.png');
|
|
||||||
|
@override
|
||||||
|
Future<void> onLoad() async {
|
||||||
|
final sprite = Sprite(await images.load('nine-box.png'));
|
||||||
nineTileBox = NineTileBox(sprite, tileSize: 8, destTileSize: 24);
|
nineTileBox = NineTileBox(sprite, tileSize: 8, destTileSize: 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -65,6 +65,12 @@ class MyGame extends BaseGame {
|
|||||||
Timer.periodic(sceneDuration, (_) => spawnParticles());
|
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]
|
/// Showcases various different uses of [Particle]
|
||||||
/// and its derivatives
|
/// and its derivatives
|
||||||
void spawnParticles() {
|
void spawnParticles() {
|
||||||
@ -295,7 +301,7 @@ class MyGame extends BaseGame {
|
|||||||
Particle imageParticle() {
|
Particle imageParticle() {
|
||||||
return ImageParticle(
|
return ImageParticle(
|
||||||
size: const Size.square(24),
|
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.
|
/// Flame's [Sprite] into the effect.
|
||||||
Particle spriteParticle() {
|
Particle spriteParticle() {
|
||||||
return SpriteParticle(
|
return SpriteParticle(
|
||||||
sprite: Sprite('zap.png'),
|
sprite: Sprite(images.fromCache('zap.png')),
|
||||||
size: Position.fromOffset(cellSize * .5),
|
size: Position.fromOffset(cellSize * .5),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -524,12 +530,11 @@ class MyGame extends BaseGame {
|
|||||||
const columns = 8;
|
const columns = 8;
|
||||||
const rows = 8;
|
const rows = 8;
|
||||||
const frames = columns * rows;
|
const frames = columns * rows;
|
||||||
const imagePath = 'boom3.png';
|
final spriteImage = images.fromCache('boom3.png');
|
||||||
final spriteImage = Flame.images.loadedFiles[imagePath].loadedImage;
|
|
||||||
final spritesheet = SpriteSheet(
|
final spritesheet = SpriteSheet(
|
||||||
rows: rows,
|
rows: rows,
|
||||||
columns: columns,
|
columns: columns,
|
||||||
imageName: imagePath,
|
image: spriteImage,
|
||||||
textureWidth: spriteImage.width ~/ columns,
|
textureWidth: spriteImage.width ~/ columns,
|
||||||
textureHeight: spriteImage.height ~/ rows,
|
textureHeight: spriteImage.height ~/ rows,
|
||||||
);
|
);
|
||||||
@ -543,19 +548,8 @@ class MyGame extends BaseGame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<BaseGame> loadGame() async {
|
Future<BaseGame> loadGame() async {
|
||||||
Size gameSize;
|
Flame.initializeWidget();
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
final gameSize = await Flame.util.initialDimensions();
|
||||||
|
|
||||||
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',
|
|
||||||
]),
|
|
||||||
]);
|
|
||||||
|
|
||||||
return MyGame(screenSize: gameSize);
|
return MyGame(screenSize: gameSize);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,14 +6,21 @@ import 'dart:convert' show base64;
|
|||||||
import 'package:flame/flame.dart';
|
import 'package:flame/flame.dart';
|
||||||
|
|
||||||
class Images {
|
class Images {
|
||||||
Map<String, ImageAssetLoader> loadedFiles = {};
|
final Map<String, _ImageAssetLoader> _loadedFiles = {};
|
||||||
|
|
||||||
void clear(String fileName) {
|
void clear(String fileName) {
|
||||||
loadedFiles.remove(fileName);
|
_loadedFiles.remove(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearCache() {
|
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 {
|
Future<List<Image>> loadAll(List<String> fileNames) async {
|
||||||
@ -21,17 +28,17 @@ class Images {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<Image> load(String fileName) async {
|
Future<Image> load(String fileName) async {
|
||||||
if (!loadedFiles.containsKey(fileName)) {
|
if (!_loadedFiles.containsKey(fileName)) {
|
||||||
loadedFiles[fileName] = ImageAssetLoader(_fetchToMemory(fileName));
|
_loadedFiles[fileName] = _ImageAssetLoader(_fetchToMemory(fileName));
|
||||||
}
|
}
|
||||||
return await loadedFiles[fileName].retreive();
|
return await _loadedFiles[fileName].retreive();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Image> fromBase64(String fileName, String base64) async {
|
Future<Image> fromBase64(String fileName, String base64) async {
|
||||||
if (!loadedFiles.containsKey(fileName)) {
|
if (!_loadedFiles.containsKey(fileName)) {
|
||||||
loadedFiles[fileName] = ImageAssetLoader(_fetchFromBase64(base64));
|
_loadedFiles[fileName] = _ImageAssetLoader(_fetchFromBase64(base64));
|
||||||
}
|
}
|
||||||
return await loadedFiles[fileName].retreive();
|
return await _loadedFiles[fileName].retreive();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Image> _fetchFromBase64(String base64Data) async {
|
Future<Image> _fetchFromBase64(String base64Data) async {
|
||||||
@ -53,8 +60,8 @@ class Images {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImageAssetLoader {
|
class _ImageAssetLoader {
|
||||||
ImageAssetLoader(this.future);
|
_ImageAssetLoader(this.future);
|
||||||
|
|
||||||
Image loadedImage;
|
Image loadedImage;
|
||||||
Future<Image> future;
|
Future<Image> future;
|
||||||
@ -6,7 +6,7 @@ import 'package:flutter/widgets.dart';
|
|||||||
|
|
||||||
import 'flame_audio.dart';
|
import 'flame_audio.dart';
|
||||||
import 'bgm.dart';
|
import 'bgm.dart';
|
||||||
import 'images.dart';
|
import 'assets/images.dart';
|
||||||
import 'assets_cache.dart';
|
import 'assets_cache.dart';
|
||||||
import 'util.dart';
|
import 'util.dart';
|
||||||
|
|
||||||
|
|||||||
@ -7,10 +7,11 @@ import 'package:flutter/widgets.dart' hide WidgetBuilder;
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
import '../keyboard.dart';
|
|
||||||
|
|
||||||
import 'widget_builder.dart';
|
import 'widget_builder.dart';
|
||||||
|
|
||||||
|
import '../keyboard.dart';
|
||||||
|
import '../assets/images.dart';
|
||||||
|
|
||||||
/// Represents a generic game.
|
/// Represents a generic game.
|
||||||
///
|
///
|
||||||
/// Subclass this to implement the [update] and [render] methods.
|
/// Subclass this to implement the [update] and [render] methods.
|
||||||
@ -19,6 +20,8 @@ abstract class Game {
|
|||||||
// Widget Builder for this Game
|
// Widget Builder for this Game
|
||||||
final builder = WidgetBuilder();
|
final builder = WidgetBuilder();
|
||||||
|
|
||||||
|
final images = Images();
|
||||||
|
|
||||||
/// Returns the game background color.
|
/// Returns the game background color.
|
||||||
/// By default it will return a black 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.
|
/// 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) {
|
if (this is KeyboardEvents) {
|
||||||
RawKeyboard.instance.removeListener(_handleKeyEvent);
|
RawKeyboard.instance.removeListener(_handleKeyEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
images.clearCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flag to tell the game loop if it should start running upon creation
|
/// Flag to tell the game loop if it should start running upon creation
|
||||||
|
|||||||
@ -14,38 +14,6 @@ class SpriteSheet {
|
|||||||
List<List<Sprite>> _sprites;
|
List<List<Sprite>> _sprites;
|
||||||
|
|
||||||
SpriteSheet({
|
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 Image image,
|
||||||
@required this.textureWidth,
|
@required this.textureWidth,
|
||||||
@required this.textureHeight,
|
@required this.textureHeight,
|
||||||
@ -56,19 +24,19 @@ class SpriteSheet {
|
|||||||
rows,
|
rows,
|
||||||
(y) => List.generate(
|
(y) => List.generate(
|
||||||
columns,
|
columns,
|
||||||
(x) => _mapImage(image, textureWidth, textureHeight, x, y),
|
(x) => _mapImagePath(image, textureWidth, textureHeight, x, y),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Sprite _mapImage(
|
Sprite _mapImagePath(
|
||||||
Image image,
|
Image image,
|
||||||
int textureWidth,
|
int textureWidth,
|
||||||
int textureHeight,
|
int textureHeight,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
) {
|
) {
|
||||||
return Sprite.fromImage(
|
return Sprite(
|
||||||
image,
|
image,
|
||||||
x: (x * textureWidth).toDouble(),
|
x: (x * textureWidth).toDouble(),
|
||||||
y: (y * textureHeight).toDouble(),
|
y: (y * textureHeight).toDouble(),
|
||||||
|
|||||||
Reference in New Issue
Block a user