Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(effects): Added ZigzagEffectController (#1261)
Simple alternating effect controller. Over the course of one period, this controller will proceed linearly from 0 to 1, then to -1, and then back to 0. Use this for oscillating effects where the starting position should be the center of the oscillations, rather than the extreme (as provided by the standard alternating EffectController).
- Loading branch information
Showing
6 changed files
with
145 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
examples/lib/stories/effects/effect_controllers_example.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import 'dart:ui'; | ||
|
||
import 'package:flame/components.dart'; | ||
import 'package:flame/effects.dart'; | ||
import 'package:flame/game.dart'; | ||
|
||
class EffectControllersExample extends FlameGame { | ||
static const description = ''' | ||
This page demonstrates application of various non-standard effect | ||
controllers. | ||
The first white square has a ZigzagEffectController with period 1. The | ||
orange square next to it has two move effects, each with a | ||
ZigzagEffectController. | ||
'''; | ||
|
||
@override | ||
void onMount() { | ||
camera.viewport = FixedResolutionViewport(Vector2(400, 600)); | ||
add( | ||
RectangleComponent.square( | ||
position: Vector2(20, 50), | ||
size: 20, | ||
)..add( | ||
MoveEffect.by( | ||
Vector2(0, 20), | ||
InfiniteEffectController(ZigzagEffectController(period: 1)), | ||
), | ||
), | ||
); | ||
add( | ||
RectangleComponent.square( | ||
position: Vector2(70, 50), | ||
size: 20, | ||
paint: Paint()..color = const Color(0xffffbc63), | ||
)..addAll([ | ||
MoveEffect.by( | ||
Vector2(0, 20), | ||
InfiniteEffectController(ZigzagEffectController(period: 8 / 7)), | ||
), | ||
MoveEffect.by( | ||
Vector2(10, 0), | ||
InfiniteEffectController(ZigzagEffectController(period: 2 / 3)), | ||
), | ||
]), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
packages/flame/lib/src/effects/controllers/zigzag_effect_controller.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import 'duration_effect_controller.dart'; | ||
import 'infinite_effect_controller.dart'; | ||
import 'repeated_effect_controller.dart'; | ||
|
||
/// This effect controller goes from 0 to 1, then back to 0, then to -1, and | ||
/// then again to 0. | ||
/// | ||
/// This is similar to an alternating controller, except that it treats the | ||
/// starting position as the "middle ground", and oscillates around it. | ||
/// | ||
/// Combine with [RepeatedEffectController] or [InfiniteEffectController] in | ||
/// order to create longer zigzags. | ||
class ZigzagEffectController extends DurationEffectController { | ||
ZigzagEffectController({required double period}) | ||
: assert(period > 0, 'Period must be positive: $period'), | ||
_quarterPeriod = period / 4, | ||
super(period); | ||
|
||
final double _quarterPeriod; | ||
|
||
@override | ||
double get progress { | ||
// Assume zigzag's period is 4 units of length. Within that period, there | ||
// are 3 linear segments: at first it's y = x, for 0 ≤ x ≤ 1, then it's | ||
// y = -x + 2, for 1 ≤ x ≤ 3, and finally it's y = x + (-4), for 3 ≤ x ≤ 4. | ||
final x = timer / _quarterPeriod; | ||
return x <= 1 | ||
? x | ||
: x >= 3 | ||
? x - 4 | ||
: 2 - x; | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
packages/flame/test/effects/controllers/zigzag_effect_controller_test.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import 'package:flame/effects.dart'; | ||
import 'package:flame_test/flame_test.dart'; | ||
import 'package:flutter_test/flutter_test.dart'; | ||
|
||
void main() { | ||
group('ZigzagEffectController', () { | ||
test('general properties', () { | ||
final ec = ZigzagEffectController(period: 1); | ||
expect(ec.duration, 1); | ||
expect(ec.started, true); | ||
expect(ec.completed, false); | ||
expect(ec.progress, 0); | ||
expect(ec.isRandom, false); | ||
}); | ||
|
||
test('progression', () { | ||
final ec = ZigzagEffectController(period: 4); | ||
final expectedProgress = [ | ||
for (var i = 0; i < 10; i++) i * 0.1, | ||
for (var i = 10; i > 0; i--) i * 0.1, | ||
for (var i = 0; i > -10; i--) i * 0.1, | ||
for (var i = -10; i <= 0; i++) i * 0.1, | ||
]; | ||
for (final p in expectedProgress) { | ||
expect(ec.progress, closeTo(p, 3e-15)); | ||
ec.advance(0.1); | ||
} | ||
expect(ec.completed, true); | ||
}); | ||
|
||
test('errors', () { | ||
expect( | ||
() => ZigzagEffectController(period: 0), | ||
failsAssert('Period must be positive: 0.0'), | ||
); | ||
expect( | ||
() => ZigzagEffectController(period: -1.1), | ||
failsAssert('Period must be positive: -1.1'), | ||
); | ||
}); | ||
}); | ||
} |