Unreliable Tilemap collisions when spawning new physics objects

Hi there,

I’m having a weird arcade physics collisions issue.

You can see a codepen of the issue here:

I’m using a 16px x 16px tilemap and creating 16px little squares as bad guys. I set the x velocity on the baddie and setup a collision with tilemap and a callback. In the callback I check if the baddie is blocked (either left of right depending on the starting velocity and direction I sent them in) and if so I flip their x velocity thus making them turn around.

i.e. the baddies walk until they hit a wall, then they turn around and repeat. When I create a baddie in the create function this works great and as expected.

I’ve added a boss bad guy (which is a container with 16 sprites in) and when they get hit on the head they spawn a new baddie using exactly the same code as before. Firstly I had issues getting this large baddie to reliable collide with walls and turn around (it was turning around too early). I increased the frame rate and this fixed it.

The problem I’m having now is that the baddies that are spawned when you hit the boss baddie get stuck when they hit the wall - their body.blocked.left and body.blocked.right is never true, yet they can’t move because they’ve hit a wall!

I tried changing the frame rate and it seems to really affect it. If I drop the frame rate low enough I almost get the opposite effect - the baddies changing direction before they even hit a wall, so I guess it’s physics being out of sync?

Is there anything I can do to fix this? Am I coding this wrong? I tried having the check for the baddie collisions with the wall in the update loop as well but read that a physics collider was a much more reliable way of doing it?

‘createBaddies’ is called from the create function and creates one regular bad guy sprite and one giant one. You can see the code for creating a working baddie in there. The new baddies are spawned in the function ‘bossBaddieSpawn’ which is called from the collider callback ‘hitBossBaddie’

Thanks,

Tom

I think the problem is that when the sprite hits the wall there will be two collision calls (wall tile and floor tile) but you want to switch directions only once.

There are probably a few solutions but I think

gameScene.megaWallsCollider = function(baddie, walls) {
    if (baddie.body.velocity.x !== 0) return;
    // …
}

will work. Horizontal velocity is zero only after the horizontal collision.

Thanks for taking a look. I’ve added this and added a few console logs. I’ve set the FPS to 160 and if you leave it running and open the console you’ll see the boss baddie and baddie hit the wall, the collider fires, x velocities go to 0 and blocked.left or blocked.right is true as you’d expect.

If I change FPS to 120 then they hit invisible walls seemingly at random and change direction. The console logs show them having an x velocity of 0 and having a blocked.left or a blocked.right. If I change back to 160 FPS then this initial bit works.

Regardless of the frame rate I set the spawned baddies never detect a blocked.left or blocked.right, they just stop and the collider keeps on firing with only the blocked.bottom flag being detected.

If you hit the big boss by jumping on their head a new baddie is spawned. The console logs show that when this hits a wall it’s x velocity drops to 0 BUT it never has a blocked.left or blocked.right being set to true. It’s like it behaves completely differently if a baddie is spawned mid game.

I’ve setup a codepen here where I just look the x velocity in the physics colliders for the baddies and the walls. I’m keeping track on the baddies direction with a ‘direction’ property being either -1 (left) or 1 (right) and if I do it without any block checks it works fine:

So it looks like it’s the blocked flags that aren’t working properly? I found this post in the forums which seems like a similar thing - Body.blocked not working at low fps - #3 by jjcapellan

Idk if it’s causing problems, but I would change recalculateFaces to true in setCollisionBetween(), e.g.

this.map.setCollisionBetween(0, 600, true, true, "platforms");

I think this version works at any FPS:

1 Like

You’ve cracked it!

It does indeed now work at any FPS. I’ve had a good play around and works great with recalculateFaces set to true, and I can consistently break it by setting it to false.

Thanks Samme, you know your stuff. Much appreciated.

1 Like