mirror of
				https://github.com/flame-engine/flame.git
				synced 2025-10-31 08:56:01 +08:00 
			
		
		
		
	Introduce updateTree (#1158)
* Introduce updateTree * Update tests * Fix update for game-in-game situations * Add dartdoc to updateTree
This commit is contained in:
		| @ -72,7 +72,6 @@ class MovableEmber extends Ember<FollowComponentExample> | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|     final deltaPosition = velocity * (speed * dt); |     final deltaPosition = velocity * (speed * dt); | ||||||
|     position.add(deltaPosition); |     position.add(deltaPosition); | ||||||
|     positionText.text = '(${x.toInt()}, ${y.toInt()})'; |     positionText.text = '(${x.toInt()}, ${y.toInt()})'; | ||||||
|  | |||||||
| @ -52,7 +52,6 @@ class MyCollidable extends PositionComponent | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|     if (_isWallHit) { |     if (_isWallHit) { | ||||||
|       removeFromParent(); |       removeFromParent(); | ||||||
|       return; |       return; | ||||||
|  | |||||||
| @ -89,7 +89,6 @@ class AnimatedComponent extends SpriteAnimationComponent | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|     position += velocity * dt; |     position += velocity * dt; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | |||||||
| @ -121,7 +121,6 @@ abstract class MyCollidable extends PositionComponent | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|     if (_isDragged) { |     if (_isDragged) { | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -1,6 +1,9 @@ | |||||||
| import 'package:flame/components.dart'; | import 'package:flame/components.dart'; | ||||||
| import 'package:flame/game.dart'; | import 'package:flame/game.dart'; | ||||||
| import 'package:flame/input.dart'; | import 'package:flame/input.dart'; | ||||||
|  | import 'package:flame/palette.dart'; | ||||||
|  | import 'package:flutter/cupertino.dart'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  |  | ||||||
| // This class only has `HasDraggables` since the game-in-game example moves a | // This class only has `HasDraggables` since the game-in-game example moves a | ||||||
| // draggable component to this game. | // draggable component to this game. | ||||||
| @ -32,8 +35,15 @@ class ComposabilityExample extends FlameGame with HasDraggables { | |||||||
| } | } | ||||||
|  |  | ||||||
| class ParentSquare extends RectangleComponent with HasGameRef { | class ParentSquare extends RectangleComponent with HasGameRef { | ||||||
|  |   static final defaultPaint = BasicPalette.white.paint() | ||||||
|  |     ..style = PaintingStyle.stroke; | ||||||
|  |  | ||||||
|   ParentSquare(Vector2 position, Vector2 size) |   ParentSquare(Vector2 position, Vector2 size) | ||||||
|       : super(position: position, size: size); |       : super( | ||||||
|  |           position: position, | ||||||
|  |           size: size, | ||||||
|  |           paint: defaultPaint, | ||||||
|  |         ); | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Future<void> onLoad() async { |   Future<void> onLoad() async { | ||||||
| @ -49,21 +59,25 @@ class ParentSquare extends RectangleComponent with HasGameRef { | |||||||
|         position: Vector2(100, 100), |         position: Vector2(100, 100), | ||||||
|         size: childSize, |         size: childSize, | ||||||
|         angle: 2, |         angle: 2, | ||||||
|  |         paint: defaultPaint, | ||||||
|       ), |       ), | ||||||
|       RectangleComponent.square( |       RectangleComponent.square( | ||||||
|         position: Vector2(160, 100), |         position: Vector2(160, 100), | ||||||
|         size: childSize, |         size: childSize, | ||||||
|         angle: 3, |         angle: 3, | ||||||
|  |         paint: defaultPaint, | ||||||
|       ), |       ), | ||||||
|       RectangleComponent.square( |       RectangleComponent.square( | ||||||
|         position: Vector2(170, 150), |         position: Vector2(170, 150), | ||||||
|         size: childSize, |         size: childSize, | ||||||
|         angle: 4, |         angle: 4, | ||||||
|  |         paint: defaultPaint, | ||||||
|       ), |       ), | ||||||
|       RectangleComponent.square( |       RectangleComponent.square( | ||||||
|         position: Vector2(70, 200), |         position: Vector2(70, 200), | ||||||
|         size: childSize, |         size: childSize, | ||||||
|         angle: 5, |         angle: 5, | ||||||
|  |         paint: defaultPaint, | ||||||
|       ), |       ), | ||||||
|     ]; |     ]; | ||||||
|  |  | ||||||
|  | |||||||
| @ -61,8 +61,6 @@ class LogoComponent extends SpriteComponent with HasGameRef<DebugExample> { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|  |  | ||||||
|     x += xDirection * speed * dt; |     x += xDirection * speed * dt; | ||||||
|  |  | ||||||
|     final rect = toRect(); |     final rect = toRect(); | ||||||
|  | |||||||
| @ -23,7 +23,6 @@ class JoystickPlayer extends SpriteComponent with HasGameRef { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|     if (!joystick.delta.isZero()) { |     if (!joystick.delta.isZero()) { | ||||||
|       position.add(joystick.relativeDelta * maxSpeed * dt); |       position.add(joystick.relativeDelta * maxSpeed * dt); | ||||||
|       angle = joystick.delta.screenAngle(); |       angle = joystick.delta.screenAngle(); | ||||||
|  | |||||||
| @ -570,7 +570,6 @@ class TrafficLightComponent extends Component { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|     colorChangeTimer.update(dt); |     colorChangeTimer.update(dt); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ | |||||||
| ## [Next] | ## [Next] | ||||||
|  - Add `ButtonComponent` backed by two `PositionComponent`s |  - Add `ButtonComponent` backed by two `PositionComponent`s | ||||||
|  - Add `SpriteButtonComponent` backed by two `Sprite`s |  - Add `SpriteButtonComponent` backed by two `Sprite`s | ||||||
|  |  - Introduce `updateTree` to follow the `renderTree` convention | ||||||
|  - Fix `Parallax.load` with different loading times |  - Fix `Parallax.load` with different loading times | ||||||
|  |  | ||||||
| ## [1.0.0-releasecandidate.18] | ## [1.0.0-releasecandidate.18] | ||||||
|  | |||||||
| @ -122,10 +122,19 @@ class Component with Loadable { | |||||||
|   /// your state considering this. |   /// your state considering this. | ||||||
|   /// All components in the tree are always updated by the same amount. The time |   /// All components in the tree are always updated by the same amount. The time | ||||||
|   /// each one takes to update adds up to the next update cycle. |   /// each one takes to update adds up to the next update cycle. | ||||||
|   @mustCallSuper |   void update(double dt) {} | ||||||
|   void update(double dt) { |  | ||||||
|  |   /// This method traverses the component tree and calls [update] on all its | ||||||
|  |   /// children according to their [priority] order, relative to the | ||||||
|  |   /// priority of the direct siblings, not the children or the ancestors. | ||||||
|  |   /// If you call this method from [update] you need to set [callOwnUpdate] to | ||||||
|  |   /// false so that you don't get stuck in an infinite loop. | ||||||
|  |   void updateTree(double dt, {bool callOwnUpdate = true}) { | ||||||
|     children.updateComponentList(); |     children.updateComponentList(); | ||||||
|     children.forEach((c) => c.update(dt)); |     if (callOwnUpdate) { | ||||||
|  |       update(dt); | ||||||
|  |     } | ||||||
|  |     children.forEach((c) => c.updateTree(dt)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void render(Canvas canvas) {} |   void render(Canvas canvas) {} | ||||||
|  | |||||||
| @ -91,7 +91,6 @@ class JoystickComponent extends HudMarginComponent with Draggable { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|     final knobRadius2 = knobRadius * knobRadius; |     final knobRadius2 = knobRadius * knobRadius; | ||||||
|     delta.setFrom(_unscaledDelta); |     delta.setFrom(_unscaledDelta); | ||||||
|     if (delta.isZero() && _baseKnobPosition != knob!.position) { |     if (delta.isZero() && _baseKnobPosition != knob!.position) { | ||||||
|  | |||||||
| @ -100,7 +100,6 @@ class ParallaxComponent<T extends FlameGame> extends PositionComponent | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|     parallax?.update(dt); |     parallax?.update(dt); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | |||||||
| @ -31,7 +31,6 @@ class ParticleComponent extends Component { | |||||||
|   /// Passes update chain to child [Particle]. |   /// Passes update chain to child [Particle]. | ||||||
|   @override |   @override | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|     particle.update(dt); |     particle.update(dt); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -100,7 +100,6 @@ class SpriteAnimationComponent extends PositionComponent with HasPaint { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|     if (playing) { |     if (playing) { | ||||||
|       animation?.update(dt); |       animation?.update(dt); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -111,7 +111,6 @@ class SpriteAnimationGroupComponent<T> extends PositionComponent with HasPaint { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|     animation?.update(dt); |     animation?.update(dt); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -232,7 +232,6 @@ class TextBoxComponent<T extends TextRenderer> extends TextComponent { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|     _lifeTime += dt; |     _lifeTime += dt; | ||||||
|     if (_previousChar != currentChar) { |     if (_previousChar != currentChar) { | ||||||
|       redraw(); |       redraw(); | ||||||
|  | |||||||
| @ -39,7 +39,6 @@ class TimerComponent extends Component { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|     timer.update(dt); |     timer.update(dt); | ||||||
|  |  | ||||||
|     if (removeOnFinish && timer.finished) { |     if (removeOnFinish && timer.finished) { | ||||||
|  | |||||||
| @ -64,10 +64,7 @@ class FlameGame extends Component with Game { | |||||||
|   /// interfering with each others rendering. |   /// interfering with each others rendering. | ||||||
|   @override |   @override | ||||||
|   @mustCallSuper |   @mustCallSuper | ||||||
|   void render(Canvas canvas) { |   void render(Canvas canvas) => _cameraWrapper.render(canvas); | ||||||
|     super.render(canvas); |  | ||||||
|     _cameraWrapper.render(canvas); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /// This updates every component in the tree. |   /// This updates every component in the tree. | ||||||
|   /// |   /// | ||||||
| @ -78,7 +75,9 @@ class FlameGame extends Component with Game { | |||||||
|   @override |   @override | ||||||
|   @mustCallSuper |   @mustCallSuper | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |     if (parent == null) { | ||||||
|  |       super.updateTree(dt, callOwnUpdate: false); | ||||||
|  |     } | ||||||
|     _cameraWrapper.update(dt); |     _cameraWrapper.update(dt); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | |||||||
| @ -18,13 +18,11 @@ class _MyTap extends PositionComponent with Tappable { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|     updated = true; |     updated = true; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void render(Canvas canvas) { |   void render(Canvas canvas) { | ||||||
|     super.render(canvas); |  | ||||||
|     rendered = true; |     rendered = true; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @ -78,12 +76,12 @@ void main() { | |||||||
|  |  | ||||||
|       await wrapper.add(child); |       await wrapper.add(child); | ||||||
|       expect(wrapper.contains(child), false); |       expect(wrapper.contains(child), false); | ||||||
|       wrapper.update(0); // children are only added on the next tick |       wrapper.updateTree(0); // children are only added on the next tick | ||||||
|       expect(wrapper.contains(child), true); |       expect(wrapper.contains(child), true); | ||||||
|  |  | ||||||
|       wrapper.remove(child); |       wrapper.remove(child); | ||||||
|       expect(wrapper.contains(child), true); |       expect(wrapper.contains(child), true); | ||||||
|       wrapper.update(0); // children are only removed on the next tick |       wrapper.updateTree(0); // children are only removed on the next tick | ||||||
|       expect(wrapper.contains(child), false); |       expect(wrapper.contains(child), false); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
| @ -98,7 +96,7 @@ void main() { | |||||||
|         expect(wrapper.contains(child), false); |         expect(wrapper.contains(child), false); | ||||||
|         await future; |         await future; | ||||||
|         expect(wrapper.contains(child), false); |         expect(wrapper.contains(child), false); | ||||||
|         wrapper.update(0); |         wrapper.updateTree(0); | ||||||
|         expect(wrapper.contains(child), true); |         expect(wrapper.contains(child), true); | ||||||
|       }, |       }, | ||||||
|     ); |     ); | ||||||
|  | |||||||
| @ -30,7 +30,6 @@ class _MyComponent extends PositionComponent with HasGameRef { | |||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|     isUpdateCalled = true; |     isUpdateCalled = true; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -159,9 +158,11 @@ void main() { | |||||||
| 
 | 
 | ||||||
|   flameGame.test('removes PositionComponent when shouldRemove is true', |   flameGame.test('removes PositionComponent when shouldRemove is true', | ||||||
|       (game) async { |       (game) async { | ||||||
|     await game.ensureAdd(PositionComponent()..shouldRemove = true); |     final component = PositionComponent(); | ||||||
|  |     await game.ensureAdd(component); | ||||||
|     expect(game.children.length, equals(1)); |     expect(game.children.length, equals(1)); | ||||||
|     game.update(0); |     component.shouldRemove = true; | ||||||
|  |     game.updateTree(0); | ||||||
|     expect(game.children.isEmpty, equals(true)); |     expect(game.children.isEmpty, equals(true)); | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
| @ -174,7 +175,7 @@ void main() { | |||||||
| 
 | 
 | ||||||
|     // Ensure clear does not remove components directly |     // Ensure clear does not remove components directly | ||||||
|     expect(game.children.length, equals(3)); |     expect(game.children.length, equals(3)); | ||||||
|     game.update(0.0); |     game.updateTree(0); | ||||||
|     expect(game.children.isEmpty, equals(true)); |     expect(game.children.isEmpty, equals(true)); | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
| @ -80,8 +80,6 @@ class BulletComponent extends SpriteAnimationComponent | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|  |  | ||||||
|     y += bulletSpeed * dt; |     y += bulletSpeed * dt; | ||||||
|     if (xDirection != 0) { |     if (xDirection != 0) { | ||||||
|       x += bulletSpeed * dt * xDirection; |       x += bulletSpeed * dt * xDirection; | ||||||
|  | |||||||
| @ -32,8 +32,6 @@ class EnemyComponent extends SpriteAnimationComponent | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|  |  | ||||||
|     y += enemySpeed * dt; |     y += enemySpeed * dt; | ||||||
|     shouldRemove = destroyed || y >= gameRef.size.y; |     shouldRemove = destroyed || y >= gameRef.size.y; | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -1,7 +1,6 @@ | |||||||
| import 'package:flame/components.dart'; | import 'package:flame/components.dart'; | ||||||
| import 'package:flame/geometry.dart'; | import 'package:flame/geometry.dart'; | ||||||
| import 'package:flame/input.dart'; | import 'package:flame/input.dart'; | ||||||
|  |  | ||||||
| import 'package:flame/timer.dart'; | import 'package:flame/timer.dart'; | ||||||
| import 'package:flame_bloc/flame_bloc.dart'; | import 'package:flame_bloc/flame_bloc.dart'; | ||||||
| import 'package:flutter/services.dart'; | import 'package:flutter/services.dart'; | ||||||
| @ -10,7 +9,6 @@ import './bullet.dart'; | |||||||
| import '../../game_stats/bloc/game_stats_bloc.dart'; | import '../../game_stats/bloc/game_stats_bloc.dart'; | ||||||
| import '../../inventory/bloc/inventory_bloc.dart'; | import '../../inventory/bloc/inventory_bloc.dart'; | ||||||
| import '../game.dart'; | import '../game.dart'; | ||||||
|  |  | ||||||
| import 'enemy.dart'; | import 'enemy.dart'; | ||||||
| import 'explosion.dart'; | import 'explosion.dart'; | ||||||
|  |  | ||||||
| @ -91,10 +89,7 @@ class PlayerComponent extends SpriteAnimationComponent | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|  |  | ||||||
|     bulletCreator.update(dt); |     bulletCreator.update(dt); | ||||||
|  |  | ||||||
|     shouldRemove = destroyed; |     shouldRemove = destroyed; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | |||||||
| @ -28,7 +28,6 @@ class FlareActorComponent extends PositionComponent { | |||||||
|   @override |   @override | ||||||
|   @mustCallSuper |   @mustCallSuper | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|     flareAnimation.advance(dt); |     flareAnimation.advance(dt); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | |||||||
| @ -27,7 +27,6 @@ class FlareParticle extends Particle { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|     flareAnimation.advance(dt); |     flareAnimation.advance(dt); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -51,8 +51,8 @@ class Ball extends BodyComponent { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|  |   @mustCallSuper | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|     _timeSinceNudge += dt; |     _timeSinceNudge += dt; | ||||||
|     if (giveNudge) { |     if (giveNudge) { | ||||||
|       giveNudge = false; |       giveNudge = false; | ||||||
|  | |||||||
| @ -47,7 +47,6 @@ abstract class PositionBodyComponent<T extends Forge2DGame> | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|     _updatePositionComponent(); |     _updatePositionComponent(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | |||||||
| @ -51,7 +51,6 @@ class RiveComponent extends PositionComponent { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void update(double dt) { |   void update(double dt) { | ||||||
|     super.update(dt); |  | ||||||
|     _renderer.advance(dt); |     _renderer.advance(dt); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -18,14 +18,14 @@ extension FlameGameExtension on Component { | |||||||
|   /// returned future to resolve. |   /// returned future to resolve. | ||||||
|   Future<void> ensureAdd(Component component) async { |   Future<void> ensureAdd(Component component) async { | ||||||
|     await add(component); |     await add(component); | ||||||
|     update(0); |     updateTree(0); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /// Makes sure that the [components] are added to the tree if you wait for the |   /// Makes sure that the [components] are added to the tree if you wait for the | ||||||
|   /// returned future to resolve. |   /// returned future to resolve. | ||||||
|   Future<void> ensureAddAll(Iterable<Component> components) async { |   Future<void> ensureAddAll(Iterable<Component> components) async { | ||||||
|     await addAll(components); |     await addAll(components); | ||||||
|     update(0); |     updateTree(0); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Lukas Klingsbo
					Lukas Klingsbo