Sign in to follow this  
Growler

Collision detection for outer collision shape: weird detection

Recommended Posts

@Parasyte

@obiot

Using the latest version of MelonJS, I'm using an outer bounding box for interaction range with NPCs, and an inner bounding box for collision.

When the player's outer bounding box overlaps an NPC, it repeats "Collision" and "No Collision" in succession even if I haven't move the player's outer bounding box away from the NPC. Shouldn't !me.collision.check(this) return true only if there's no collision? 

In the image below, the blue square is the player, the green square is the NPC.

Why is this happening?

Console.log:

NO COLLISION

COLLISION

COLLISION

NO COLLISION

COLLISION

game.PlayerEntity = me.Entity.extend({ ... }): two bounding boxes for Player entity:

        // indexShapeA: 0 - Set collision shape and anchor it to bottom half of Player
        this.body.removeShape(this.body.getShape(0));
        this.body.addShape(new me.Rect(0, 0, settings.width * 2, settings.height));
        this.anchorPoint.set(0, 0);

        // indexShapeA: 1 - Interaction bubble: set the larger outside bounding box for the player
        this.body.addShape(new me.Rect(0, 0, settings.width * 4, settings.height * 2));
        this.anchorPoint.set(0.5, 0.5);

 

game.NPCEntity = me.Entity.extend({ ... }):

    update: function (dt) {
        // handle collisions against other shapes
        if (!me.collision.check(this)) {
            console.log('NO COLLISION');
        }

        // return true if we moved
        return (this._super(me.Entity, "update", [dt]) || this.body.vel.x !== 0 || this.body.vel.y !== 0);
    },

    /**
     * Collision handler
     * @param  {[type]} response [description]
     * @param  {[type]} other    [description]
     * @return {[type]}          [description]
     */
    onCollision : function (response, other) {
        console.log('COLLISION');

        // Make the object solid
        return true;
    }

 

Screen Shot 2018-04-25 at 9.58.43 PM.png

Share this post


Link to post
Share on other sites

I think what you're seeing has something to do with the misunderstanding of collision shapes on a body. Collision detection does not happen on a "per-shape basis", but on a "per-body basis". In short, bodies collide with other bodies, not with shapes. The shapes are only there to add a physical structure to the body. Under this axiom, it doesn't make sense to have a large rectangle with a smaller inner rectangle, because only the larger rectangle "matters" when performing collision detection.

Secondly, you are using two competing collision processes and expecting them to operate independently (I guess). In reality, they are just two sides of the same feature; the me.collision.check() call is the caller, and the onCollision handler is the callee. Obviously, the check ignores itself, but it will call onCollision on the same object in addition to other objects that implement the handler. What you're seeing in the console log is this exact behavior: one of the entities somewhere in the scene is not colliding with anything, and somewhere else, two or more entities are colliding.

Thirdly, the scenario that you are testing is artificial, since it should not be possible (under normal circumstances) to end up with two solid entities in the configuration shown in the screenshot. What I mean by artificial is that you have set explicit coordinates to "force" the smaller entity inside the larger one. If they were moved using only the physics properties such as velocity, they would instead repel one another by responding to the collision; adjusting the velocities to counteract any motion that would result in overlapping like that.

I believe that describes the situation, at least in short. To fix it, you want to use the collision detection system only as a way to respond to collisions (e.g. pushing solid entities apart, taken damage from projectiles, etc.) and use something else like distanceTo() for the interaction range. You can use me.collision.quadTree.retrieve() to gather a list of potential candidates for performing distance checks.

edit: I had mistakenly asserted that onCollision will not be called on the same object that calls me.collision.check(). The handler is definitely called on both entities when they collide. You can see the implementation here: https://github.com/melonjs/melonJS/blob/97ede483f5798651e7a7c225df2bb77df66a4a27/src/physics/collision.js#L486-L492

Share this post


Link to post
Share on other sites

@Parasyte RE: "Under this axiom, it doesn't make sense to have a large rectangle with a smaller inner rectangle, because only the larger rectangle "matters" when performing collision detection." 

I actually got this idea from you guys. In the old forum, on 2/16/16, post title "[melonjs:10815] Proximity detection for multiple entity instances causing issues" , I asked about wonky collision and the response is shown in the attached image, but Aaron and melonJS basically said:

"even more simple  ! Just add a second body shape to your entity, a bigger one that define the region used of "interacting"".

And

"Another technique you can use too is to create an instance of me.Rect for your player & npcs. Set the size of them as you want, and position them so the center of the rect is in the center of the player. As the player translates, translate the rect with it (this is why I want to support more scene graph stuff with melon), then check if the rect intersects with the rect of an NPC. That way you're not hard coding distances as much. You're using a separate bounding box instead."

RE: "Thirdly, the scenario that you are testing is artificial..."

I haven't set explicit coordinates, I simply return False if response.indexShapeA === 1; (aka the outer bounding box) and True if response.indexShapeA === 0; (aka the inner bounding box). This allows the outer bounding box of the player and the NPC to pass through each other (this is what I want as the outer box simply detects proximity).

RE: Collision — No Collision — Collision thing

Oops that was dumb. Console.logging the ID of the NPCs shows that the NPC I'm currently colliding with is ALWAYS colliding, and other NPCs are not colliding on the screen. My bad. 

Screen Shot 2018-04-25 at 11.07.54 PM.png

Screen Shot 2018-04-25 at 11.17.03 PM.png

Share this post


Link to post
Share on other sites

The code in the OP shows that you return true from the collision handler unconditionally. (Remember, this is the only information I have to go on! I can't see all of your code, and I definitely don't see any conditions checking the shape index.) Which means it would apply the collision response (repel the entities by adjusting the velocity). The code I linked above shows how it calls respondToCollision on the body when the collision handler returns true. And this method adjusts the velocity accordingly. Thus, my observation.

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
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.