CruelYodeler Posted July 15, 2014 Share Posted July 15, 2014 I'm creating a game which contains simple puzzles. Early on, the player will have to push some crates out of the way to continue on. In my code here, I have two crates stacked on top of each other. As expected, when the player pushes against the bottom crate, it moves out of the way and the one on top falls to the ground. Now, this is where it gets tricky. I want there to be a delay once the player has collided with the crate before the crate can be pushed. I use "timers" (not really timers, but counters incremented in the update() function) to determine when to start playing the animation that shows the player pushing against the crates and when to actually start pushing the crates. I tried giving the crates a lot of mass to prevent the player from pushing them, but that causes the crates to go zooming away super fast from the player. I could use a little help figuring this out. I've tried a lot of different things but with no luck. I had a solution before which toggled the crates' immovable state, but that prevented the top box from falling after the bottom box was pushed out. function create() { game.world.setBounds(0, 0, 2000, 600); game.physics.startSystem(Phaser.Physics.ARCADE); solidPlatforms = game.add.group(); pushablePlatforms = game.add.group(); solidPlatforms.enableBody = true; pushablePlatforms.enableBody = true; var ground = solidPlatforms.create(0, game.world.height - 64, 'ground'); ground.scale.setTo(5, 2); ground.body.immovable = true; // two moveable crates crate = pushablePlatforms.create(310, game.world.height - 142, 'crate1'); crate.body.gravity.y = 600; crate = pushablePlatforms.create(300, game.world.height - 221, 'crate2'); crate.body.gravity.y = 600; pushablePlatforms.setAll('body.mass', 99); player = game.add.sprite(41, game.world.height - 130, 'robot'); game.physics.arcade.enable(player); player.body.bounce.y = 0.2; player.body.gravity.y = 600; player.body.collideWorldBounds = true; // Set player direction to the right direction = 'right'; // Pushing animations, left and right player.animations.add('push-left', [8, 9, 10, 11], 6, true); player.animations.add('push-right', [12, 13, 14, 15], 6, true); // Moving animations, left and right player.animations.add('left', [0, 1, 2, 3], 10, true); player.animations.add('right', [4, 5, 6, 7], 10, true); player.body.setSize(37, 51, 2, 4); // Initialize push timers pushLeftTimer = 0; pushRightTimer = 0; cursors = game.input.keyboard.createCursorKeys(); game.camera.follow(player, Phaser.Camera.FOLLOW_PLATFORMER); } function update() { game.physics.arcade.collide(player, solidPlatforms); game.physics.arcade.collide(player, pushablePlatforms, platformCollisionHandler, null, this); game.physics.arcade.collide(pushablePlatforms, solidPlatforms); game.physics.arcade.collide(pushablePlatforms, pushablePlatforms); player.body.velocity.x = 0; if (cursors.left.isDown) { // Set player direction to left direction = 'left'; player.body.velocity.x = -150; pushRightTimer = 0; if (player.body.touching.left && player.body.touching.down) // Can only push while touching the ground pushLeftTimer++; if (pushLeftTimer > 15 && player.body.touching.down) { // Play the pushing animation player.animations.play('push-left'); } else { stopPushingPlatforms(); player.animations.play('left'); } } else if (cursors.right.isDown) { // Set player direction to right player.body.velocity.x = 150; pushLeftTimer = 0; if (player.body.touching.right && player.body.touching.down) // Can only push while touching the ground pushRightTimer++; if (pushRightTimer > 15 && player.body.touching.down) { // Play the pushing animation player.animations.play('push-right'); } else { stopPushingPlatforms(); player.animations.play('right'); } } else { // Stand still player.animations.stop(); // Stop pushing objects stopPushingPlatforms(); // Reset both push timers pushRightTimer = 0; pushLeftTimer = 0; // Reset player frame if (direction == 'right') { player.frame = 4; } else { player.frame = 0; } } // Allow the player to jump if they are touching the ground. if (cursors.up.isDown && player.body.touching.down) { // Reset both push timers pushRightTimer = 0; pushLeftTimer = 0; player.body.velocity.y = -350; } } function platformCollisionHandler(obj1, obj2) { if (obj1.body.touching.down) { if (pushRightTimer >= 80) obj2.body.mass = 1; else if (pushLeftTimer >= 80) obj2.body.mass = 1; else obj2.body.mass = 999; } } function stopPushingPlatforms() { for (var i = 0; i < pushablePlatforms.children.length; i++) { var platform = pushablePlatforms.children[i]; platform.body.velocity.x = 0; } } Link to comment Share on other sites More sharing options...
lewster32 Posted July 15, 2014 Share Posted July 15, 2014 Mass I believe is only used to calculate how much momentum is transferred between two colliding objects, and doesn't work for constant forces such as this. Instead I think you could maybe temporarily zero the player's velocity.x when pushing against a crate, and then return it to normal after the timer ends so the player can then start pushing. Also I think what you need to use is the body.drag property, which is basically the object's 'friction'. Setting the drag to high values will let you push objects but they will come to a stop very quickly - which means you can drop the 'stopPushingPlatforms' function. Link to comment Share on other sites More sharing options...
lewster32 Posted July 15, 2014 Share Posted July 15, 2014 I've been playing with this for a little bit and come up with a quick, dirty and wholly unsatisfying solution: http://jsfiddle.net/lewster32/ba8x3/ It may serve as a start, but it has issues; crates can get pushed 'through' other crates, for instance. I feel a simpler and better solution is flittering around in my head somewhere but I can't seem to get at it right now. Link to comment Share on other sites More sharing options...
CruelYodeler Posted July 16, 2014 Author Share Posted July 16, 2014 Your JSFiddle helped point me in the right direction I think. body.moves was the key. I have a solution that's working for the most part; I'll post my solution later when I've had a chance to clean it up. Thanks for your help! lewster32 1 Link to comment Share on other sites More sharing options...
CruelYodeler Posted July 19, 2014 Author Share Posted July 19, 2014 I had to scrap my solution because the physics were so buggy. I think your solution is definitely the way to go; there's just the one bug. I was able to determine that the crates don't trigger the collision handler (I added one to the collide function for the crates) when their sides touch. Even body.touching.left and body.touching.right return false for both crates. Link to comment Share on other sites More sharing options...
Recommended Posts