Hi all. I am currently recreating a Shockwave 2D platformer game using Phaser3 (Hannah and the Pirate Caves from Neopets, if anyone is familiar), and am attempting to nail down the way in which game objects interact. Specifically, there are arrow crates & boulders in the game that obey the following rules:
- When an arrow crate breaks, it generates an arrow that flies in a direction will break an object it hits. There is a slight delay here.
- When an object breaks or falls, there is a slight delay before the object above it begins to fall
- When a boulder lands, the boulder will roll to either side depending on whether the path is clear
I have successfully implemented this using delayedCalls. Here are some code snippets:
// Arrow crate collider
this.physics.add.collider(this.arrows, this.arrowCollisionObjects, null, (a, o) => {
// Set a small delay so that a cascade of arrows will actually cascade, not all burst simultaneously
this.time.delayedCall(75, (o, collisionDirection) => {
this.destroyWoodCrate(o, collisionDirection);
}, [o, collisionDirection], this);
}
// This method is called when an object starts to fall - triggers the object above it to fall as well
triggerObjectGravityEvent(x, y, delay) {
this.time.delayedCall(delay, (x, y) => {
const gravityCapableObjects = [...this.woodenCrates, ...this.boulders, ...this.metalCrates, ...this.treasures, ...this.gemCrates];
gravityCapableObjects.forEach((object) => {
if (!object.active || object.body.allowGravity) {
return;
}
const xCheck = Math.abs(object.x - x) < 12;
const yCheck = Math.abs(object.y - y + 32) < 12;
if (xCheck && yCheck) {
object.body.allowGravity = true;
this.triggerObjectGravityEvent(object.x, object.y, 300);
}
})
}, [x, y], this)
}
I’ve uploaded a short video of the current behavior to Youtube here: https://www.youtube.com/watch?v=U0tggW6YDUI.
The problem demonstrated in this video is that the behavior is inconsistent across runs. Sometimes boulders will fall in a certain pattern, and sometimes in a different pattern. I believe this is due to the way I chain together delayedCalls. The 75 millisecond delay between arrow crates breaking or 300 millisecond delay between objects falling may have some slight imprecision, and be off by a few millisecond with each call. But these milliseconds add up and result in different game behavior (e.g., nearby boulders will fall slightly earlier in some runs, causing them to pile up differently).
How precise is delayedCall supposed to be? Are there any more precise options? Does anyone have any tips on how I can improve the consistency of the game behavior?