v0.2.0, audio loop and rectangle textures

This commit is contained in:
Luan Nico
2017-10-22 13:44:06 -02:00
parent 58ed937d61
commit 37252b8159
6 changed files with 62 additions and 18 deletions

View File

@ -1,2 +1,6 @@
## [0.2.0]
- Added a loop method for playing audio on loop
- Added the option to make rectangular SpriteComponents, not just squares
## [0.1.0] ## [0.1.0]
- First release, basic utilities - First release, basic utilities

View File

@ -4,7 +4,7 @@ A minimalist Flutter game engine.
## WIP ## WIP
Audio doesn't work on iOS; the rest should (not tested). Audio does not work on iOS; the rest should (not tested).
Help is appreciated, check the Audio section for more details. Help is appreciated, check the Audio section for more details.
@ -90,7 +90,19 @@ You must have an appropriate folder structure and add the files to the `pubspec.
It has to be an MP3 file. It has to be an MP3 file.
This uses the [audioplayers](https://github.com/luanpotter/audioplayer) lib, in order to allow playing multiple sounds simultaneously (crucial in a game). This uses the [audioplayers](https://github.com/luanpotter/audioplayer) lib, in order to allow playing multiple sounds simultaneously (crucial in a game).
Therefore, it doesn't work on iOS yet; check their README for more details on that. Therefore, it does not work on iOS yet; check their README for more details on that.
If you want to play indefinitely, just use loop:
```
Flame.audio.loop('music.mp3');
```
Beware: in order to use loop or any platform binding callbacks, you need to call this utility function first thing on your application code:
```
Flame.util.enableEvents();
```
### Images ### Images
@ -112,13 +124,14 @@ Just use:
canvas.drawImageRect(image, rect, rect, paint); canvas.drawImageRect(image, rect, rect, paint);
}); });
``` ```
Similarly to Audio, you can instantiate your own copy of Image: Similarly to Audio, you can instantiate your own copy of Image:
``` ```
Image image = await new Images().load('asd'); Image image = await new Images().load('asd');
``` ```
If you are using the Component module, you probably shouldn't use this one; use SpriteComponent instead! If you are using the Component module, you probably should not use this one; use SpriteComponent instead!
You must have an appropriate folder structure and add the files to the `pubspec.yaml` file, as explained above. You must have an appropriate folder structure and add the files to the `pubspec.yaml` file, as explained above.
@ -137,7 +150,7 @@ But you can use the default implementation, `SpriteComponent`, which makes rende
const size = 128.0; // size that will be drawn on the screen const size = 128.0; // size that will be drawn on the screen
// it will resize the image according // it will resize the image according
SpriteComponent player = new SpriteComponent(size, 'player.png'); SpriteComponent player = new SpriteComponent.square(size, 'player.png');
// the image sprite will be loaded by the Images module // the image sprite will be loaded by the Images module
// screen coordinates // screen coordinates
@ -149,6 +162,12 @@ But you can use the default implementation, `SpriteComponent`, which makes rende
player.render(canvas); // it will render if the image is ready player.render(canvas); // it will render if the image is ready
``` ```
You can also use the rectangle constructor if you want a non-square sprite:
```
var object = new SpriteComponent.rectangle(width, height, imagePath);
```
### Game Loop ### Game Loop
The Game Loop module is a simple abstraction over the game loop concept. The Game Loop module is a simple abstraction over the game loop concept.
@ -163,11 +182,11 @@ Extend the abstract class Game and just implement render and update; they will b
List<Component> objs = new List(); List<Component> objs = new List();
update(double t) { update(double t) {
components.forEach((Component obj) { obj.update(t); }); components.forEach((Component obj) => obj.update(t));
} }
render(Canvas canvas) { render(Canvas canvas) {
components.forEach((Component obj) { obj.render(canvas); }); components.forEach((Component obj) => obj.render(canvas));
} }
} }
@ -182,9 +201,10 @@ The update method receives the delta time in milliseconds since last update and
### Util ### Util
This module will incorporate a few utility functions that are good to have in any game environment. For now, there is only one: This module will incorporate a few utility functions that are good to have in any game environment. For now, there is only two:
* initialDimensions : returns a Future with the dimension (Size) of the screen. This has to be done in a hacky way because of the reasons described in the code. * initialDimensions : returns a Future with the dimension (Size) of the screen. This has to be done in a hacky way because of the reasons described in the code.
* enableEvents : this is also a hack that allows you to use the Service bindings with platform specific code callbacks. Normally they would only work if you called runApp with a widget, since we draw on canvas for the game, that's never called. This makes sure it works.
Ideas are appreciated! Ideas are appreciated!

View File

@ -8,7 +8,6 @@ import 'package:audioplayers/audioplayer.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
class Audio { class Audio {
Map<String, File> loadedFiles = new Map(); Map<String, File> loadedFiles = new Map();
Future<ByteData> _loadAsset(String fileName) async { Future<ByteData> _loadAsset(String fileName) async {
@ -21,10 +20,21 @@ class Audio {
} }
Future<int> play(String fileName) async { Future<int> play(String fileName) async {
File file = await assertLoaded(fileName);
return await new AudioPlayer().play(file.path, isLocal: true);
}
Future<int> loop(String fileName) async {
File file = await assertLoaded(fileName);
AudioPlayer player = new AudioPlayer();
player.setCompletionHandler(() => player.play(file.path, isLocal: true));
return await player.play(file.path, isLocal: true);
}
Future<File> assertLoaded(String fileName) async {
if (!loadedFiles.containsKey(fileName)) { if (!loadedFiles.containsKey(fileName)) {
loadedFiles[fileName] = await load(fileName); loadedFiles[fileName] = await load(fileName);
} }
AudioPlayer audioPlayer = new AudioPlayer(); return loadedFiles[fileName];
return await audioPlayer.play(loadedFiles[fileName].path, isLocal: true);
} }
} }

View File

@ -14,22 +14,24 @@ abstract class SpriteComponent extends Component {
double x, y, angle; double x, y, angle;
double size; double width, height;
Image image; Image image;
final Paint paint = new Paint()..color = new Color(0xffffffff); final Paint paint = new Paint()..color = new Color(0xffffffff);
SpriteComponent(this.size, String imagePath) { SpriteComponent.square(double size, String imagePath) : this.rectangle(size, size, imagePath);
SpriteComponent.rectangle(this.width, this.height, String imagePath) {
Flame.images.load(imagePath).then((image) { this.image = image; }); Flame.images.load(imagePath).then((image) { this.image = image; });
} }
render(Canvas canvas) { render(Canvas canvas) {
canvas.translate(x, y); canvas.translate(x, y);
canvas.rotate(PI /2 + angle); canvas.rotate(PI /2 + angle);
canvas.translate(-size/2, -size/2); canvas.translate(-width/2, -height/2);
if (image != null) { if (image != null) {
Rect src = new Rect.fromLTWH(0.0, 0.0, image.width.toDouble(), image.height.toDouble()); Rect src = new Rect.fromLTWH(0.0, 0.0, image.width.toDouble(), image.height.toDouble());
Rect dst = new Rect.fromLTWH(0.0, 0.0, size, size); Rect dst = new Rect.fromLTWH(0.0, 0.0, width, height);
canvas.drawImageRect(image, src, dst, paint); canvas.drawImageRect(image, src, dst, paint);
} }
} }

View File

@ -1,10 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'dart:async'; import 'dart:async';
import 'dart:ui'; import 'dart:ui';
class Util { class Util {
Future<Size> initialDimensions() async { Future<Size> initialDimensions() async {
// https://github.com/flutter/flutter/issues/5259 // https://github.com/flutter/flutter/issues/5259
// "In release mode we start off at 0x0 but we don't in debug mode" // "In release mode we start off at 0x0 but we don't in debug mode"
@ -21,4 +22,11 @@ class Util {
return window.physicalSize; return window.physicalSize;
}); });
} }
}
void enableEvents() {
new CustomBinder();
}
}
class CustomBinder extends BindingBase with ServicesBinding {
}

View File

@ -1,6 +1,6 @@
name: flame name: flame
description: A minimalist Flutter game engine description: A minimalist Flutter game engine
version: 0.1.0 version: 0.2.0
author: Luan Nico <luannico27@gmail.com> author: Luan Nico <luannico27@gmail.com>
homepage: https://github.com/luanpotter/flame homepage: https://github.com/luanpotter/flame