From 64170f29324b92304dbc5208d5f55b048c39f8dc Mon Sep 17 00:00:00 2001 From: Kurtis Melby Date: Sun, 25 Aug 2024 23:40:09 -0400 Subject: [PATCH] fix: fixing prevPosition updating (#55) --- examples/standard_platformer/pubspec.lock | 20 +-- .../behaviors/apply_velocity_behavior.dart | 2 +- .../lib/src/entities/moving_platform.dart | 164 ++++++++++-------- .../lib/src/entities/physical_entity.dart | 5 +- packages/leap/pubspec.lock | 4 +- 5 files changed, 111 insertions(+), 84 deletions(-) diff --git a/examples/standard_platformer/pubspec.lock b/examples/standard_platformer/pubspec.lock index 8e81c93..0089813 100644 --- a/examples/standard_platformer/pubspec.lock +++ b/examples/standard_platformer/pubspec.lock @@ -93,18 +93,18 @@ packages: dependency: transitive description: name: crypto - sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27 url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.5" ffi: dependency: transitive description: name: ffi - sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" + sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" file: dependency: transitive description: @@ -192,7 +192,7 @@ packages: path: "../../packages/leap" relative: true source: path - version: "0.7.0" + version: "0.8.0" lints: dependency: transitive description: @@ -245,10 +245,10 @@ packages: dependency: transitive description: name: path_provider_android - sha256: "490539678396d4c3c0b06efdaab75ae60675c3e0c66f72bc04c2e2c1e0e2abeb" + sha256: "6f01f8e37ec30b07bc424b4deabac37cacb1bc7e2e515ad74486039918a37eb7" url: "https://pub.dev" source: hosted - version: "2.2.9" + version: "2.2.10" path_provider_foundation: dependency: transitive description: @@ -338,10 +338,10 @@ packages: dependency: transitive description: name: synchronized - sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558" + sha256: a824e842b8a054f91a728b783c177c1e4731f6b124f9192468457a8913371255 url: "https://pub.dev" source: hosted - version: "3.1.0+1" + version: "3.2.0" term_glyph: dependency: transitive description: @@ -407,5 +407,5 @@ packages: source: hosted version: "6.5.0" sdks: - dart: ">=3.4.0 <4.0.0" + dart: ">=3.5.0 <4.0.0" flutter: ">=3.22.0" diff --git a/packages/leap/lib/src/entities/behaviors/apply_velocity_behavior.dart b/packages/leap/lib/src/entities/behaviors/apply_velocity_behavior.dart index 44d8911..89eb3b2 100644 --- a/packages/leap/lib/src/entities/behaviors/apply_velocity_behavior.dart +++ b/packages/leap/lib/src/entities/behaviors/apply_velocity_behavior.dart @@ -7,7 +7,7 @@ class ApplyVelocityBehavior extends PhysicalBehavior { @override void update(double dt) { - super.update(dt); + parent.prevPosition.setFrom(position); if (parent.statuses .where((s) => s is IgnoredByWorld || s is IgnoresVelocity) diff --git a/packages/leap/lib/src/entities/moving_platform.dart b/packages/leap/lib/src/entities/moving_platform.dart index b1c96ab..e1f1792 100644 --- a/packages/leap/lib/src/entities/moving_platform.dart +++ b/packages/leap/lib/src/entities/moving_platform.dart @@ -20,6 +20,12 @@ abstract class MovingPlatform extends PhysicalEntity { // with the platform. super.priority = 2, }) : super(static: true) { + // Behaviors + add(_ApplySpeedBehavior()); + add(ApplyVelocityBehavior()); + add(_PreventOvershotPositionBehavior()); + add(_MoveEntitiesAtopBehavior()); + tags.add(CommonTags.ground); position = initialPosition; @@ -56,6 +62,8 @@ abstract class MovingPlatform extends PhysicalEntity { /// at the front (index 0). late final List positionPath; + Vector2 get nextPosition => positionPath[_nextPathNode]; + /// What to do when reaching the end of the tilePath. final MovingPlatformLoopMode loopMode; @@ -70,75 +78,6 @@ abstract class MovingPlatform extends PhysicalEntity { positionPath = _calculatePositionPath(position, tilePath, tileSize); } - @override - @mustCallSuper - void updateAfter(double dt) { - if (!_stopped) { - _updatePositionAndLoop(dt); - - final deltaX = x - prevPosition.x; - final deltaY = y - prevPosition.y; - // Update the position of anything on top of this platform. Ideally - // this happens before the other entity's collision logic - leapWorld.physicals - .where((other) => other.collisionInfo.downCollision == this) - .forEach((element) { - element.x += deltaX; - element.y += deltaY; - }); - } - - super.updateAfter(dt); - } - - void _updatePositionAndLoop(double dt) { - if (position == positionPath[_nextPathNode]) { - if (_reversing) { - _nextPathNode -= 1; - } else { - _nextPathNode += 1; - } - - if (_nextPathNode < 0) { - _reversing = false; - _nextPathNode = 1; - } - if (_nextPathNode >= positionPath.length) { - switch (loopMode) { - case MovingPlatformLoopMode.none: - _stopped = true; - case MovingPlatformLoopMode.resetAndLoop: - position.x = positionPath[0].x; - position.y = positionPath[0].y; - _nextPathNode = 1; - case MovingPlatformLoopMode.reverseAndLoop: - _reversing = true; - _nextPathNode = positionPath.length - 2; - } - } - } - - final nextPosition = positionPath[_nextPathNode]; - - final lastX = position.x; - if (nextPosition.x > x) { - position.x += dt * moveSpeed.x * tileSize; - position.x = position.x.clamp(lastX, nextPosition.x); - } else { - position.x -= dt * moveSpeed.x * tileSize; - position.x = position.x.clamp(nextPosition.x, lastX); - } - - final lastY = position.y; - if (nextPosition.y > y) { - position.y += dt * moveSpeed.y * tileSize; - position.y = position.y.clamp(lastY, nextPosition.y); - } else { - position.y -= dt * moveSpeed.y * tileSize; - position.y = position.y.clamp(nextPosition.y, lastY); - } - } - static Vector2 _parseMoveSpeed(TiledObject tiledObject) { final x = tiledObject.properties.getValue('MoveSpeedX') ?? 1; final y = tiledObject.properties.getValue('MoveSpeedY') ?? 1; @@ -217,3 +156,90 @@ enum MovingPlatformLoopMode { /// start the path again. reverseAndLoop, } + +class _ApplySpeedBehavior extends PhysicalBehavior { + @override + void update(double dt) { + if (parent._stopped) { + return; + } + + if (position == parent.positionPath[parent._nextPathNode]) { + if (parent._reversing) { + parent._nextPathNode -= 1; + } else { + parent._nextPathNode += 1; + } + + if (parent._nextPathNode < 0) { + parent._reversing = false; + parent._nextPathNode = 1; + } + if (parent._nextPathNode >= parent.positionPath.length) { + switch (parent.loopMode) { + case MovingPlatformLoopMode.none: + parent._stopped = true; + case MovingPlatformLoopMode.resetAndLoop: + position.x = parent.positionPath[0].x; + position.y = parent.positionPath[0].y; + parent._nextPathNode = 1; + case MovingPlatformLoopMode.reverseAndLoop: + parent._reversing = true; + parent._nextPathNode = parent.positionPath.length - 2; + } + } + } + + if (parent.nextPosition.x > parent.x) { + velocity.x = parent.moveSpeed.x * parent.tileSize; + } else { + velocity.x = -parent.moveSpeed.x * parent.tileSize; + } + + if (parent.nextPosition.y > parent.y) { + velocity.y = parent.moveSpeed.y * parent.tileSize; + } else { + velocity.y = -parent.moveSpeed.y * parent.tileSize; + } + } +} + +class _MoveEntitiesAtopBehavior extends PhysicalBehavior { + @override + void update(double dt) { + if (!parent._stopped) { + final deltaX = x - prevPosition.x; + final deltaY = y - prevPosition.y; + // Update the position of anything on top of this platform. Ideally + // this happens before the other entity's collision logic + leapWorld.physicals + .where((other) => other.collisionInfo.downCollision == parent) + .forEach((element) { + element.x += deltaX; + element.y += deltaY; + }); + } + } +} + +class _PreventOvershotPositionBehavior + extends PhysicalBehavior { + @override + void update(double dt) { + if (parent.nextPosition.x > parent.prevPosition.x) { + position.x = + position.x.clamp(parent.prevPosition.x, parent.nextPosition.x); + } else { + position.x = + position.x.clamp(parent.nextPosition.x, parent.prevPosition.x); + } + + if (parent.nextPosition.y > parent.prevPosition.y) { + position.y = + position.y.clamp(parent.prevPosition.y, parent.nextPosition.y); + } else { + position.y = + position.y.clamp(parent.nextPosition.y, parent.prevPosition.y); + } + } +} diff --git a/packages/leap/lib/src/entities/physical_entity.dart b/packages/leap/lib/src/entities/physical_entity.dart index 321ba02..c2b7f43 100644 --- a/packages/leap/lib/src/entities/physical_entity.dart +++ b/packages/leap/lib/src/entities/physical_entity.dart @@ -63,7 +63,9 @@ abstract class PhysicalEntity extends PositionedEntity { /// [collisionInfo] from last game tick final CollisionInfo prevCollisionInfo = CollisionInfo(); - /// [position] from last game tick + /// [position] from last game tick. + /// Typically set by [ApplyVelocityBehavior], but if an entity + /// manages its own position state it should set this itself final Vector2 prevPosition = Vector2.zero(); /// Multiplier on standard gravity, see [LeapWorld]. @@ -127,7 +129,6 @@ abstract class PhysicalEntity extends PositionedEntity { @mustCallSuper void updateAfter(double dt) { _updateDebugHitbox(); - prevPosition.setFrom(position); } void _updateDebugHitbox() { diff --git a/packages/leap/pubspec.lock b/packages/leap/pubspec.lock index 98c208f..7e2762d 100644 --- a/packages/leap/pubspec.lock +++ b/packages/leap/pubspec.lock @@ -53,10 +53,10 @@ packages: dependency: transitive description: name: crypto - sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27 url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.5" fake_async: dependency: transitive description: