mirror of
				https://github.com/flame-engine/flame.git
				synced 2025-11-04 04:47:13 +08:00 
			
		
		
		
	Merge branch 'develop' into feature/add-joystick-component
This commit is contained in:
		@ -4,6 +4,9 @@
 | 
				
			|||||||
 - Add Joystick Component
 | 
					 - Add Joystick Component
 | 
				
			||||||
 - Adding BaseGame#markToRemove
 | 
					 - Adding BaseGame#markToRemove
 | 
				
			||||||
 - Upgrade tiled and flutter_svg dependencies
 | 
					 - Upgrade tiled and flutter_svg dependencies
 | 
				
			||||||
 | 
					 - onComplete callback for effects
 | 
				
			||||||
 | 
					 - Adding Layers
 | 
				
			||||||
 | 
					 - Update tiled dep to 0.5.0 and add support for rotation with improved api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 0.22.1
 | 
					## 0.22.1
 | 
				
			||||||
 - Fix Box2DComponent render priority
 | 
					 - Fix Box2DComponent render priority
 | 
				
			||||||
 | 
				
			|||||||
@ -42,6 +42,7 @@ Check out the [awesome flame repository](https://github.com/flame-engine/awesome
 | 
				
			|||||||
   - [Text Rendering](text.md)
 | 
					   - [Text Rendering](text.md)
 | 
				
			||||||
   - [Colors and the Palette](palette.md)
 | 
					   - [Colors and the Palette](palette.md)
 | 
				
			||||||
   - [Particles](particles.md)
 | 
					   - [Particles](particles.md)
 | 
				
			||||||
 | 
					   - [Layers](layers.md)
 | 
				
			||||||
 * Other Modules
 | 
					 * Other Modules
 | 
				
			||||||
   - [Util](util.md)
 | 
					   - [Util](util.md)
 | 
				
			||||||
   - [Gamepad](gamepad.md)
 | 
					   - [Gamepad](gamepad.md)
 | 
				
			||||||
 | 
				
			|||||||
@ -14,6 +14,8 @@ If `isInfinite` is false and `isAlternating` is true the effect will go from the
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
`isInfinite` and `isAlternating` are false by default and then the effect is just applied once, from the beginning of the curve until the end.
 | 
					`isInfinite` and `isAlternating` are false by default and then the effect is just applied once, from the beginning of the curve until the end.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When an effect is completed the callback `onComplete` will be called, it can be set as an optional argument to your effect.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## MoveEffect
 | 
					## MoveEffect
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Applied to `PositionComponent`s, this effect can be used to move the component to a new position, using an [animation curve](https://api.flutter.dev/flutter/animation/Curves-class.html).
 | 
					Applied to `PositionComponent`s, this effect can be used to move the component to a new position, using an [animation curve](https://api.flutter.dev/flutter/animation/Curves-class.html).
 | 
				
			||||||
 | 
				
			|||||||
@ -65,6 +65,7 @@ class MyGame extends BaseGame with TapDetector {
 | 
				
			|||||||
      isInfinite: false,
 | 
					      isInfinite: false,
 | 
				
			||||||
      isAlternating: true,
 | 
					      isAlternating: true,
 | 
				
			||||||
      offset: 0.5,
 | 
					      offset: 0.5,
 | 
				
			||||||
 | 
					      onComplete: () => print("onComplete callback"),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    greenSquare.addEffect(combination);
 | 
					    greenSquare.addEffect(combination);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										49
									
								
								doc/examples/layers/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								doc/examples/layers/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					# Miscellaneous
 | 
				
			||||||
 | 
					*.class
 | 
				
			||||||
 | 
					*.log
 | 
				
			||||||
 | 
					*.pyc
 | 
				
			||||||
 | 
					*.swp
 | 
				
			||||||
 | 
					.DS_Store
 | 
				
			||||||
 | 
					.atom/
 | 
				
			||||||
 | 
					.buildlog/
 | 
				
			||||||
 | 
					.history
 | 
				
			||||||
 | 
					.svn/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# IntelliJ related
 | 
				
			||||||
 | 
					*.iml
 | 
				
			||||||
 | 
					*.ipr
 | 
				
			||||||
 | 
					*.iws
 | 
				
			||||||
 | 
					.idea/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The .vscode folder contains launch configuration and tasks you configure in
 | 
				
			||||||
 | 
					# VS Code which you may wish to be included in version control, so this line
 | 
				
			||||||
 | 
					# is commented out by default.
 | 
				
			||||||
 | 
					#.vscode/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Flutter/Dart/Pub related
 | 
				
			||||||
 | 
					**/doc/api/
 | 
				
			||||||
 | 
					**/ios/Flutter/.last_build_id
 | 
				
			||||||
 | 
					.dart_tool/
 | 
				
			||||||
 | 
					.flutter-plugins
 | 
				
			||||||
 | 
					.flutter-plugins-dependencies
 | 
				
			||||||
 | 
					.packages
 | 
				
			||||||
 | 
					.pub-cache/
 | 
				
			||||||
 | 
					.pub/
 | 
				
			||||||
 | 
					/build/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Web related
 | 
				
			||||||
 | 
					lib/generated_plugin_registrant.dart
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Symbolication related
 | 
				
			||||||
 | 
					app.*.symbols
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Obfuscation related
 | 
				
			||||||
 | 
					app.*.map.json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Exceptions to above rules.
 | 
				
			||||||
 | 
					!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					android
 | 
				
			||||||
 | 
					ios
 | 
				
			||||||
 | 
					macos
 | 
				
			||||||
 | 
					web
 | 
				
			||||||
							
								
								
									
										10
									
								
								doc/examples/layers/.metadata
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								doc/examples/layers/.metadata
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					# 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: 9d58a87066d1da98eb06826918e4b90cc76ae0ef
 | 
				
			||||||
 | 
					  channel: master
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					project_type: app
 | 
				
			||||||
							
								
								
									
										3
									
								
								doc/examples/layers/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								doc/examples/layers/README.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					# layers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Simple project to showcase the layer feature of Flame
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								doc/examples/layers/assets/images/background.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								doc/examples/layers/assets/images/background.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 550 B  | 
							
								
								
									
										
											BIN
										
									
								
								doc/examples/layers/assets/images/enemy.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								doc/examples/layers/assets/images/enemy.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 228 B  | 
							
								
								
									
										
											BIN
										
									
								
								doc/examples/layers/assets/images/player.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								doc/examples/layers/assets/images/player.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 392 B  | 
							
								
								
									
										82
									
								
								doc/examples/layers/lib/main.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								doc/examples/layers/lib/main.dart
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,82 @@
 | 
				
			|||||||
 | 
					import 'package:flutter/material.dart' hide Animation;
 | 
				
			||||||
 | 
					import 'package:flame/game.dart';
 | 
				
			||||||
 | 
					import 'package:flame/sprite.dart';
 | 
				
			||||||
 | 
					import 'package:flame/layer/layer.dart';
 | 
				
			||||||
 | 
					import 'package:flame/flame.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'dart:ui';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void main() async {
 | 
				
			||||||
 | 
					  WidgetsFlutterBinding.ensureInitialized();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  await Flame.util.fullScreen();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final playerSprite = await Sprite.loadSprite('player.png');
 | 
				
			||||||
 | 
					  final enemySprite = await Sprite.loadSprite('enemy.png');
 | 
				
			||||||
 | 
					  final backgroundSprite = await Sprite.loadSprite('background.png');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  runApp(LayerGame(playerSprite, enemySprite, backgroundSprite).widget);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class GameLayer extends DynamicLayer {
 | 
				
			||||||
 | 
					  final Sprite playerSprite;
 | 
				
			||||||
 | 
					  final Sprite enemySprite;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  GameLayer(this.playerSprite, this.enemySprite) {
 | 
				
			||||||
 | 
					    preProcessors.add(ShadowProcessor());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  void drawLayer() {
 | 
				
			||||||
 | 
					    playerSprite.renderRect(
 | 
				
			||||||
 | 
					      canvas,
 | 
				
			||||||
 | 
					      const Rect.fromLTWH(50, 50, 150, 150),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    enemySprite.renderRect(
 | 
				
			||||||
 | 
					      canvas,
 | 
				
			||||||
 | 
					      const Rect.fromLTWH(250, 150, 100, 50),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class BackgroundLayer extends PreRenderedLayer {
 | 
				
			||||||
 | 
					  final Sprite sprite;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  BackgroundLayer(this.sprite) {
 | 
				
			||||||
 | 
					    preProcessors.add(ShadowProcessor());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  void drawLayer() {
 | 
				
			||||||
 | 
					    sprite.renderRect(
 | 
				
			||||||
 | 
					      canvas,
 | 
				
			||||||
 | 
					      const Rect.fromLTWH(50, 200, 300, 150),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class LayerGame extends Game {
 | 
				
			||||||
 | 
					  Sprite playerSprite;
 | 
				
			||||||
 | 
					  Sprite enemySprite;
 | 
				
			||||||
 | 
					  Sprite backgroundSprite;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Layer gameLayer;
 | 
				
			||||||
 | 
					  Layer backgroundLayer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  LayerGame(this.playerSprite, this.enemySprite, this.backgroundSprite) {
 | 
				
			||||||
 | 
					    gameLayer = GameLayer(playerSprite, enemySprite);
 | 
				
			||||||
 | 
					    backgroundLayer = BackgroundLayer(backgroundSprite);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  void update(double dt) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  void render(Canvas canvas) {
 | 
				
			||||||
 | 
					    gameLayer.render(canvas);
 | 
				
			||||||
 | 
					    backgroundLayer.render(canvas);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Color backgroundColor() => const Color(0xFF38607C);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										28
									
								
								doc/examples/layers/pubspec.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								doc/examples/layers/pubspec.yaml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					name: layers
 | 
				
			||||||
 | 
					description: Simple project to showcase the layer feature of Flame
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					publish_to: 'none' # Remove this line if you wish to publish to pub.dev
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					version: 1.0.0+1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					environment:
 | 
				
			||||||
 | 
					  sdk: ">=2.7.0 <3.0.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dependencies:
 | 
				
			||||||
 | 
					  flutter:
 | 
				
			||||||
 | 
					    sdk: flutter
 | 
				
			||||||
 | 
					  flame:
 | 
				
			||||||
 | 
					    path: ../../../
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  cupertino_icons: ^0.1.3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dev_dependencies:
 | 
				
			||||||
 | 
					  flutter_test:
 | 
				
			||||||
 | 
					    sdk: flutter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					flutter:
 | 
				
			||||||
 | 
					  uses-material-design: true
 | 
				
			||||||
 | 
					  assets:
 | 
				
			||||||
 | 
					    - assets/images/background.png
 | 
				
			||||||
 | 
					    - assets/images/enemy.png
 | 
				
			||||||
 | 
					    - assets/images/player.png
 | 
				
			||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@ -15,7 +15,7 @@ void main() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class TiledGame extends BaseGame {
 | 
					class TiledGame extends BaseGame {
 | 
				
			||||||
  TiledGame() {
 | 
					  TiledGame() {
 | 
				
			||||||
    final TiledComponent tiledMap = TiledComponent('map.tmx');
 | 
					    final TiledComponent tiledMap = TiledComponent('map.tmx', 16.0);
 | 
				
			||||||
    add(tiledMap);
 | 
					    add(tiledMap);
 | 
				
			||||||
    _addCoinsInMap(tiledMap);
 | 
					    _addCoinsInMap(tiledMap);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -30,8 +30,12 @@ class TiledGame extends BaseGame {
 | 
				
			|||||||
      final comp = AnimationComponent(
 | 
					      final comp = AnimationComponent(
 | 
				
			||||||
        20.0,
 | 
					        20.0,
 | 
				
			||||||
        20.0,
 | 
					        20.0,
 | 
				
			||||||
        Animation.sequenced('coins.png', 8,
 | 
					        Animation.sequenced(
 | 
				
			||||||
            textureWidth: 20, textureHeight: 20),
 | 
					          'coins.png',
 | 
				
			||||||
 | 
					          8,
 | 
				
			||||||
 | 
					          textureWidth: 20,
 | 
				
			||||||
 | 
					          textureHeight: 20,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
      comp.x = obj.x.toDouble();
 | 
					      comp.x = obj.x.toDouble();
 | 
				
			||||||
      comp.y = obj.y.toDouble();
 | 
					      comp.y = obj.y.toDouble();
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										92
									
								
								doc/layers.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								doc/layers.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,92 @@
 | 
				
			|||||||
 | 
					# Layers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Layers are an useful feature that lets you group renderization by context, as well as allow you yo pre-render things. That enables, for example, the renderization in memory of parts of your game that don't change much, like a background, and by doing that, freeing resources for more dynamic content that needs to be rendered every loop cycle.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There are two types of layers on Flame: `DynamicLayer` (for things that are moving or changing) and `PreRenderedLayer` (for things that are static).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## DynamicLayer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Dynamic layers are layers that are rendered every time that they are draw on the canvas. As the name suggests, it is meant for dynamic content and is most useful to group renderizations that are of the same context.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Usage example:
 | 
				
			||||||
 | 
					```dart
 | 
				
			||||||
 | 
					class GameLayer extends DynamicLayer {
 | 
				
			||||||
 | 
					  final MyGame game;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  GameLayer(this.game);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  void drawLayer() {
 | 
				
			||||||
 | 
					    game.playerSprite.renderRect(
 | 
				
			||||||
 | 
					      canvas,
 | 
				
			||||||
 | 
					      game.playerRect,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    game.enemySprite.renderRect(
 | 
				
			||||||
 | 
					      canvas,
 | 
				
			||||||
 | 
					      game.enemyRect,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MyGame extends Game {
 | 
				
			||||||
 | 
					  // Other methods ommited...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  void render(Canvas canvas) {
 | 
				
			||||||
 | 
					    gameLayer.render(canvas); // x and y can be provided as optional position arguments
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## PreRenderedLayer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Pre-rendered layers are layers that are rendered only once, cached in memory and then just replicated on the game canvas afterwards. They are most useful to cache content that don't change during the game, like a background for example.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Usage example:
 | 
				
			||||||
 | 
					```dart
 | 
				
			||||||
 | 
					class BackgroundLayer extends PreRenderedLayer {
 | 
				
			||||||
 | 
					  final Sprite sprite;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  BackgroundLayer(this.sprite);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  void drawLayer() {
 | 
				
			||||||
 | 
					    sprite.renderRect(
 | 
				
			||||||
 | 
					      canvas,
 | 
				
			||||||
 | 
					      const Rect.fromLTWH(50, 200, 300, 150),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MyGame extends Game {
 | 
				
			||||||
 | 
					  // Other methods ommited...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  void render(Canvas canvas) {
 | 
				
			||||||
 | 
					    backgroundLayer.render(canvas); // x and y can be provided as optional position arguments
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Layer Processors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Flame also provides a way to add processors on your layer, which are ways to add effects on the entire layer. At the moment, out of the box, only the `ShadowProcessor` is available, this processor renders a cool back drop shadow on your layer.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To add processors to your layer, just add them to the layer `preProcessors` or `postProcessors` list. For example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```dart
 | 
				
			||||||
 | 
					// Works the same for both DynamicLayer and PreRenderedLayer
 | 
				
			||||||
 | 
					class BackgroundLayer extends PreRenderedLayer {
 | 
				
			||||||
 | 
					  final Sprite sprite;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  BackgroundLayer(this.sprite) {
 | 
				
			||||||
 | 
					    preProcessors.add(ShadowProcessor());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  void drawLayer() { /* ommited */ }
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Custom processors can be creted by extending the `LayerProcessor` class.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can check an working example of layers [here](/doc/examples/layers).
 | 
				
			||||||
@ -1,7 +1,11 @@
 | 
				
			|||||||
# Tiled
 | 
					# Tiled
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[Tiled](https://www.mapeditor.org/) is an awesome tool to design levels and maps. Flame bundles a [dart package](https://pub.dev/packages/tiled) that parses tmx files and implements a very simple component for the map rendering.
 | 
					[Tiled](https://www.mapeditor.org/) is an awesome tool to design levels and maps.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Right now Tiled support on Flame is quite simple and it only renders the map on the screen, other advanced features are not yet supported.
 | 
					Flame bundles a [dart package](https://pub.dev/packages/tiled) that allows you to parse tmx (xml) files and access the tiles, objects and everything in there.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Flame also provides a simple TiledComponent for the map rendering, which renders the tiles on the screen and supports rotations and flips.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Other advanced features are not yet supported but you can easily read the objects and other features of the tmx and add custom behaviour (eg regions for triggers and walking areas, custom animated objects).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You can check a working example [here](/doc/examples/tiled).
 | 
					You can check a working example [here](/doc/examples/tiled).
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					import 'dart:math' as math;
 | 
				
			||||||
import 'dart:async';
 | 
					import 'dart:async';
 | 
				
			||||||
import 'dart:ui';
 | 
					import 'dart:ui';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -6,6 +7,68 @@ import 'package:flame/flame.dart';
 | 
				
			|||||||
import 'package:flutter/material.dart' show Colors;
 | 
					import 'package:flutter/material.dart' show Colors;
 | 
				
			||||||
import 'package:tiled/tiled.dart' hide Image;
 | 
					import 'package:tiled/tiled.dart' hide Image;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Tiled represents all flips and rotation using three possible flips: horizontal, vertical and diagonal.
 | 
				
			||||||
 | 
					/// This class converts that representation to a simpler one, that uses one angle (with pi/2 steps) and two flips (H or V).
 | 
				
			||||||
 | 
					/// More reference: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#tile-flipping
 | 
				
			||||||
 | 
					class _SimpleFlips {
 | 
				
			||||||
 | 
					  /// The angle (in steps of pi/2 rads), clockwise, around the center of the tile.
 | 
				
			||||||
 | 
					  final int angle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Whether to flip across a central vertical axis (passing through the center).
 | 
				
			||||||
 | 
					  final bool flipH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Whether to flip across a central horizontal axis (passing through the center).
 | 
				
			||||||
 | 
					  final bool flipV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _SimpleFlips(this.angle, this.flipH, this.flipV);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// This is the conversion from the truth table that I drew.
 | 
				
			||||||
 | 
					  factory _SimpleFlips.fromFlips(Flips flips) {
 | 
				
			||||||
 | 
					    int angle;
 | 
				
			||||||
 | 
					    bool flipV, flipH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!flips.diagonally && !flips.vertically && !flips.horizontally) {
 | 
				
			||||||
 | 
					      angle = 0;
 | 
				
			||||||
 | 
					      flipV = false;
 | 
				
			||||||
 | 
					      flipH = false;
 | 
				
			||||||
 | 
					    } else if (!flips.diagonally && !flips.vertically && flips.horizontally) {
 | 
				
			||||||
 | 
					      angle = 0;
 | 
				
			||||||
 | 
					      flipV = false;
 | 
				
			||||||
 | 
					      flipH = true;
 | 
				
			||||||
 | 
					    } else if (!flips.diagonally && flips.vertically && !flips.horizontally) {
 | 
				
			||||||
 | 
					      angle = 0;
 | 
				
			||||||
 | 
					      flipV = true;
 | 
				
			||||||
 | 
					      flipH = false;
 | 
				
			||||||
 | 
					    } else if (!flips.diagonally && flips.vertically && flips.horizontally) {
 | 
				
			||||||
 | 
					      angle = 2;
 | 
				
			||||||
 | 
					      flipV = false;
 | 
				
			||||||
 | 
					      flipH = false;
 | 
				
			||||||
 | 
					    } else if (flips.diagonally && !flips.vertically && !flips.horizontally) {
 | 
				
			||||||
 | 
					      angle = 1;
 | 
				
			||||||
 | 
					      flipV = false;
 | 
				
			||||||
 | 
					      flipH = true;
 | 
				
			||||||
 | 
					    } else if (flips.diagonally && !flips.vertically && flips.horizontally) {
 | 
				
			||||||
 | 
					      angle = 1;
 | 
				
			||||||
 | 
					      flipV = false;
 | 
				
			||||||
 | 
					      flipH = false;
 | 
				
			||||||
 | 
					    } else if (flips.diagonally && flips.vertically && !flips.horizontally) {
 | 
				
			||||||
 | 
					      angle = 3;
 | 
				
			||||||
 | 
					      flipV = false;
 | 
				
			||||||
 | 
					      flipH = false;
 | 
				
			||||||
 | 
					    } else if (flips.diagonally && flips.vertically && flips.horizontally) {
 | 
				
			||||||
 | 
					      angle = 1;
 | 
				
			||||||
 | 
					      flipV = true;
 | 
				
			||||||
 | 
					      flipH = false;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      // this should be exhaustive
 | 
				
			||||||
 | 
					      throw 'Invalid combination of booleans: $flips';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return _SimpleFlips(angle, flipH, flipV);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// This component renders a tile map based on a TMX file from Tiled.
 | 
				
			||||||
class TiledComponent extends Component {
 | 
					class TiledComponent extends Component {
 | 
				
			||||||
  String filename;
 | 
					  String filename;
 | 
				
			||||||
  TileMap map;
 | 
					  TileMap map;
 | 
				
			||||||
@ -13,10 +76,13 @@ class TiledComponent extends Component {
 | 
				
			|||||||
  Map<String, Image> images = <String, Image>{};
 | 
					  Map<String, Image> images = <String, Image>{};
 | 
				
			||||||
  Future future;
 | 
					  Future future;
 | 
				
			||||||
  bool _loaded = false;
 | 
					  bool _loaded = false;
 | 
				
			||||||
 | 
					  double destTileSize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static Paint paint = Paint()..color = Colors.white;
 | 
					  static Paint paint = Paint()..color = Colors.white;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  TiledComponent(this.filename) {
 | 
					  /// Creates this TiledComponent with the filename (for the tmx file resource)
 | 
				
			||||||
 | 
					  /// and destTileSize is the tile size to be rendered (not the tile size in the texture, that one is configured inside Tiled).
 | 
				
			||||||
 | 
					  TiledComponent(this.filename, this.destTileSize) {
 | 
				
			||||||
    future = _load();
 | 
					    future = _load();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -70,12 +136,28 @@ class TiledComponent extends Component {
 | 
				
			|||||||
        final image = images[tile.image.source];
 | 
					        final image = images[tile.image.source];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final rect = tile.computeDrawRect();
 | 
					        final rect = tile.computeDrawRect();
 | 
				
			||||||
        final src = Rect.fromLTWH(rect.left.toDouble(), rect.top.toDouble(),
 | 
					        final src = Rect.fromLTWH(
 | 
				
			||||||
            rect.width.toDouble(), rect.height.toDouble());
 | 
					          rect.left.toDouble(),
 | 
				
			||||||
        final dst = Rect.fromLTWH(tile.x.toDouble(), tile.y.toDouble(),
 | 
					          rect.top.toDouble(),
 | 
				
			||||||
            rect.width.toDouble(), rect.height.toDouble());
 | 
					          rect.width.toDouble(),
 | 
				
			||||||
 | 
					          rect.height.toDouble(),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        final dst = Rect.fromLTWH(
 | 
				
			||||||
 | 
					          tile.x * destTileSize,
 | 
				
			||||||
 | 
					          tile.y * destTileSize,
 | 
				
			||||||
 | 
					          destTileSize,
 | 
				
			||||||
 | 
					          destTileSize,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        final flips = _SimpleFlips.fromFlips(tile.flips);
 | 
				
			||||||
 | 
					        c.save();
 | 
				
			||||||
 | 
					        c.translate(dst.center.dx, dst.center.dy);
 | 
				
			||||||
 | 
					        c.rotate(flips.angle * math.pi / 2);
 | 
				
			||||||
 | 
					        c.scale(flips.flipV ? -1.0 : 1.0, flips.flipH ? -1.0 : 1.0);
 | 
				
			||||||
 | 
					        c.translate(-dst.center.dx, -dst.center.dy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        c.drawImageRect(image, src, dst, paint);
 | 
					        c.drawImageRect(image, src, dst, paint);
 | 
				
			||||||
 | 
					        c.restore();
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -83,6 +165,8 @@ class TiledComponent extends Component {
 | 
				
			|||||||
  @override
 | 
					  @override
 | 
				
			||||||
  void update(double t) {}
 | 
					  void update(double t) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// This returns an object group fetch by name from a given layer.
 | 
				
			||||||
 | 
					  /// Use this to add custom behaviour to special objects and groups.
 | 
				
			||||||
  Future<ObjectGroup> getObjectGroupFromLayer(String name) {
 | 
					  Future<ObjectGroup> getObjectGroupFromLayer(String name) {
 | 
				
			||||||
    return future.then((onValue) {
 | 
					    return future.then((onValue) {
 | 
				
			||||||
      return map.objectGroups
 | 
					      return map.objectGroups
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,8 @@ class CombinedEffect extends PositionComponentEffect {
 | 
				
			|||||||
    this.offset = 0.0,
 | 
					    this.offset = 0.0,
 | 
				
			||||||
    bool isInfinite = false,
 | 
					    bool isInfinite = false,
 | 
				
			||||||
    bool isAlternating = false,
 | 
					    bool isAlternating = false,
 | 
				
			||||||
  }) : super(isInfinite, isAlternating) {
 | 
					    Function onComplete,
 | 
				
			||||||
 | 
					  }) : super(isInfinite, isAlternating, onComplete: onComplete) {
 | 
				
			||||||
    final types = effects.map((e) => e.runtimeType);
 | 
					    final types = effects.map((e) => e.runtimeType);
 | 
				
			||||||
    assert(
 | 
					    assert(
 | 
				
			||||||
      types.toSet().length == types.length,
 | 
					      types.toSet().length == types.length,
 | 
				
			||||||
 | 
				
			|||||||
@ -12,6 +12,7 @@ export './sequence_effect.dart';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
abstract class PositionComponentEffect {
 | 
					abstract class PositionComponentEffect {
 | 
				
			||||||
  PositionComponent component;
 | 
					  PositionComponent component;
 | 
				
			||||||
 | 
					  Function() onComplete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool _isDisposed = false;
 | 
					  bool _isDisposed = false;
 | 
				
			||||||
  bool get isDisposed => _isDisposed;
 | 
					  bool get isDisposed => _isDisposed;
 | 
				
			||||||
@ -37,7 +38,11 @@ abstract class PositionComponentEffect {
 | 
				
			|||||||
  /// travel time
 | 
					  /// travel time
 | 
				
			||||||
  double get totalTravelTime => travelTime * (isAlternating ? 2 : 1);
 | 
					  double get totalTravelTime => travelTime * (isAlternating ? 2 : 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  PositionComponentEffect(this._initialIsInfinite, this._initialIsAlternating) {
 | 
					  PositionComponentEffect(
 | 
				
			||||||
 | 
					    this._initialIsInfinite,
 | 
				
			||||||
 | 
					    this._initialIsAlternating, {
 | 
				
			||||||
 | 
					    this.onComplete,
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
    isInfinite = _initialIsInfinite;
 | 
					    isInfinite = _initialIsInfinite;
 | 
				
			||||||
    isAlternating = _initialIsAlternating;
 | 
					    isAlternating = _initialIsAlternating;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -53,6 +58,9 @@ abstract class PositionComponentEffect {
 | 
				
			|||||||
    if (!hasFinished()) {
 | 
					    if (!hasFinished()) {
 | 
				
			||||||
      currentTime += dt * curveDirection + driftTime * driftMultiplier;
 | 
					      currentTime += dt * curveDirection + driftTime * driftMultiplier;
 | 
				
			||||||
      percentage = min(1.0, max(0.0, currentTime / travelTime));
 | 
					      percentage = min(1.0, max(0.0, currentTime / travelTime));
 | 
				
			||||||
 | 
					      if (hasFinished()) {
 | 
				
			||||||
 | 
					        onComplete?.call();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -28,7 +28,8 @@ class MoveEffect extends PositionComponentEffect {
 | 
				
			|||||||
    this.curve,
 | 
					    this.curve,
 | 
				
			||||||
    isInfinite = false,
 | 
					    isInfinite = false,
 | 
				
			||||||
    isAlternating = false,
 | 
					    isAlternating = false,
 | 
				
			||||||
  }) : super(isInfinite, isAlternating);
 | 
					    Function onComplete,
 | 
				
			||||||
 | 
					  }) : super(isInfinite, isAlternating, onComplete: onComplete);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  void initialize(_comp) {
 | 
					  void initialize(_comp) {
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,8 @@ class RotateEffect extends PositionComponentEffect {
 | 
				
			|||||||
    this.curve,
 | 
					    this.curve,
 | 
				
			||||||
    isInfinite = false,
 | 
					    isInfinite = false,
 | 
				
			||||||
    isAlternating = false,
 | 
					    isAlternating = false,
 | 
				
			||||||
  }) : super(isInfinite, isAlternating);
 | 
					    Function onComplete,
 | 
				
			||||||
 | 
					  }) : super(isInfinite, isAlternating, onComplete: onComplete);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  void initialize(_comp) {
 | 
					  void initialize(_comp) {
 | 
				
			||||||
 | 
				
			|||||||
@ -25,7 +25,8 @@ class ScaleEffect extends PositionComponentEffect {
 | 
				
			|||||||
    this.curve,
 | 
					    this.curve,
 | 
				
			||||||
    isInfinite = false,
 | 
					    isInfinite = false,
 | 
				
			||||||
    isAlternating = false,
 | 
					    isAlternating = false,
 | 
				
			||||||
  }) : super(isInfinite, isAlternating);
 | 
					    Function onComplete,
 | 
				
			||||||
 | 
					  }) : super(isInfinite, isAlternating, onComplete: onComplete);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  void initialize(_comp) {
 | 
					  void initialize(_comp) {
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,8 @@ class SequenceEffect extends PositionComponentEffect {
 | 
				
			|||||||
    @required this.effects,
 | 
					    @required this.effects,
 | 
				
			||||||
    isInfinite = false,
 | 
					    isInfinite = false,
 | 
				
			||||||
    isAlternating = false,
 | 
					    isAlternating = false,
 | 
				
			||||||
  }) : super(isInfinite, isAlternating) {
 | 
					    Function onComplete,
 | 
				
			||||||
 | 
					  }) : super(isInfinite, isAlternating, onComplete: onComplete) {
 | 
				
			||||||
    assert(
 | 
					    assert(
 | 
				
			||||||
      effects.every((effect) => effect.component == null),
 | 
					      effects.every((effect) => effect.component == null),
 | 
				
			||||||
      "No effects can be added to components from the start",
 | 
					      "No effects can be added to components from the start",
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										75
									
								
								lib/layer/layer.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								lib/layer/layer.dart
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,75 @@
 | 
				
			|||||||
 | 
					import 'package:meta/meta.dart';
 | 
				
			||||||
 | 
					import 'dart:ui';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import './processors.dart';
 | 
				
			||||||
 | 
					export './processors.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class Layer {
 | 
				
			||||||
 | 
					  List<LayerProcessor> preProcessors = [];
 | 
				
			||||||
 | 
					  List<LayerProcessor> postProcessors = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Picture _picture;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  PictureRecorder _recorder;
 | 
				
			||||||
 | 
					  Canvas _canvas;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @mustCallSuper
 | 
				
			||||||
 | 
					  void render(Canvas canvas, {double x = 0.0, double y = 0.0}) {
 | 
				
			||||||
 | 
					    if (_picture == null) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    canvas.save();
 | 
				
			||||||
 | 
					    canvas.translate(x, y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    preProcessors.forEach((p) => p.process(_picture, canvas));
 | 
				
			||||||
 | 
					    canvas.drawPicture(_picture);
 | 
				
			||||||
 | 
					    postProcessors.forEach((p) => p.process(_picture, canvas));
 | 
				
			||||||
 | 
					    canvas.restore();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Canvas get canvas {
 | 
				
			||||||
 | 
					    assert(
 | 
				
			||||||
 | 
					      _canvas != null,
 | 
				
			||||||
 | 
					      'Layer is not ready for rendering, call beginRendering first',
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    return _canvas;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void beginRendering() {
 | 
				
			||||||
 | 
					    _recorder = PictureRecorder();
 | 
				
			||||||
 | 
					    _canvas = Canvas(_recorder);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void finishRendering() {
 | 
				
			||||||
 | 
					    _picture = _recorder.endRecording();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _recorder = null;
 | 
				
			||||||
 | 
					    _canvas = null;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void drawLayer();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class PreRenderedLayer extends Layer {
 | 
				
			||||||
 | 
					  PreRenderedLayer() {
 | 
				
			||||||
 | 
					    reRender();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void reRender() {
 | 
				
			||||||
 | 
					    beginRendering();
 | 
				
			||||||
 | 
					    drawLayer();
 | 
				
			||||||
 | 
					    finishRendering();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class DynamicLayer extends Layer {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  void render(Canvas canvas, {double x = 0.0, double y = 0.0}) {
 | 
				
			||||||
 | 
					    beginRendering();
 | 
				
			||||||
 | 
					    drawLayer();
 | 
				
			||||||
 | 
					    finishRendering();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    super.render(canvas, x: x, y: y);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										29
									
								
								lib/layer/processors.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								lib/layer/processors.dart
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					import 'dart:ui';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class LayerProcessor {
 | 
				
			||||||
 | 
					  void process(Picture pic, Canvas canvas);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ShadowProcessor extends LayerProcessor {
 | 
				
			||||||
 | 
					  Paint _shadowPaint;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final Offset offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ShadowProcessor({
 | 
				
			||||||
 | 
					    this.offset = const Offset(10, 10),
 | 
				
			||||||
 | 
					    double opacity = 0.9,
 | 
				
			||||||
 | 
					    Color color = const Color(0xFF000000),
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    _shadowPaint = Paint()
 | 
				
			||||||
 | 
					      ..colorFilter =
 | 
				
			||||||
 | 
					          ColorFilter.mode(color.withOpacity(opacity), BlendMode.srcATop);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  void process(Picture pic, Canvas canvas) {
 | 
				
			||||||
 | 
					    canvas.saveLayer(Rect.largest, _shadowPaint);
 | 
				
			||||||
 | 
					    canvas.translate(offset.dx, offset.dy);
 | 
				
			||||||
 | 
					    canvas.drawPicture(pic);
 | 
				
			||||||
 | 
					    canvas.restore();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -11,7 +11,7 @@ dependencies:
 | 
				
			|||||||
  path_provider: ^1.6.0
 | 
					  path_provider: ^1.6.0
 | 
				
			||||||
  box2d_flame: ^0.4.6
 | 
					  box2d_flame: ^0.4.6
 | 
				
			||||||
  synchronized: ^2.1.0
 | 
					  synchronized: ^2.1.0
 | 
				
			||||||
  tiled: ^0.4.0
 | 
					  tiled: ^0.5.0
 | 
				
			||||||
  convert: ^2.0.1
 | 
					  convert: ^2.0.1
 | 
				
			||||||
  flutter_svg: ^0.18.0
 | 
					  flutter_svg: ^0.18.0
 | 
				
			||||||
  flare_flutter: ^2.0.1
 | 
					  flare_flutter: ^2.0.1
 | 
				
			||||||
 | 
				
			|||||||
@ -10,7 +10,7 @@ import 'package:test/test.dart';
 | 
				
			|||||||
void main() {
 | 
					void main() {
 | 
				
			||||||
  test('my first widget test', () async {
 | 
					  test('my first widget test', () async {
 | 
				
			||||||
    await Flame.init(bundle: TestAssetBundle());
 | 
					    await Flame.init(bundle: TestAssetBundle());
 | 
				
			||||||
    final tiled = TiledComponent('x');
 | 
					    final tiled = TiledComponent('x', 16);
 | 
				
			||||||
    await tiled.future;
 | 
					    await tiled.future;
 | 
				
			||||||
    expect(1, equals(1));
 | 
					    expect(1, equals(1));
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user