Compare commits

...

4 Commits

Author SHA1 Message Date
Davy Hélard
911443ebd7 Review change: wording 2022-11-08 21:32:08 +01:00
Davy Hélard
5faf9bd63c Format 2022-11-08 16:07:46 +01:00
Davy Hélard
bb23e05edc Remplace todo by comments. 2022-11-08 15:59:12 +01:00
Davy Hélard
b45c448cdb Add an action to follow the floor. 2022-11-08 15:59:12 +01:00
5 changed files with 69 additions and 13 deletions

View File

@@ -648,6 +648,19 @@ void DeclarePlatformBehaviorExtension(gd::PlatformExtension& extension) {
.UseStandardOperatorParameters("number") .UseStandardOperatorParameters("number")
.MarkAsAdvanced(); .MarkAsAdvanced();
aut.AddScopedAction("FollowCurrentPlatform",
_("Follow the floor"),
_("Move the object to follow the platform it's currently"
"on if any. This action allows to avoid the 1-frame "
"delay induced by the automatic following."),
_("Move _PARAM0_ to follow the floor"),
_(""),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.MarkAsAdvanced();
aut.AddCondition("CurrentSpeed", aut.AddCondition("CurrentSpeed",
_("Current horizontal speed"), _("Current horizontal speed"),
_("Compare the current horizontal speed of the object " _("Compare the current horizontal speed of the object "

View File

@@ -131,10 +131,14 @@ class PlatformBehaviorJsExtension : public gd::PlatformExtension {
"getCurrentJumpSpeed"); "getCurrentJumpSpeed");
autExpressions["CurrentJumpSpeed"].SetFunctionName("getCurrentJumpSpeed"); autExpressions["CurrentJumpSpeed"].SetFunctionName("getCurrentJumpSpeed");
autActions["PlatformBehavior::SetCanJump"].SetFunctionName("setCanJump"); autActions["PlatformBehavior::SetCanJump"].SetFunctionName("setCanJump");
autActions["PlatformBehavior::PlatformerObjectBehavior::SetCanNotAirJump"].SetFunctionName("setCanNotAirJump"); autActions["PlatformBehavior::PlatformerObjectBehavior::SetCanNotAirJump"]
autActions["PlatformBehavior::PlatformerObjectBehavior::AbortJump"].SetFunctionName("abortJump"); .SetFunctionName("setCanNotAirJump");
autConditions["PlatformBehavior::CanJump"].SetFunctionName( autActions["PlatformBehavior::PlatformerObjectBehavior::AbortJump"]
"canJump"); .SetFunctionName("abortJump");
autActions
["PlatformBehavior::PlatformerObjectBehavior::FollowCurrentPlatform"]
.SetFunctionName("followCurrentPlatformIfAny");
autConditions["PlatformBehavior::CanJump"].SetFunctionName("canJump");
autActions["PlatformBehavior::SimulateLeftKey"].SetFunctionName( autActions["PlatformBehavior::SimulateLeftKey"].SetFunctionName(
"simulateLeftKey"); "simulateLeftKey");
autActions["PlatformBehavior::SimulateRightKey"].SetFunctionName( autActions["PlatformBehavior::SimulateRightKey"].SetFunctionName(

View File

@@ -1592,6 +1592,17 @@ namespace gdjs {
this._currentFallSpeed !== 0 this._currentFallSpeed !== 0
); );
} }
followCurrentPlatformIfAny(): boolean {
let hasMoved = false;
if (this.isOnFloor()) {
const timeDelta = this.owner.getElapsedTime() / 1000;
const hasMovedX = this._onFloor.followCurrentPlatformOnX(timeDelta);
const hasMovedY = this._onFloor.followCurrentPlatformOnY(timeDelta);
hasMoved = hasMovedX || hasMovedY;
}
return hasMoved;
}
} }
/** /**
@@ -1666,6 +1677,11 @@ namespace gdjs {
} }
beforeUpdatingObstacles(timeDelta: float) { beforeUpdatingObstacles(timeDelta: float) {
this.followCurrentPlatformOnY(timeDelta);
}
followCurrentPlatformOnY(timeDelta: float): boolean {
let hasMoved = false;
const object = this._behavior.owner; const object = this._behavior.owner;
//Stick the object to the floor if its height has changed. //Stick the object to the floor if its height has changed.
if (this._oldHeight !== object.getHeight()) { if (this._oldHeight !== object.getHeight()) {
@@ -1674,6 +1690,7 @@ namespace gdjs {
object.getHeight() + object.getHeight() +
(object.getY() - object.getDrawableY()) (object.getY() - object.getDrawableY())
); );
hasMoved = true;
} }
// Directly follow the floor movement on the Y axis by moving the character. // Directly follow the floor movement on the Y axis by moving the character.
// For the X axis, we follow the floor movement using `_requestedDeltaX` // For the X axis, we follow the floor movement using `_requestedDeltaX`
@@ -1694,14 +1711,18 @@ namespace gdjs {
// and the platform can go out of the spatial search rectangle // and the platform can go out of the spatial search rectangle
// even though they are next to each other, which means // even though they are next to each other, which means
// that the character will fall. // that the character will fall.
const deltaY = this._floorPlatform!.owner.getY() - this._floorLastY; const floorY = this._floorPlatform!.owner.getY();
const deltaY = floorY - this._floorLastY;
if ( if (
deltaY !== 0 && deltaY !== 0 &&
Math.abs(deltaY) <= Math.abs(deltaY) <=
Math.abs(this._behavior._maxFallingSpeed * timeDelta) Math.abs(this._behavior._maxFallingSpeed * timeDelta)
) { ) {
object.setY(object.getY() + deltaY); object.setY(object.getY() + deltaY);
this._floorLastY = floorY;
hasMoved = true;
} }
return hasMoved;
} }
checkTransitionBeforeX() { checkTransitionBeforeX() {
@@ -1739,11 +1760,29 @@ namespace gdjs {
beforeMovingX() { beforeMovingX() {
const behavior = this._behavior; const behavior = this._behavior;
// Shift the object according to the floor movement. // Shift the object according to the floor movement.
behavior._requestedDeltaX += const floorX = this._floorPlatform!.owner.getX();
this._floorPlatform!.owner.getX() - this._floorLastX; const deltaX = floorX - this._floorLastX;
behavior._requestedDeltaX += deltaX;
this._floorLastX = floorX;
// See `beforeUpdatingObstacles` for the logic for the Y axis. // See `beforeUpdatingObstacles` for the logic for the Y axis.
} }
followCurrentPlatformOnX(timeDelta: float): boolean {
let hasMoved = false;
const object = this._behavior.owner;
// Shift the object according to the floor movement.
const floorX = this._floorPlatform!.owner.getX();
const deltaX = floorX - this._floorLastX;
if (deltaX !== 0) {
console.log(deltaX);
object.setX(object.getX() + deltaX);
this._floorLastX = floorX;
hasMoved = true;
}
return hasMoved;
}
checkTransitionBeforeY(timeDelta: float) { checkTransitionBeforeY(timeDelta: float) {
const behavior = this._behavior; const behavior = this._behavior;
// Go on a ladder // Go on a ladder

View File

@@ -694,7 +694,7 @@ describe('gdjs.PlatformerObjectRuntimeBehavior', function () {
expect(object.getBehavior('auto1').isFalling()).to.be(false); expect(object.getBehavior('auto1').isFalling()).to.be(false);
expect(object.getBehavior('auto1').isOnFloor()).to.be(true); expect(object.getBehavior('auto1').isOnFloor()).to.be(true);
expect(object.getY()).to.be.within(140.6297999, 140.6298001); expect(object.getY()).to.be.within(140.6297999, 140.6298001);
// TODO Remove the 1-frame delay // The floor following has a 1-frame delay.
expect(object.getX()).to.be(5); expect(object.getX()).to.be(5);
runtimeScene.renderAndStep(1000 / 60); runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.be(6); expect(object.getX()).to.be(6);

View File

@@ -68,7 +68,7 @@ describe('gdjs.PlatformerObjectRuntimeBehavior', function () {
runtimeScene.renderAndStepWithEventsFunction(1000 / 60, () => { runtimeScene.renderAndStepWithEventsFunction(1000 / 60, () => {
platform.setX(platform.getX() + 0.12); platform.setX(platform.getX() + 0.12);
}); });
// TODO Remove the 1-frame delay // The floor following has a 1-frame delay.
expect(object.getX()).to.be(0.24); expect(object.getX()).to.be(0.24);
runtimeScene.renderAndStep(1000 / 60); runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.be(0.36); expect(object.getX()).to.be(0.36);
@@ -258,13 +258,13 @@ describe('gdjs.PlatformerObjectRuntimeBehavior', function () {
// The object follow the platform // The object follow the platform
// The rounding error is probably due to a separate call. // The rounding error is probably due to a separate call.
// TODO Try to make it exact or find why // TODO Try to make it exact or find why
// TODO Remove the 1-frame delay // The floor following has a 1-frame delay.
expect(object.getY()).to.be.within( expect(object.getY()).to.be.within(
previousPlatformY - object.getHeight() - epsilon, previousPlatformY - object.getHeight() - epsilon,
previousPlatformY - object.getHeight() + epsilon previousPlatformY - object.getHeight() + epsilon
); );
} }
// TODO Remove the 1-frame delay // The floor following has a 1-frame delay.
expect(object.getX()).to.be(0 + 4 * deltaX); expect(object.getX()).to.be(0 + 4 * deltaX);
runtimeScene.renderAndStep(1000 / 60); runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.be(0 + 5 * deltaX); expect(object.getX()).to.be(0 + 5 * deltaX);
@@ -400,13 +400,13 @@ describe('gdjs.PlatformerObjectRuntimeBehavior', function () {
expect(object.getBehavior('auto1').isFalling()).to.be(false); expect(object.getBehavior('auto1').isFalling()).to.be(false);
expect(object.getBehavior('auto1').isMoving()).to.be(false); expect(object.getBehavior('auto1').isMoving()).to.be(false);
// The object must not be inside the platform or it gets stuck // The object must not be inside the platform or it gets stuck
// TODO Remove the 1-frame delay // The floor following has a 1-frame delay.
expect(object.getY()).to.be.within( expect(object.getY()).to.be.within(
previousPlatformY - object.getHeight() - epsilon, previousPlatformY - object.getHeight() - epsilon,
previousPlatformY - object.getHeight() + epsilon previousPlatformY - object.getHeight() + epsilon
); );
} }
// TODO Remove the 1-frame delay // The floor following has a 1-frame delay.
expect(object.getX()).to.be(0 + 4 * deltaX); expect(object.getX()).to.be(0 + 4 * deltaX);
runtimeScene.renderAndStep(1000 / 60); runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.be(0 + 5 * deltaX); expect(object.getX()).to.be(0 + 5 * deltaX);