diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8721dae82..b1ab0a3d7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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
diff --git a/doc/README.md b/doc/README.md
index 4a59aa775..2eb948485 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -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!
diff --git a/doc/examples/debug/assets/android.svg b/doc/examples/debug/assets/android.svg
deleted file mode 100644
index 1db6886aa..000000000
--- a/doc/examples/debug/assets/android.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-
diff --git a/doc/examples/debug/assets/images/android.png b/doc/examples/debug/assets/images/android.png
new file mode 100644
index 000000000..54fe8001b
Binary files /dev/null and b/doc/examples/debug/assets/images/android.png differ
diff --git a/doc/examples/debug/lib/main.dart b/doc/examples/debug/lib/main.dart
index 032987a90..5fb0639d5 100644
--- a/doc/examples/debug/lib/main.dart
+++ b/doc/examples/debug/lib/main.dart
@@ -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;
diff --git a/doc/examples/debug/pubspec.yaml b/doc/examples/debug/pubspec.yaml
index abc656df6..6dea24adf 100644
--- a/doc/examples/debug/pubspec.yaml
+++ b/doc/examples/debug/pubspec.yaml
@@ -18,4 +18,4 @@ dev_dependencies:
flutter:
assets:
- - assets/android.svg
+ - assets/images/android.png
diff --git a/doc/examples/flare/lib/main.dart b/doc/examples/flare/lib/main.dart
index 36310713f..af5dda162 100644
--- a/doc/examples/flare/lib/main.dart
+++ b/doc/examples/flare/lib/main.dart
@@ -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 _animations = ["Stand", "Wave", "Jump", "Dance"];
diff --git a/doc/examples/particles/lib/main.dart b/doc/examples/particles/lib/main.dart
index aa59a502c..4f5608ab7 100644
--- a/doc/examples/particles/lib/main.dart
+++ b/doc/examples/particles/lib/main.dart
@@ -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),
);
diff --git a/doc/examples/svg/.gitignore b/doc/examples/svg/.gitignore
deleted file mode 100644
index 07488ba61..000000000
--- a/doc/examples/svg/.gitignore
+++ /dev/null
@@ -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
diff --git a/doc/examples/svg/.metadata b/doc/examples/svg/.metadata
deleted file mode 100644
index 2746ae240..000000000
--- a/doc/examples/svg/.metadata
+++ /dev/null
@@ -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
diff --git a/doc/examples/svg/README.md b/doc/examples/svg/README.md
deleted file mode 100644
index a3a0a6345..000000000
--- a/doc/examples/svg/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# svg
-
-A sample Flame game showcasing hot to use Flame's SVG components
diff --git a/doc/examples/svg/assets/android.svg b/doc/examples/svg/assets/android.svg
deleted file mode 100644
index 1db6886aa..000000000
--- a/doc/examples/svg/assets/android.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-
diff --git a/doc/examples/svg/lib/main.dart b/doc/examples/svg/lib/main.dart
deleted file mode 100644
index b50756c26..000000000
--- a/doc/examples/svg/lib/main.dart
+++ /dev/null
@@ -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);
- }
-}
diff --git a/doc/examples/svg/pubspec.yaml b/doc/examples/svg/pubspec.yaml
deleted file mode 100644
index 9f7405ac5..000000000
--- a/doc/examples/svg/pubspec.yaml
+++ /dev/null
@@ -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
diff --git a/doc/examples/text/lib/main.dart b/doc/examples/text/lib/main.dart
index c10090dee..037c8df67 100644
--- a/doc/examples/text/lib/main.dart
+++ b/doc/examples/text/lib/main.dart
@@ -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) {
diff --git a/doc/examples/timer/lib/main.dart b/doc/examples/timer/lib/main.dart
index dcb8e7d25..0e1dad562 100644
--- a/doc/examples/timer/lib/main.dart
+++ b/doc/examples/timer/lib/main.dart
@@ -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;
diff --git a/doc/images.md b/doc/images.md
index 6ac9e47de..85bd8dc51 100644
--- a/doc/images.md
+++ b/doc/images.md
@@ -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');
diff --git a/lib/components/component.dart b/lib/components/component.dart
index 18b95712f..35cd27cc5 100644
--- a/lib/components/component.dart
+++ b/lib/components/component.dart
@@ -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;
- }
-}
diff --git a/lib/components/text_box_component.dart b/lib/components/text_box_component.dart
index c2180f29a..02e9be5e8 100644
--- a/lib/components/text_box_component.dart
+++ b/lib/components/text_box_component.dart
@@ -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) {
diff --git a/lib/components/text_component.dart b/lib/components/text_component.dart
index e21b732ad..4e52ca28b 100644
--- a/lib/components/text_component.dart
+++ b/lib/components/text_component.dart
@@ -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();
}
diff --git a/lib/memory_cache.dart b/lib/memory_cache.dart
new file mode 100644
index 000000000..4c5d46e7a
--- /dev/null
+++ b/lib/memory_cache.dart
@@ -0,0 +1,27 @@
+import 'dart:collection';
+
+/// Simple class to cache values on the cache
+///
+class MemoryCache {
+ final LinkedHashMap _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;
+}
diff --git a/lib/svg.dart b/lib/svg.dart
deleted file mode 100644
index f41b9f535..000000000
--- a/lib/svg.dart
+++ /dev/null
@@ -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;
- }
-}
diff --git a/lib/text_config.dart b/lib/text_config.dart
index 9f9bdcfa8..088b62805 100644
--- a/lib/text_config.dart
+++ b/lib/text_config.dart
@@ -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();
+
/// 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,22 +97,26 @@ 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) {
- final material.TextStyle style = material.TextStyle(
- color: color,
- fontSize: fontSize,
- fontFamily: fontFamily,
- );
- final material.TextSpan span = material.TextSpan(
- style: style,
- text: text,
- );
- final material.TextPainter tp = material.TextPainter(
- text: span,
- textAlign: textAlign,
- textDirection: textDirection,
- );
- tp.layout();
- return tp;
+ if (!_textPainterCache.containsKey(text)) {
+ final material.TextStyle style = material.TextStyle(
+ color: color,
+ fontSize: fontSize,
+ fontFamily: fontFamily,
+ );
+ final material.TextSpan span = material.TextSpan(
+ style: style,
+ text: text,
+ );
+ final material.TextPainter tp = material.TextPainter(
+ text: span,
+ textAlign: textAlign,
+ textDirection: textDirection,
+ );
+ tp.layout();
+
+ _textPainterCache.setValue(text, tp);
+ }
+ return _textPainterCache.getValue(text);
}
/// Creates a new [TextConfig] changing only the [fontSize].
diff --git a/pubspec.yaml b/pubspec.yaml
index 0ebcfbba0..19b46bf25 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -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
diff --git a/test/memory_cache_test.dart b/test/memory_cache_test.dart
new file mode 100644
index 000000000..bf4cf6473
--- /dev/null
+++ b/test/memory_cache_test.dart
@@ -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();
+ cache.setValue(0, 'bla');
+ expect(cache.getValue(0), 'bla');
+ });
+
+ test('contains key', () {
+ final cache = MemoryCache();
+ cache.setValue(0, 'bla');
+ expect(cache.containsKey(0), true);
+ expect(cache.containsKey(1), false);
+ });
+
+ test('cache size', () {
+ final cache = MemoryCache(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);
+ });
+ });
+}