mirror of
https://github.com/flame-engine/flame.git
synced 2025-10-29 16:05:47 +08:00
New Rotate effect (#1061)
* Added FlameAnimationController class * Added MainAnimationController class * Update doc comments * formatting * rename MainAnimationController * Added tests for StandardAnimationController * Added more tests * comment * Added changelog note * Export StandardAnimationController * formatting * Use a default for 'curve' parameter * rename onsetDelay -> startDelay * Added Transofm2DEffect * Added EffectComponent * Added .transform getter * formatting * Rename EffectComponent -> Effect * Add documentation for the Effect class * minor * Added a test for Effect class * Adding tests for removeOnFinish * Adding tests for onStart and onFinish * Also check the effect after reset * Fix-up merge * formatting * added doc-comments * changelog note * Added test for transform2DEffect * Adjusted comments * Make PositionComponent._transform public * change changelog * Adding RotateEffect * wip on rotate2 example * Rename -> RotateEffect2 * export rotation effect * Finish example for RotateEffect2 * formatting * rename RotateEffect2 -> RotateEffect * Changelog note * Added test file * flutter format * Remove a print() call * _lastProgress moved to Transform2DEffect class * remove avoid_print for now * Moved description * Initialize paints during construction * Added a random test * flutter format Co-authored-by: Lukas Klingsbo <lukas.klingsbo@gmail.com>
This commit is contained in:
201
examples/lib/stories/effects/rotate_effect_example.dart
Normal file
201
examples/lib/stories/effects/rotate_effect_example.dart
Normal file
@ -0,0 +1,201 @@
|
||||
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) {
|
||||
super.render(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) {
|
||||
super.render(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) {
|
||||
super.render(canvas);
|
||||
canvas.drawCircle(Offset(_radius, _radius), _radius - _width / 2, _bgPaint);
|
||||
canvas.drawCircle(Offset(_radius, _radius), _radius - _width, _marksPaint);
|
||||
canvas.drawPath(_marksPath, _marksPaint);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user