Use a list of vector2 for MoveEffect

This commit is contained in:
Lukas Klingsbo
2020-10-04 21:26:04 +02:00
committed by Lukas Klingsbo
parent ba02032c68
commit b60f45c388
7 changed files with 68 additions and 24 deletions

View File

@ -13,7 +13,7 @@
- Make `Resizable` have a `gameSize` property instead of `size`
- Fix bug with CombinedEffect inside SequenceEffect
- Fix wrong end angle for relative rotational effects
- Use a list of Vector2 for Move effect to open up for more capabilities
- Use a list of Vector2 for Move effect to open up for more advanced move effects
## [next]
- Fix spriteAsWidget deprecation message

View File

@ -20,7 +20,7 @@ When an effect is completed the callback `onComplete` will be called, it can be
## MoveEffect
Applied to `PositionComponent`s, this effect can be used to move the component to a new position, using an [animation curve](https://api.flutter.dev/flutter/animation/Curves-class.html).
Applied to `PositionComponent`s, this effect can be used to move the component to a new positions, using an [animation curve](https://api.flutter.dev/flutter/animation/Curves-class.html).
Usage example:
```dart
@ -28,12 +28,18 @@ import 'package:flame/effects/effects.dart';
// Square is a PositionComponent
square.addEffect(MoveEffect(
destination: Position(200, 200),
path: [Vector2(200, 200), Vector2(200, 100), Vector(0, 50)],
speed: 250.0,
curve: Curves.bounceInOut,
isRelative: false,
));
```
If you want the positions in the path list to be relative to the components last position, and not absolute values on the screen, then you can set `isRelative = true`.
When you use that, the next position in the list will be relative to the previous position in the list, or if it is the first element of the list it is relative to the components position.
So if you have a component which is positioned at `Vector2(100, 100)` and you use `isRelative = true` with the following path list `path: [Vector(20, 0), Vector(0, 50)]`, then the component will
first move to `(120, 0)` and then to `(120, 100)`.
## ScaleEffect
Applied to `PositionComponent`s, this effect can be used to change the width and height of the component, using an [animation curve](https://api.flutter.dev/flutter/animation/Curves-class.html).

View File

@ -44,9 +44,9 @@ class MyGame extends BaseGame with TapDetector {
final move2 = MoveEffect(
path: [
Vector2(dx, dy + 20),
Vector2(dx - 20, dy - 20),
Vector2(dx + 20, dy),
Vector2(dx, dy + 50),
Vector2(dx - 50, dy - 50),
Vector2(dx + 50, dy),
],
speed: 150.0,
curve: Curves.easeIn,
@ -72,14 +72,15 @@ class MyGame extends BaseGame with TapDetector {
final combination = CombinedEffect(
effects: [move2, rotate],
isAlternating: true,
isAlternating: false,
isInfinite: true,
);
final sequence = SequenceEffect(
effects: [move1, scale, combination],
isInfinite: false,
isAlternating: true,
isInfinite: true,
isAlternating: false,
);
greenSquare.addEffect(sequence);
greenSquare.addEffect(combination);
}
}

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flame/extensions/vector2.dart';
import 'package:flame/game.dart';
import 'package:flame/gestures.dart';
import 'package:flame/effects/effects.dart';
@ -17,9 +18,19 @@ class MyGame extends BaseGame with TapDetector {
@override
void onTapUp(details) {
square.addEffect(MoveEffect(
path: [details.localPosition.toVector2()],
path: [
details.localPosition.toVector2().clone(),
Vector2(100, 100),
Vector2(50, 120),
Vector2(200, 400),
Vector2(150, 0),
Vector2(100, 300),
],
speed: 250.0,
curve: Curves.bounceInOut,
isRelative: false,
isInfinite: true,
isAlternating: true,
));
}
}

View File

@ -31,6 +31,11 @@ abstract class PositionComponentEffect {
double driftTime = 0.0;
int curveDirection = 1;
/// Used to be able to determine the start state of the component
Vector2 originalPosition;
double originalAngle;
Vector2 originalSize;
/// Used to be able to determine the end state of a sequence of effects
Vector2 endPosition;
double endAngle;
@ -70,6 +75,9 @@ abstract class PositionComponentEffect {
@mustCallSuper
void initialize(PositionComponent _comp) {
component = _comp;
originalPosition = component.position;
originalAngle = component.angle;
originalSize = component.size;
/// You need to set the travelTime during the initialization of the
/// extending effect

View File

@ -25,7 +25,6 @@ class MoveEffect extends PositionComponentEffect {
double speed;
Curve curve;
Vector2 _startPosition;
Vector2 _peakPosition;
MoveEffect({
@required this.path,
@ -61,10 +60,10 @@ class MoveEffect extends PositionComponentEffect {
} else {
_movePath = path;
}
print(_movePath);
_peakPosition = isRelative ? path.last : path.last - _startPosition;
if (!isAlternating) {
endPosition = _peakPosition;
endPosition = _movePath.last;
} else {
endPosition = _startPosition;
}
double pathLength = 0;
@ -91,9 +90,16 @@ class MoveEffect extends PositionComponentEffect {
);
lastPosition = v;
}
print(_percentagePath);
travelTime = pathLength / speed;
}
@override
void reset() {
super.reset();
if(_percentagePath?.isNotEmpty ?? false) {
_currentSubPath = _percentagePath.first;
}
}
@override
void update(double dt) {

View File

@ -5,10 +5,10 @@ import 'effects.dart';
class SequenceEffect extends PositionComponentEffect {
final List<PositionComponentEffect> effects;
int _currentIndex = 0;
int _currentIndex;
PositionComponentEffect currentEffect;
bool _currentWasAlternating;
double _driftModifier = 0.0;
double _driftModifier;
SequenceEffect({
@required this.effects,
@ -26,9 +26,7 @@ class SequenceEffect extends PositionComponentEffect {
void initialize(PositionComponent _comp) {
super.initialize(_comp);
_currentIndex = 0;
final originalSize = _comp.size;
final originalPosition = _comp.position;
final originalAngle = _comp.angle;
_driftModifier = 0.0;
effects.forEach((effect) {
effect.reset();
_comp.size = endSize;
@ -43,9 +41,9 @@ class SequenceEffect extends PositionComponentEffect {
0,
(time, effect) => time + effect.totalTravelTime,
);
component.size = originalSize;
component.position = originalPosition;
component.angle = originalAngle;
component.size = originalSize;
currentEffect = effects.first;
_currentWasAlternating = currentEffect.isAlternating;
}
@ -57,20 +55,30 @@ class SequenceEffect extends PositionComponentEffect {
}
super.update(dt);
// If the last effect's time to completion overshot its total time, add that
// time to the first time step of the next effect.
currentEffect.update(dt + _driftModifier);
_driftModifier = 0.0;
if (currentEffect.hasFinished()) {
_driftModifier = currentEffect.driftTime;
currentEffect.isAlternating = _currentWasAlternating;
_currentIndex++;
final iterationSize = isAlternating ? effects.length * 2 : effects.length;
if (_currentIndex != 0 && _currentIndex % iterationSize == 0) {
if (_currentIndex != 0
&& _currentIndex == iterationSize
&& (currentEffect.isAlternating ||
currentEffect.isAlternating == isAlternating)) {
isInfinite ? reset() : dispose();
return;
}
final orderedEffects =
curveDirection.isNegative ? effects.reversed.toList() : effects;
// Make sure the current effect has the `isAlternating` value it
// initially started with
currentEffect.isAlternating = _currentWasAlternating;
// Get the next effect that should be executed
currentEffect = orderedEffects[_currentIndex % effects.length];
// Keep track of what value of `isAlternating` the effect had from the
// start
_currentWasAlternating = currentEffect.isAlternating;
if (isAlternating &&
!currentEffect.isAlternating &&
@ -84,6 +92,10 @@ class SequenceEffect extends PositionComponentEffect {
@override
void reset() {
super.reset();
component.position = originalPosition;
component.angle = originalAngle;
component.size = originalSize;
initialize(component);
//effects.forEach((e) => e.reset());
}
}