Files
flame/examples/lib/stories/effects/rotate_effect_example.dart
Pasha Stetsenko 6e7e098f1b 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>
2021-11-02 21:08:55 +01:00

202 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) {
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);
}
}