Ppozniak

Hitting a wall should make you fall down (arcade physics)

Recommended Posts

Hello there.

I am dealing for a long time with this issue.

I am making an endless runner where platforms are made from small chunks (each 32x32 square).

Character should fall down, not stop on the wall.

helpmeplease.gif.98be383f6a53cc83b8bd2d1493b8e2a3.gif

This also happens when chunks don't have any velocity, until I add

if( this.body.touching.right ) {
  this.body.velocity.x = 0;
  this.body.acceleration.x = 0;
}

to the player sprite.

 

When I don't apply velocity to the chunks but instead say this.left -= 10 on chunk group in update the things are get more weird

reallyhelpmeplease.gif.a165bea906f3164d7780f708b12f612e.gif

 

I guess that has to do something with chunks, am I doing this in wrong way?

Each platform is a group, to which I add those chunks

export default class Platform extends Phaser.Group {
  constructor(game, _) {
    super(game);

    const defaults = {
      startX: 0,
      startY: game.height - 64,
      width: game.width * .3,
      tileLevel: 1,
      tileFrame: 8,
    };

    this.state = {
      extended: false
    };

    _ = Object.assign({}, defaults, _);

    this.physicsBodyType = Phaser.Physics.ARCADE;
    this.enableBody = true;

    // Y axis
    for(let y = _.startY; y <= game.height + game.global.tileSize; y += game.global.tileSize) {
      // X axis
      _.tileLevel === 1 ? _.tileFrame = 8 : _.tileFrame = 1;
      for( let x = 0; x < _.width; x += game.global.tileSize ) {
        this.create(x + _.startX, y, 'tileset', _.tileFrame);
      }
      _.tileLevel++;
    }

    const BODY_OFFSET = 4;
    this.forEach((child) => {
      child.body.immovable = true;
      child.body.allowGravity = false;
      child.body.offset.y = BODY_OFFSET;
      child.body.friction.set(0);
      child.body.velocity.x = -10;
    }, this);
  }

  update() {
    // Spawn another platform
    if ((this.left <= this.game.width) && (!this.state.extended)) {
      this.state.extended = true;
      this.game.global.spawnPlatform.dispatch(this.right);
    }

    // Destroy when off bounds
    if(this.right < 0) {
      this.destroy();
    }
  }
}

 

Best regards.

Share this post


Link to post
Share on other sites

Thanks for your reply @ncil

I have a simple .collide method, nothing else applied at the moment:

    this.game.physics.arcade.collide(this.player, this.platforms.children);

 

While platforms is another group that has platform instances inside

 

import Platform from './Platform';

export default class Platforms extends Phaser.Group {
  constructor(game) {
    super(game);

    this.game.add.existing(this);
    this.game.global.spawnPlatform = new Phaser.Signal();
    this.game.global.spawnPlatform.add(this._spawnPlatform, this);

    this._init();
  }

  // Create initial ground
  _init() {
    this.add(new Platform(this.game, {
      width: this.game.width * .5
    }));
  }

  // Spawns platform
  _spawnPlatform(prevRight = 0) {
    const RAND_Y = this.game.rnd.integerInRange(200, 400),
          GAP = this.game.rnd.integerInRange(0, 200),
          RAND_WIDTH = this.game.rnd.integerInRange(150, 700);

      this.add(new Platform(this.game, {
        startX: prevRight + GAP,
        startY: this.game.height - RAND_Y,
        width: RAND_WIDTH,
      }));
  }
}

Just adding this in case this matters. Hope that makes sense.

 

Best regards.

Share this post


Link to post
Share on other sites

In the collision method, why do you use this.platforms.children instead of just this.platforms? I don't think it makes a difference but I am just curious.

How are you controlling the player? I'm confused why you are setting the player's velocity and the platform's velocity...

Share this post


Link to post
Share on other sites

You need to use a nonzero velocity to create movement instead of setting left or position, etc., otherwise the collisions won't work.

Often when you use sprite "tiles" packed together like this the player can be stuck on a vertical edge. phaser-plugin-debug-arcade-physics can show you where it's touching. You can try any of:

  • Increase player.body.bounce.x from 0.
  • Set body.checkCollision.*=false (top, bottom, etc.) on all the interior edges.
  • Use a single physics body for each platform.

Share this post


Link to post
Share on other sites

@ncil that's because platforms is a group, which has another groups inside (platform).  And in documentation you can find (collide method) https://photonstorm.github.io/phaser-ce/Phaser.Physics.Arcade.html#collide

Quote

This function is not recursive, and will not test against children of objects passed (i.e. Groups or Tilemaps within other Groups).

Velocity on blocks makes an illusion of that the only player is moving, but I don't want the player to only stand and jump so he can move around (like he was slowing down or running faster in real life, but he is always running). Could've done with camera, and stage, but can be also done this way.

 

@samme thanks for the tip. Unfortunately it still doesn't work as intended, however it happens much less often and not so "hard". Seems that removing collision from inner blocks has speed up the game significantly. My theory is that some blocks move faster than others and that's why it creates really tiny floor, because when I was debugging that before touching.right and touching.down were true, while player was on side of a wall.

I am not sure about your last point 

  • Use a single physics body for each platform.

What do you mean by that? You cannot apply physics to group, so I'm kinda confused. Or maybe there is a way to create body? So tiles would be tiles, but then I would apply one big "fake" body that would cover all of the blocks? If that's what you meant I am not quite sure how to achieve that.

#Edit I've tried making an empty sprite, then apply body to that and make it as long as the tiles, same with height and it's working pretty good! Never thought of making empty sprite, which is kind of silly in terms of logic I guess? However thanks for the help!

 

Best regards.

Share this post


Link to post
Share on other sites
16 hours ago, Ppozniak said:

@ncil that's because platforms is a group, which has another groups inside (platform).  And in documentation you can find (collide method) https://photonstorm.github.io/phaser-ce/Phaser.Physics.Arcade.html#collide:

Thanks for the explanation :)

Glad you got it working! I think the blank/empty sprite is a good way to tackle it. I wonder if you might also be able to make use of tile sprites? https://phaser.io/examples/v2/category/tile-sprites

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.