RichJ Posted March 19, 2017 Share Posted March 19, 2017 Hi, I'm new to Phaser, but a seasoned games programmer. Seems like a great framework so far, but I'm experiencing a glitch in the Arcade physics engine which I'm not sure is a bug, or down to the way I'm manipulating the body's velocity in code. I've setup a sprite object and strips of horizontal & vertical wall blocks, all of which are enabled in the physics engine. The walls are immovable. If I move my sprite up, it will eventually hit a wall, but with the up key held I can still use the left & right keys to move the sprite smoothly against the wall. If I do the same thing against the vertical wall, the up and down movements get stuck at the edge of some of the wall blocks if I keep the right key pressed. Here's a example... http://cam64.net/temp/phaser/default.html ...and here's the code. Is it a bug, or am I doing something wrong? var game = new Phaser.Game(800, 600, Phaser.AUTO, '', { preload: preload, create: create, update: update }); var walls; var player; function preload() { game.load.image('playerImage', 'Images/sprite.png'); game.load.image('wallImage', 'Images/block.png'); } function create() { // Start physics engine game.physics.startSystem(Phaser.Physics.ARCADE); // Setup walls group walls = game.add.group(); walls.enableBody = true; // Create horizontal and vertical wall blocks for (i = 0; i < 9; i++) { var w1 = walls.create(i * 64, 0, 'wallImage'); w1.body.immovable = true; var w2 = walls.create(576, i * 64, 'wallImage'); w2.body.immovable = true; } // Create player player = game.add.sprite(250, 250, 'playerImage'); game.physics.arcade.enable(player); player.body.maxVelocity.setTo(300, 300); player.body.collideWorldBounds = true; } function update() { cursors = game.input.keyboard.createCursorKeys(); // Move left and right if (cursors.left.isDown) { player.body.velocity.x -= 50; } else if (cursors.right.isDown) { player.body.velocity.x += 50; } else { player.body.velocity.x = 0; } // Move up and down if (cursors.up.isDown) { player.body.velocity.y -= 50; } else if (cursors.down.isDown) { player.body.velocity.y += 50; } else { player.body.velocity.y = 0; } // Update collisions game.physics.arcade.collide(player, walls); } samid737 1 Link to comment Share on other sites More sharing options...
RichJ Posted March 20, 2017 Author Share Posted March 20, 2017 Anyone else experienced this, even if it hasn't been resolved? It's kind of a deal breaker, quite surprised that the arcade physics engine fails in such a simple scenario, hence I'm thinking I've done something wrong Link to comment Share on other sites More sharing options...
samid737 Posted March 20, 2017 Share Posted March 20, 2017 Looks very strange, maybe you could inspect the collision bodies? https://phaser.io/examples/v2/arcade-physics/body-debug But it definitely looks and smells like a glitch:p... Link to comment Share on other sites More sharing options...
RichJ Posted March 20, 2017 Author Share Posted March 20, 2017 Thanks for the tip, I didn't realise you could display all that debug info. It doesn't show anything up though. Really odd how the problem only occurs when brushing up against the vertical wall. Link to comment Share on other sites More sharing options...
drhayes Posted March 20, 2017 Share Posted March 20, 2017 This is a common fail state in 2d physics engines. The engine usually has to have special code to overcome this. Phaser's special code is in its Tilemap implementation. I would suggest making your blocks a Tilemap (even if you have to generate it dynamically) and going from there. What's happening is that the physics engine tries to move your sprite by its velocity. Each dimension (x and y) are exactly the same mathematically: add the velocity * time delta to the position and you're done. However, there are two components to velocity, so which one do we do first? Phaser picks a really common one: do y first (we're more often standing on floors than sliding down walls, if you get me). The side effect is that your sprites can catch on edges like you're seeing. Since the sprite's velocity is, say, (5, 5) the sprite's AABB body tries to move diagonally downwards to the right. First we check y, then we check x. Checking y we see that the wall is there, intersecting the right side of our AABB body! So we stop downwards movement entirely. And there's your bug. The best way around this that I know (and that Phaser uses in its Tilemap implementation) is to declare particular edges in a map as "uninteresting" so they don't get checked for collision. The most important edge in your wall of solid vertical tiles is the left one, not each edge between each adjacent tile. This prevents the problem from happening. But Phaser doesn't want to generalize that behavior across a bunch of individual sprites for performance reasons. Sprites move all the time, have different sizes, etc. Ah, but Tilemaps! All the same size, all not moving. And there you go. Here's the function in Tilemap that does just what I described and finds "interesting" edges on Tiles. It saves them by modifying the tiles' face* properties. samid737 and RichJ 2 Link to comment Share on other sites More sharing options...
samid737 Posted March 20, 2017 Share Posted March 20, 2017 @drhayes very interesting! Link to comment Share on other sites More sharing options...
RichJ Posted March 20, 2017 Author Share Posted March 20, 2017 Thanks for the detailed post @drhayes, I've looked into Tilemaps and got it all up and running perfectly. I was yet to come across Tilemaps, still only a few days into Phaser, so I'd fallen into the trap of going against the framework by trying to build up my tile map manually. Can't believe how simple it is to implement a map exported as JSON from the Tiled map editor Shame about the physics bug, but I understand what you're saying. I wrote a very simple 2D physics engine a few months ago for a Monogame project and ran into pretty much the same problem. Thanks again Link to comment Share on other sites More sharing options...
samme Posted March 20, 2017 Share Posted March 20, 2017 I think you could try game.physics.arcade.collide(player, walls); var touching = player.body.touching; var cursors = game.input.keyboard.createCursorKeys(); if (cursors.left.isDown && !touching.left ) player.body.velocity.x -= 50; else if (cursors.right.isDown && !touching.right) player.body.velocity.x += 50; else player.body.velocity.x = 0; if (cursors.up.isDown && !touching.up ) player.body.velocity.y -= 50; else if (cursors.down.isDown && !touching.down) player.body.velocity.y += 50; else player.body.velocity.y = 0; Link to comment Share on other sites More sharing options...
RichJ Posted March 20, 2017 Author Share Posted March 20, 2017 Thanks @samme , I tried reading the "touching" properties but that didn't work either. The debug info showed the touching properties being set every other frame. Link to comment Share on other sites More sharing options...
Recommended Posts