1
\$\begingroup\$

I'm developing a 2D Top-down Game using HTML5 Canvas and a custom Game Engine. I'm implementing the Quad-intersection detection (Function below, if it helps) on different areas of the Sprites (As they're larger than Tiles in some cases), and have thought of an issue with this. I want to check these areas before moving, using the amount of pixels I will move if allowed to (Nothing blocking the character). Below if the code I use to move the Player:

move: function(delta) {
    var distance = Math.floor(this.getSpeed() * Math.floor(delta / 10));

    this.setMoving(false);

    if(Engine.input().isPressed(Engine.keys.LEFT_ARROW)) {
        this._config.x -= distance;

        this.setMoving(true);
        this.setDir(0);
    }
    if(Engine.input().isPressed(Engine.keys.RIGHT_ARROW)) {
        this._config.x += distance;

        this.setMoving(true);
        this.setDir(1);
    }
    if(Engine.input().isPressed(Engine.keys.UP_ARROW)) {
        this._config.y -= distance;

        this.setMoving(true);
        this.setDir(2);
    }
    if(Engine.input().isPressed(Engine.keys.DOWN_ARROW)) {
        this._config.y += distance;

        this.setMoving(true);
        this.setDir(3);
    }

    this.boundaries();
}

As the distance is not 1 pixel, it will be checking a few pixels ahead of the Player for solid tiles, and if there is one X many pixels in front of them, they can't move the distance and stop.

Problem

So - let's say the distance is 3. If they're 2 pixels from a Solid Tile, they will not move those 2 pixels because of the collision detection, meaning there will be a 2 pixel gap between the Player and the tile, which will only increase the larger the Player, or Entities, speed.

Is there any way to get around this, other than having to check pixel-by-pixel for each anchor point I want to check collision on?

Collision Detection

collided: function(box1, box2) { // Basic Quad-intersection Collision
    return (
        ( (box1.x >= box2.x && box1.x <= (box2.x + box2.width) ) ||
        ( (box1.x + box1.width) >= box2.x && (box1.x + box1.width) <= (box2.x + box2.width) ) ) &&
        ( (box1.y >= box2.y && box1.y <= (box2.y + box2.height) ) ||
        ( (box1.y + h1) >= box2.y && (box1.y + h1) <= (box2.y + box2.height) ) )
    ) ? true : false;
},
\$\endgroup\$
2
\$\begingroup\$

There's a couple of things you can do in this case:

  1. Move the player sprite then resolve collisions. For simple 2D games you should probably use impulse resolution. The gist is that you move the player sprite, figure out what it is colliding with, then move the player sprite the shortest distance out of the colliding bounding box so that it isn't colliding anymore. This is a super common method of handling this that is used in many game engines. You can make this more complicated by taking the two objects' masses into account or just moving the player sprite if it is colliding with terrain.

  2. Only move the player sprite enough so that it isn't colliding in the first place. If you know exactly what the player sprite is going to hit (as is common in the case of tile maps), then don't move the player sprite the full distance -- just enough so that the collision takes place, then set the player sprite velocity to 0. This is basically like #1, but might be simpler depending on what the rest of your physics code looks like.

Some useful terms that'll help with later Googling include: AABB (axially-aligned bounding box), collision resolution.

\$\endgroup\$
  • \$\begingroup\$ Thanks man, this is great information. I'll attempt implementing the first one you've suggested, I can't see the second one being easy or feasible for me right now. Thanks again! \$\endgroup\$ – Oyed Dec 31 '13 at 16:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.