mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-01 10:38:17 +08:00
v0.2.0, audio loop and rectangle textures
This commit is contained in:
@ -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
|
||||||
|
|||||||
34
README.md
34
README.md
@ -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!
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 {
|
||||||
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user