Make ScaleEffect.by multiplicative (#1174)

* Make ScaleEffect.by multiplicative

* formatting

Co-authored-by: Lukas Klingsbo <lukas.klingsbo@gmail.com>
This commit is contained in:
Pasha Stetsenko
2021-12-07 03:01:36 -08:00
committed by GitHub
parent 341d227bfc
commit 3ae134aee5
3 changed files with 31 additions and 26 deletions

View File

@ -11,6 +11,7 @@
- Fix render order of components and add tests
- `isHud` renamed to `respectCamera`
- Fix `HitboxCircle` when component is flipped
- `ScaleEffect.by` now applies multiplicatively instead of additively
## [1.0.0-releasecandidate.18]
- Forcing portrait and landscape mode is now supported on web

View File

@ -7,27 +7,36 @@ import 'transform2d_effect.dart';
///
/// The following constructors are provided:
///
/// - [ScaleEffect.by] will scale the target in relation to it's current
/// scale;
/// - [ScaleEffect.to] will scale the target to the specified scale
/// - [ScaleEffect.by] will scale the target by the given factor, relative to
/// its current scale;
/// - [ScaleEffect.to] will scale the target to the specified scale.
///
/// This effect applies incremental changes to the component's scale, and
/// requires that any other effect or update logic applied to the same component
/// also used incremental updates.
class ScaleEffect extends Transform2DEffect {
ScaleEffect.by(Vector2 offset, EffectController controller)
: _offset = offset.clone(),
ScaleEffect.by(Vector2 scaleFactor, EffectController controller)
: _scaleFactor = scaleFactor.clone(),
super(controller);
factory ScaleEffect.to(Vector2 targetScale, EffectController controller) =>
_ScaleToEffect(targetScale, controller);
Vector2 _offset;
final Vector2 _scaleFactor;
late Vector2 _scaleDelta;
@override
void onStart() {
_scaleDelta = Vector2(
target.scale.x * (_scaleFactor.x - 1),
target.scale.y * (_scaleFactor.y - 1),
);
}
@override
void apply(double progress) {
final dProgress = progress - previousProgress;
target.scale += _offset * dProgress;
target.scale += _scaleDelta * dProgress;
super.apply(progress);
}
}
@ -42,6 +51,6 @@ class _ScaleToEffect extends ScaleEffect {
@override
void onStart() {
_offset = _targetScale - target.scale;
_scaleDelta = _targetScale - target.scale;
}
}

View File

@ -13,9 +13,8 @@ void main() {
final component = PositionComponent();
game.ensureAdd(component);
component.scale = Vector2.all(1.0);
component.add(
ScaleEffect.by(Vector2.all(1.0), EffectController(duration: 1)),
ScaleEffect.by(Vector2.all(2.0), EffectController(duration: 1)),
);
game.update(0);
expectVector2(component.scale, Vector2.all(1.0));
@ -58,18 +57,18 @@ void main() {
game.ensureAdd(component);
final effect = ScaleEffect.by(
Vector2.all(1.0),
Vector2.all(2.0),
EffectController(duration: 1),
);
component.add(effect..removeOnFinish = false);
final expectedScale = Vector2.all(1.0);
for (var i = 0; i < 5; i++) {
expectVector2(component.scale, expectedScale);
// After each reset the object will be scaled up by Vector2(1, 1)
// After each reset the object will be scaled up twice
// relative to its scale at the start of the effect.
effect.reset();
game.update(1);
expectedScale.add(Vector2.all(1.0));
expectedScale.multiply(Vector2.all(2));
expectVector2(component.scale, expectedScale);
}
});
@ -94,7 +93,7 @@ void main() {
});
flameGame.test('scale composition', (game) {
final component = PositionComponent();
final component = PositionComponent()..flipVertically();
game.ensureAdd(component);
component.add(
@ -112,21 +111,17 @@ void main() {
);
game.update(1);
expectVector2(
component.scale,
Vector2.all(2),
epsilon: 1e-15,
); // 5*1/10 + 0.5*1
expect(component.scale.x, closeTo(0.7, 1e-15)); // (1 + 0.4) * 0.5
expect(component.scale.y, closeTo(-0.7, 1e-15));
game.update(1);
expectVector2(
component.scale,
Vector2.all(2),
epsilon: 1e-15,
); // 5*2/10 + 0.5*1 - 0.5*1
for (var i = 0; i < 10; i++) {
expect(component.scale.x, closeTo(1.8, 1e-15)); // (1 + 2*0.4) * 1
expect(component.scale.y, closeTo(-1.8, 1e-15));
for (var i = 0; i < 8; i++) {
game.update(1);
}
expectVector2(component.scale, Vector2.all(6), epsilon: 1e-15);
expect(component.scale.x, closeTo(5, 1e-15));
expect(component.scale.y, closeTo(-5, 1e-15));
game.update(0);
expect(component.children.length, 0);
});