mirror of
				https://github.com/flame-engine/flame.git
				synced 2025-10-31 17:06:50 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			92 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			92 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
| import 'dart:ui';
 | |
| 
 | |
| import 'package:flame/components/mixins/has_game_ref.dart';
 | |
| import 'package:flame/components/mixins/tapable.dart';
 | |
| import 'package:flame/game/base_game.dart';
 | |
| import 'package:ordered_set/comparing.dart';
 | |
| import 'package:ordered_set/ordered_set.dart';
 | |
| 
 | |
| import 'component.dart';
 | |
| import 'mixins/resizable.dart';
 | |
| 
 | |
| /// A mixin that helps you to make a `Component` wraps other components. It is useful to group visual components through a hierarchy.
 | |
| /// When implemented, makes every item in its `components` collection field be updated and rendered with the same conditions.
 | |
| ///
 | |
| /// Example of usage, where visibility of two components are handled by a wrapper:
 | |
| ///
 | |
| /// ```dart
 | |
| ///  class GameOverPanel extends PositionComponent with Resizable, ComposedComponent {
 | |
| ///   bool visible = false;
 | |
| ///
 | |
| ///   GameOverText gameOverText;
 | |
| ///   GameOverButton gameOverButton;
 | |
| ///
 | |
| ///   GameOverPanel(Image spriteImage) : super() {
 | |
| ///     gameOverText = GameOverText(spriteImage); // GameOverText is a Component
 | |
| ///     gameOverButton = GameOverButton(spriteImage); // GameOverRestart is a SpriteComponent
 | |
| ///
 | |
| ///     components..add(gameOverText)..add(gameOverButton);
 | |
| ///   }
 | |
| ///
 | |
| ///   @override
 | |
| ///   void render(Canvas canvas) {
 | |
| ///     if (visible) {
 | |
| ///       super.render(canvas);
 | |
| ///     } // If not, neither of its `components` will be rendered
 | |
| ///   }
 | |
| /// }
 | |
| /// ```
 | |
| ///
 | |
| mixin ComposedComponent on Component, HasGameRef, Tapable {
 | |
|   OrderedSet<Component> components =
 | |
|       OrderedSet(Comparing.on((c) => c.priority()));
 | |
| 
 | |
|   @override
 | |
|   void render(Canvas canvas) {
 | |
|     canvas.save();
 | |
|     components.forEach((comp) => _renderComponent(canvas, comp));
 | |
|     canvas.restore();
 | |
|   }
 | |
| 
 | |
|   void _renderComponent(Canvas canvas, Component c) {
 | |
|     if (!c.loaded()) {
 | |
|       return;
 | |
|     }
 | |
|     c.render(canvas);
 | |
|     canvas.restore();
 | |
|     canvas.save();
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   void update(double t) {
 | |
|     components.forEach((c) => c.update(t));
 | |
|     components.removeWhere((c) => c.destroy());
 | |
|   }
 | |
| 
 | |
|   void add(Component c) {
 | |
|     if (gameRef is BaseGame) {
 | |
|       (gameRef as BaseGame).preAdd(c);
 | |
|     }
 | |
|     components.add(c);
 | |
|   }
 | |
| 
 | |
|   // this is an important override for the Tapable mixin
 | |
|   @override
 | |
|   Iterable<Tapable> tapableChildren() => _findT<Tapable>();
 | |
| 
 | |
|   // this is an important override for the Resizable mixin
 | |
|   Iterable<Resizable> resizableChildren() => _findT<Resizable>();
 | |
| 
 | |
|   // Finds all children of type T, recursively
 | |
|   Iterable<T> _findT<T>() => components.expand((c) {
 | |
|         final List<T> r = [];
 | |
|         if (c is T) {
 | |
|           r.add(c as T);
 | |
|         }
 | |
|         if (c is ComposedComponent) {
 | |
|           r.addAll(c._findT<T>());
 | |
|         }
 | |
|         return r;
 | |
|       }).cast();
 | |
| }
 | 
