Merge pull request #411 from flame-engine/develop

0.24.0 RC
This commit is contained in:
Erick
2020-07-02 20:02:15 -03:00
committed by GitHub
25 changed files with 115 additions and 281 deletions

View File

@@ -1,5 +1,11 @@
# CHANGELOG
## 0.24.0
- Outsourcing SVG support to an external package
- Adding MemoryCache class
- Fixing games crashes on Web
- Update tiled dependency to 0.6.0 (objects' properties are now double)
## 0.23.0
- Add Joystick Component
- Adding BaseGame#markToRemove

View File

@@ -18,7 +18,7 @@ Put the pub package as your dependency by dropping the following in your `pubspe
```yaml
dependencies:
flame: ^0.23.0
flame: ^0.24.0
```
And start using it!

View File

@@ -1,11 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 105">
<g fill="#97C024" stroke="#97C024" stroke-linejoin="round" stroke-linecap="round">
<path d="M14,40v24M81,40v24M38,68v24M57,68v24M28,42v31h39v-31z" stroke-width="12"/>
<path d="M32,5l5,10M64,5l-6,10 " stroke-width="2"/>
</g>
<path d="M22,35h51v10h-51zM22,33c0-31,51-31,51,0" fill="#97C024"/>
<g fill="#FFF">
<circle cx="36" cy="22" r="2"/>
<circle cx="59" cy="22" r="2"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 471 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -1,8 +1,7 @@
import 'package:flame/game.dart';
import 'package:flame/flame.dart';
import 'package:flame/svg.dart';
import 'package:flame/position.dart';
import 'package:flame/components/component.dart' show SvgComponent;
import 'package:flame/components/component.dart';
import 'package:flame/components/mixins/resizable.dart';
import 'package:flame/text_config.dart';
@@ -16,12 +15,12 @@ void main() async {
myGame.start();
}
class AndroidComponent extends SvgComponent with Resizable {
class AndroidComponent extends SpriteComponent with Resizable {
static const int SPEED = 150;
int xDirection = 1;
int yDirection = 1;
AndroidComponent() : super.fromSvg(100, 100, Svg('android.svg'));
AndroidComponent() : super.square(100, 'android.png');
@override
void update(double dt) {
@@ -49,7 +48,7 @@ class AndroidComponent extends SvgComponent with Resizable {
}
class MyGame extends BaseGame {
final fpsTextConfig = const TextConfig(color: const Color(0xFFFFFFFF));
final fpsTextConfig = TextConfig(color: const Color(0xFFFFFFFF));
@override
bool debugMode() => true;

View File

@@ -18,4 +18,4 @@ dev_dependencies:
flutter:
assets:
- assets/android.svg
- assets/images/android.png

View File

@@ -16,8 +16,7 @@ void main() {
}
class MyGame extends BaseGame with TapDetector {
final TextConfig fpsTextConfig =
const TextConfig(color: const Color(0xFFFFFFFF));
final TextConfig fpsTextConfig = TextConfig(color: const Color(0xFFFFFFFF));
final paint = Paint()..color = const Color(0xFFE5E5E5E5);
final List<String> _animations = ["Stand", "Wave", "Jump", "Dance"];

View File

@@ -43,7 +43,7 @@ class MyGame extends BaseGame {
final Random rnd = Random();
final StepTween steppedTween = StepTween(begin: 0, end: 5);
final trafficLight = TrafficLightComponent();
final TextConfig fpsTextConfig = const TextConfig(
final TextConfig fpsTextConfig = TextConfig(
color: const Color(0xFFFFFFFF),
);

View File

@@ -1,70 +0,0 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# Visual Studio Code related
.vscode/
# Flutter/Dart/Pub related
**/doc/api/
.dart_tool/
.flutter-plugins
.packages
.pub-cache/
.pub/
/build/
# Android related
**/android/**/gradle-wrapper.jar
**/android/.gradle
**/android/captures/
**/android/gradlew
**/android/gradlew.bat
**/android/local.properties
**/android/**/GeneratedPluginRegistrant.java
# iOS/XCode related
**/ios/**/*.mode1v3
**/ios/**/*.mode2v3
**/ios/**/*.moved-aside
**/ios/**/*.pbxuser
**/ios/**/*.perspectivev3
**/ios/**/*sync/
**/ios/**/.sconsign.dblite
**/ios/**/.tags*
**/ios/**/.vagrant/
**/ios/**/DerivedData/
**/ios/**/Icon?
**/ios/**/Pods/
**/ios/**/.symlinks/
**/ios/**/profile
**/ios/**/xcuserdata
**/ios/.generated/
**/ios/Flutter/App.framework
**/ios/Flutter/Flutter.framework
**/ios/Flutter/Generated.xcconfig
**/ios/Flutter/app.flx
**/ios/Flutter/app.zip
**/ios/Flutter/flutter_assets/
**/ios/ServiceDefinitions.json
**/ios/Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!**/ios/**/default.mode1v3
!**/ios/**/default.mode2v3
!**/ios/**/default.pbxuser
!**/ios/**/default.perspectivev3
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages

View File

@@ -1,10 +0,0 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: f91df4abe1427fef8862c9e81b2e5af6fc05a67a
channel: dev
project_type: app

View File

@@ -1,3 +0,0 @@
# svg
A sample Flame game showcasing hot to use Flame's SVG components

View File

@@ -1,11 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 105">
<g fill="#97C024" stroke="#97C024" stroke-linejoin="round" stroke-linecap="round">
<path d="M14,40v24M81,40v24M38,68v24M57,68v24M28,42v31h39v-31z" stroke-width="12"/>
<path d="M32,5l5,10M64,5l-6,10 " stroke-width="2"/>
</g>
<path d="M22,35h51v10h-51zM22,33c0-31,51-31,51,0" fill="#97C024"/>
<g fill="#FFF">
<circle cx="36" cy="22" r="2"/>
<circle cx="59" cy="22" r="2"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 471 B

View File

@@ -1,38 +0,0 @@
import 'package:flame/game.dart';
import 'package:flame/svg.dart';
import 'package:flame/position.dart';
import 'package:flame/components/component.dart' show SvgComponent;
import 'package:flutter/material.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
final game = MyGame();
runApp(game.widget);
}
class MyGame extends BaseGame {
Svg svgInstance;
SvgComponent android;
MyGame() {
_start();
}
void _start() {
svgInstance = Svg('android.svg');
android = SvgComponent.fromSvg(100, 100, svgInstance);
android.x = 100;
android.y = 100;
add(android);
}
@override
void render(Canvas canvas) {
super.render(canvas);
svgInstance.renderPosition(canvas, Position(100, 200), 300, 300);
}
}

View File

@@ -1,21 +0,0 @@
name: svg
description: Flame sample for using SVG images
version: 1.0.0+1
environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
flame:
path: ../../../
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
assets:
- assets/android.svg

View File

@@ -19,8 +19,7 @@ TextConfig tiny = regular.withFontSize(12.0);
class MyTextBox extends TextBoxComponent {
MyTextBox(String text)
: super(text,
config: tiny, boxConfig: const TextBoxConfig(timePerChar: 0.05));
: super(text, config: tiny, boxConfig: TextBoxConfig(timePerChar: 0.05));
@override
void drawBackground(Canvas c) {

View File

@@ -33,8 +33,7 @@ class GameWidget extends StatelessWidget {
}
class RenderedTimeComponent extends TimerComponent {
final TextConfig textConfig =
const TextConfig(color: const Color(0xFFFFFFFF));
final TextConfig textConfig = TextConfig(color: const Color(0xFFFFFFFF));
RenderedTimeComponent(Timer timer) : super(timer);
@@ -58,8 +57,7 @@ class MyBaseGame extends BaseGame with TapDetector, DoubleTapDetector {
}
class MyGame extends Game with TapDetector {
final TextConfig textConfig =
const TextConfig(color: const Color(0xFFFFFFFF));
final TextConfig textConfig = TextConfig(color: const Color(0xFFFFFFFF));
Timer countdown;
Timer interval;

View File

@@ -68,7 +68,9 @@ See example [here](/doc/examples/sprite_batch).
Flame provides a simple API to render SVG images in your game.
To use it just import the `Svg` class from `'package:flame/svg.dart'`, and use the following snippet to render it on the canvas:
Svg support is provided by the `flame_svg` external package, be sure to put it on your pubspec to use it
To use it just import the `Svg` class from `'package:flame_svg/flame_svg.dart'`, and use the following snippet to render it on the canvas:
```dart
Svg svgInstance = Svg('android.svg');

View File

@@ -4,7 +4,6 @@ import 'dart:ui';
import 'package:flutter/painting.dart';
import 'package:meta/meta.dart';
import '../svg.dart';
import '../sprite.dart';
import '../position.dart';
import '../anchor.dart';
@@ -205,23 +204,3 @@ class SpriteComponent extends PositionComponent {
return sprite != null && sprite.loaded() && x != null && y != null;
}
}
class SvgComponent extends PositionComponent {
Svg svg;
SvgComponent.fromSvg(double width, double height, this.svg) {
this.width = width;
this.height = height;
}
@override
void render(Canvas canvas) {
prepareCanvas(canvas);
svg.render(canvas, width, height);
}
@override
bool loaded() {
return svg != null && svg.loaded() && x != null && y != null;
}
}

View File

@@ -15,7 +15,7 @@ class TextBoxConfig {
final double timePerChar;
final double dismissDelay;
const TextBoxConfig({
TextBoxConfig({
this.maxWidth = 200.0,
this.margin = 8.0,
this.timePerChar = 0.0,
@@ -46,11 +46,13 @@ class TextBoxComponent extends PositionComponent with Resizable {
TextBoxConfig get boxConfig => _boxConfig;
TextBoxComponent(String text,
{TextConfig config = const TextConfig(),
TextBoxConfig boxConfig = const TextBoxConfig()}) {
_boxConfig = boxConfig;
_config = config;
TextBoxComponent(
String text, {
TextConfig config,
TextBoxConfig boxConfig,
}) {
_boxConfig = boxConfig ?? TextBoxConfig();
_config = config ?? TextConfig();
_text = text;
_lines = [];
text.split(' ').forEach((word) {

View File

@@ -27,8 +27,8 @@ class TextComponent extends PositionComponent {
_updateBox();
}
TextComponent(this._text, {TextConfig config = const TextConfig()}) {
_config = config;
TextComponent(this._text, {TextConfig config}) {
_config = config ?? TextConfig();
_updateBox();
}

27
lib/memory_cache.dart Normal file
View File

@@ -0,0 +1,27 @@
import 'dart:collection';
/// Simple class to cache values on the cache
///
class MemoryCache<K, V> {
final LinkedHashMap<K, V> _cache = LinkedHashMap();
final int cacheSize;
MemoryCache({this.cacheSize = 10});
void setValue(K key, V value) {
if (!_cache.containsKey(key)) {
_cache[key] = value;
while (_cache.length > cacheSize) {
final k = _cache.keys.first;
_cache.remove(k);
}
}
}
V getValue(K key) => _cache[key];
bool containsKey(K key) => _cache.containsKey(key);
int get size => _cache.length;
}

View File

@@ -1,51 +0,0 @@
import 'dart:ui';
import 'package:flutter_svg/flutter_svg.dart';
import 'flame.dart';
import 'position.dart';
class Svg {
DrawableRoot svgRoot;
Size size;
Svg(String fileName) {
Flame.assets.readFile(fileName).then((svgString) async {
svgRoot = await svg.fromSvgString(svgString, svgString);
});
}
/// Renders the svg on the [canvas] using the dimensions provided on [width] and [height]
///
/// If not loaded, does nothing
void render(Canvas canvas, double width, double height) {
if (!loaded()) {
return;
}
svgRoot.scaleCanvasToViewBox(canvas, Size(width, height));
svgRoot.draw(canvas, null);
}
/// Renders the svg on the [canvas] on the given [position] using the dimensions provided on [width] and [height]
///
/// If not loaded, does nothing
void renderPosition(
Canvas canvas,
Position position,
double width,
double height,
) {
if (!loaded()) {
return;
}
canvas.save();
canvas.translate(position.x, position.y);
render(canvas, width, height);
canvas.restore();
}
bool loaded() {
return svgRoot != null;
}
}

View File

@@ -4,6 +4,7 @@ import 'package:flutter/material.dart' as material;
import 'position.dart';
import 'anchor.dart';
import 'memory_cache.dart';
/// A Text Config contains all typographical information required to render texts; i.e., font size and color, family, etc.
///
@@ -52,10 +53,13 @@ class TextConfig {
/// For proper fonts of languages like Hebrew or Arabic, replace this with [TextDirection.rtl].
final TextDirection textDirection;
final MemoryCache _textPainterCache =
MemoryCache<String, material.TextPainter>();
/// Creates a constant [TextConfig] with sensible defaults.
///
/// Every parameter can be specified.
const TextConfig({
TextConfig({
this.fontSize = 24.0,
this.color = const Color(0xFF000000),
this.fontFamily = 'Arial',
@@ -93,6 +97,7 @@ class TextConfig {
/// However, you probably want to use the [render] method witch already renders for you considering the anchor.
/// That way, you don't need to perform the math for yourself.
material.TextPainter toTextPainter(String text) {
if (!_textPainterCache.containsKey(text)) {
final material.TextStyle style = material.TextStyle(
color: color,
fontSize: fontSize,
@@ -108,7 +113,10 @@ class TextConfig {
textDirection: textDirection,
);
tp.layout();
return tp;
_textPainterCache.setValue(text, tp);
}
return _textPainterCache.getValue(text);
}
/// Creates a new [TextConfig] changing only the [fontSize].

View File

@@ -1,6 +1,6 @@
name: flame
description: A minimalist Flutter game engine, provides a nice set of somewhat independent modules you can choose from.
version: 0.23.0
version: 0.24.0
homepage: https://github.com/flame-engine/flame
dependencies:
@@ -11,9 +11,8 @@ dependencies:
path_provider: ^1.6.0
box2d_flame: ^0.4.6
synchronized: ^2.1.0
tiled: ^0.5.0
tiled: ^0.6.0
convert: ^2.0.1
flutter_svg: ^0.18.0
flare_flutter: ^2.0.1
meta: ^1.1.8

View File

@@ -0,0 +1,31 @@
import 'package:test/test.dart';
import 'package:flame/memory_cache.dart';
void main() {
group('MemoryCache', () {
test('basic cache addition', () {
final cache = MemoryCache<int, String>();
cache.setValue(0, 'bla');
expect(cache.getValue(0), 'bla');
});
test('contains key', () {
final cache = MemoryCache<int, String>();
cache.setValue(0, 'bla');
expect(cache.containsKey(0), true);
expect(cache.containsKey(1), false);
});
test('cache size', () {
final cache = MemoryCache<int, String>(cacheSize: 1);
cache.setValue(0, 'bla');
cache.setValue(1, 'ble');
expect(cache.containsKey(0), false);
expect(cache.containsKey(1), true);
expect(cache.getValue(0), null);
expect(cache.getValue(1), 'ble');
expect(cache.size, 1);
});
});
}