mirror of
				https://github.com/flame-engine/flame.git
				synced 2025-11-01 01:18:38 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			206 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			206 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
| import 'dart:math';
 | |
| import 'dart:ui';
 | |
| 
 | |
| import 'package:flame/components.dart';
 | |
| import 'package:flame/game.dart';
 | |
| import 'package:flame/src/effects2/rotate_effect.dart'; // ignore: implementation_imports
 | |
| import 'package:flame/src/effects2/standard_effect_controller.dart'; // ignore: implementation_imports
 | |
| import 'package:flutter/animation.dart';
 | |
| 
 | |
| class RotateEffectExample extends FlameGame {
 | |
|   static const description = '''
 | |
|     The outer rim rotates at a different speed forward and reverse, and
 | |
|     uses the "ease" animation curve.
 | |
| 
 | |
|     The compass arrow has 3 rotation effects applied to it at the same
 | |
|     time: one effect rotates the arrow at a constant speed, and two more
 | |
|     add small amounts of wobble, creating quasi-chaotic movement.
 | |
|   ''';
 | |
| 
 | |
|   @override
 | |
|   void onMount() {
 | |
|     camera.viewport = FixedResolutionViewport(Vector2(400, 600));
 | |
|     final compass = Compass(200)..position = Vector2(200, 300);
 | |
|     add(compass);
 | |
| 
 | |
|     compass.rim.add(
 | |
|       RotateEffect.by(
 | |
|         1.0,
 | |
|         StandardEffectController(
 | |
|           duration: 6,
 | |
|           reverseDuration: 3,
 | |
|           curve: Curves.ease,
 | |
|           infinite: true,
 | |
|         ),
 | |
|       ),
 | |
|     );
 | |
|     compass.arrow
 | |
|       ..add(
 | |
|         RotateEffect.to(
 | |
|           Transform2D.tau,
 | |
|           StandardEffectController(
 | |
|             duration: 20,
 | |
|             infinite: true,
 | |
|           ),
 | |
|         ),
 | |
|       )
 | |
|       ..add(
 | |
|         RotateEffect.by(
 | |
|           Transform2D.tau * 0.015,
 | |
|           StandardEffectController(
 | |
|             duration: 0.1,
 | |
|             reverseDuration: 0.1,
 | |
|             infinite: true,
 | |
|           ),
 | |
|         ),
 | |
|       )
 | |
|       ..add(
 | |
|         RotateEffect.by(
 | |
|           Transform2D.tau * 0.021,
 | |
|           StandardEffectController(
 | |
|             duration: 0.13,
 | |
|             reverseDuration: 0.13,
 | |
|             infinite: true,
 | |
|           ),
 | |
|         ),
 | |
|       );
 | |
|   }
 | |
| }
 | |
| 
 | |
| class Compass extends PositionComponent {
 | |
|   Compass(double size)
 | |
|       : _radius = size / 2,
 | |
|         super(
 | |
|           size: Vector2.all(size),
 | |
|           anchor: Anchor.center,
 | |
|         );
 | |
| 
 | |
|   late PositionComponent arrow;
 | |
|   late PositionComponent rim;
 | |
| 
 | |
|   final double _radius;
 | |
|   final _bgPaint = Paint()..color = const Color(0xffeacb31);
 | |
|   final _marksPaint = Paint()
 | |
|     ..color = const Color(0xFF7F6D36)
 | |
|     ..style = PaintingStyle.stroke
 | |
|     ..strokeWidth = 1.5;
 | |
|   late Path _marksPath;
 | |
| 
 | |
|   @override
 | |
|   Future<void> onLoad() async {
 | |
|     super.onLoad();
 | |
|     _marksPath = Path();
 | |
|     for (var i = 0; i < 12; i++) {
 | |
|       final angle = Transform2D.tau * (i / 12);
 | |
|       // Note: rim takes up 0.1radius, so the lengths must be > than that
 | |
|       final markLength = (i % 3 == 0) ? _radius * 0.2 : _radius * 0.15;
 | |
|       _marksPath.moveTo(
 | |
|         _radius + _radius * sin(angle),
 | |
|         _radius + _radius * cos(angle),
 | |
|       );
 | |
|       _marksPath.lineTo(
 | |
|         _radius + (_radius - markLength) * sin(angle),
 | |
|         _radius + (_radius - markLength) * cos(angle),
 | |
|       );
 | |
|     }
 | |
| 
 | |
|     arrow = CompassArrow(width: _radius * 0.3, radius: _radius * 0.7)
 | |
|       ..position = Vector2(_radius, _radius);
 | |
|     rim = CompassRim(radius: _radius, width: _radius * 0.1)
 | |
|       ..position = Vector2(_radius, _radius);
 | |
|     add(arrow);
 | |
|     add(rim);
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   void render(Canvas canvas) {
 | |
|     canvas.drawCircle(Offset(_radius, _radius), _radius, _bgPaint);
 | |
|     canvas.drawPath(_marksPath, _marksPaint);
 | |
|   }
 | |
| }
 | |
| 
 | |
| class CompassArrow extends PositionComponent {
 | |
|   CompassArrow({required double width, required double radius})
 | |
|       : assert(width <= radius),
 | |
|         _radius = radius,
 | |
|         _width = width,
 | |
|         super(size: Vector2(width, 2 * radius), anchor: Anchor.center);
 | |
| 
 | |
|   final double _radius;
 | |
|   final double _width;
 | |
|   late final Path _northPath;
 | |
|   late final Path _southPath;
 | |
|   final _northPaint = Paint()..color = const Color(0xff387fcb);
 | |
|   final _southPaint = Paint()..color = const Color(0xffa83636);
 | |
| 
 | |
|   @override
 | |
|   Future<void> onLoad() async {
 | |
|     super.onLoad();
 | |
|     _northPath = Path()
 | |
|       ..moveTo(0, _radius)
 | |
|       ..lineTo(_width / 2, 0)
 | |
|       ..lineTo(_width, _radius)
 | |
|       ..close();
 | |
|     _southPath = Path()
 | |
|       ..moveTo(0, _radius)
 | |
|       ..lineTo(_width, _radius)
 | |
|       ..lineTo(_width / 2, 2 * _radius)
 | |
|       ..close();
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   void render(Canvas canvas) {
 | |
|     canvas.drawPath(_northPath, _northPaint);
 | |
|     canvas.drawPath(_southPath, _southPaint);
 | |
|   }
 | |
| }
 | |
| 
 | |
| class CompassRim extends PositionComponent {
 | |
|   CompassRim({required double radius, required double width})
 | |
|       : assert(radius > width),
 | |
|         _radius = radius,
 | |
|         _width = width,
 | |
|         super(
 | |
|           size: Vector2.all(2 * radius),
 | |
|           anchor: Anchor.center,
 | |
|         );
 | |
| 
 | |
|   static const int numberOfNotches = 144;
 | |
|   final double _radius;
 | |
|   final double _width;
 | |
|   late final Path _marksPath;
 | |
|   final _bgPaint = Paint()
 | |
|     ..style = PaintingStyle.stroke
 | |
|     ..color = const Color(0xffb6a241);
 | |
|   final _marksPaint = Paint()
 | |
|     ..style = PaintingStyle.stroke
 | |
|     ..color = const Color(0xff3d3b26);
 | |
| 
 | |
|   @override
 | |
|   Future<void> onLoad() async {
 | |
|     super.onLoad();
 | |
|     _bgPaint.strokeWidth = _width;
 | |
|     _marksPath = Path();
 | |
|     final innerRadius = _radius - _width;
 | |
|     final midRadius = _radius - _width / 3;
 | |
|     for (var i = 0; i < numberOfNotches; i++) {
 | |
|       final angle = Transform2D.tau * (i / numberOfNotches);
 | |
|       _marksPath.moveTo(
 | |
|         _radius + innerRadius * sin(angle),
 | |
|         _radius + innerRadius * cos(angle),
 | |
|       );
 | |
|       _marksPath.lineTo(
 | |
|         _radius + midRadius * sin(angle),
 | |
|         _radius + midRadius * cos(angle),
 | |
|       );
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   void render(Canvas canvas) {
 | |
|     canvas.drawCircle(Offset(_radius, _radius), _radius - _width / 2, _bgPaint);
 | |
|     canvas.drawCircle(Offset(_radius, _radius), _radius - _width, _marksPaint);
 | |
|     canvas.drawPath(_marksPath, _marksPaint);
 | |
|   }
 | |
| }
 | 
