Collision detection and correction (Again, Javascript, not Java)

Hey folks,

This is Javascript <— For those that doesn’t read the title all the way through

So I’ve got a working method for detecting collisions and it’s working pretty good™, though the position correction causes weird artifacts, such as:

  • When falling near a wall, you can “walk” towards it, and thus cling to it
  • Walking over an edge and quickly walking the other direction brings you back on top of the platform(sometimes with a little jump).

Here’s the code for collision detection:

var CollisionManager = {};

/**
 * Axis-Aligned Bounding Box collision test
 * @returns {Boolean} Whether there was a collision or not
 */
CollisionManager.boolAABB = function(a, b) {
    if(Math.abs(a.position.x - b.position.x) >= (Math.abs(a.width) + Math.abs(b.width)) / 2) {
        return false;
    }
    if(Math.abs(a.position.y - b.position.y) >= (Math.abs(a.height) + Math.abs(b.height)) / 2) {
        return false;
    }

    return true;
};

/**
 * Axis-Aligned Bounding Box collision test
 * @returns {Boolean|null} The direction of the collision or undefined if no collision
 */
CollisionManager.AABB = function(a, b) {
    if(!CollisionManager.boolAABB(a, b)) {
        return;
    }

    // x and y distances from the center
    var xd = Math.abs(a.position.x - b.position.x);
    var yd = Math.abs(a.position.y - b.position.y);

    // The minimum width to be seperated
    var cw = (Math.abs(a.width) + Math.abs(b.width)) / 2;
    var ch = (Math.abs(a.height) + Math.abs(b.height)) / 2;

    // Amount of overlap
    var ox = Math.abs(xd - cw);
    var oy = Math.abs(yd - ch);

    // Direction of the collision
    var dir = new Vec2D(a.x, a.y);
    dir = dir.sub(b);
    dir = dir.normalize();

    if(ox > oy) {
        return new Vec2D(0, dir.y * oy);
    } else if(ox < oy) {
        return new Vec2D(dir.x * ox, 0);
    }

    return new Vec2D(dir.x * ox, dir.y * oy);
};

So, if there is a collision, it’ll give me the direction and distance to move my object to get out of the collision.

Here’s the code that tries to move my player:


function tryToMove(d) { // d the velocity vector, divided into steps
    move(d);
    for(var i = 0; i < adventure.entities.length; i++) {
        var entity = adventure.entities[i];
        if(entity.isPassable === true) {
            continue;
        }

        var dv = CollisionManager.AABB(_this, entity);
        if(dv !== undefined) {
            entity.hit(dv);
            move(dv); // Move back out of the collision
        }
    }
}

And the bit that cuts the velocity vector and calls tryToMove():


var steps = Math.max(Math.abs(this.velocity.x), Math.abs(this.velocity.y));
var distance = this.velocity.div(steps);

for(var i = 0; i < steps; i++) {
    tryToMove(distance);
}

Sooo, any thoughts on how to fix the above issues?

Cheers! :slight_smile:

If you aren’t already I suggest you use some of the available (and very good) libraries that practically all come with basic and customisable collision frameworks instead of going full vanilla mode like in the early 2000’s.

[EDIT]: I used createjs for instance on ld29 that I never finished: http://jin.fi/ld29/ld29.html (just right-click and view page source for source)

I really only need collision detection and correction. I’m already using pixi.js for rendering, 'cause it has support for Spine, and I’m using howler.js for sound.

And my collision detection works like a charm, there’s never a time that it doesn’t detect a collision, only times where it makes the char act weird, e.g. letting it get back up on a platform even though it shouldn’t be able to, or cling to walls.