Impact

This forum is read only and just serves as an archive. If you have any questions, please post them on github.com/phoboslab/impact

4 years ago by AndrewMast

Is there a way for "2.5D" advanced collision?

I overwrote the following from entity.js in a different file.

ig.Entity.checkPair = function( a, b ) {

        // Do these entities want checks?
        if( a.checkAgainst & b.type ) {
            a.check( b );
        }

        if( b.checkAgainst & a.type ) {
            b.check( a );
        }

        // If this pair allows collision, solve it! At least one entity must
        // collide ACTIVE or FIXED, while the other one must not collide NEVER.
        if (a.collides && b.collides) {
            ig.Entity.solveCollision( a, b );
        }
    };
    
    ig.Entity.solveCollision = function( a, b ) {

        // If one entity is FIXED, or the other entity is LITE, the weak
        // (FIXED/NON-LITE) entity won't move in collision response
        var weak = null;
        
        if (-1 * a.collides == b.collides) {
            weak = "none";
        } else if (a.collides == 9 || Math.abs(a.collides) > Math.abs(b.collides)) {
            weak = b;
        } else if (b.collides == 9 || Math.abs(a.collides) < Math.abs(b.collides)) {
            weak = a;
        }

        // Did they already overlap on the X-axis in the last frame? If so,
        // this must be a vertical collision!
        if(
            a.last.x + a.size.x > b.last.x &&
            a.last.x < b.last.x + b.size.x
        ) {
            // Which one is on top?
            if( a.last.y < b.last.y ) {
                if (weak != "none") {
                    ig.Entity.seperateOnYAxis( a, b, weak );
                }
            }
            else {
                if (weak != "none") {
                    ig.Entity.seperateOnYAxis( b, a, weak );
                }
            }
            a.collideWith( b, 'y' );
            b.collideWith( a, 'y' );
        }

        // Horizontal collision
        else if(
            a.last.y + a.size.y > b.last.y &&
            a.last.y < b.last.y + b.size.y
        ){
            // Which one is on the left?
            if( a.last.x < b.last.x ) {
                if (weak != "none") {
                    ig.Entity.seperateOnXAxis( a, b, weak );
                }
            }
            else {
                if (weak != "none") {
                    ig.Entity.seperateOnXAxis( b, a, weak );
                }
            }
            a.collideWith( b, 'x' );
            b.collideWith( a, 'x' );
        }
    };
    
    ig.Entity.seperateOnXAxis = function( left, right, weak ) {
        var nudge = (left.pos.x + left.size.x - right.pos.x);

        // We have a weak entity, so just move this one
        if( weak ) {
            var strong = left === weak ? right : left;
            weak.vel.x = -weak.vel.x * weak.bounciness + strong.vel.x;

            var resWeak = ig.game.collisionMap.trace( 
                weak.pos.x, weak.pos.y, weak == left ? -nudge : nudge, 0, weak.size.x, weak.size.y
            );
            weak.pos.x = resWeak.pos.x;
        }

        // Normal collision - both move
        else {
            /*var v2 = (left.vel.x - right.vel.x)/2;
            left.vel.x = -v2;
            right.vel.x = v2;

            var resLeft = ig.game.collisionMap.trace( 
                left.pos.x, left.pos.y, -nudge/2, 0, left.size.x, left.size.y
            );
            left.pos.x = Math.floor(resLeft.pos.x);

            var resRight = ig.game.collisionMap.trace( 
                right.pos.x, right.pos.y, nudge/2, 0, right.size.x, right.size.y
            );
            right.pos.x = Math.ceil(resRight.pos.x);*/
            
            var vel = 0;
            
            if (Math.abs(left.vel.x) > Math.abs(right.vel.x)) {
                vel = left.vel.x
            }
            
            if (Math.abs(left.vel.x) < Math.abs(right.vel.x)) {
                vel = right.vel.x
            }
            
            left.vel.x = vel;
            right.vel.x = vel;
        }
    };

    ig.Entity.seperateOnYAxis = function( top, bottom, weak ) {
        var nudge = (top.pos.y + top.size.y - bottom.pos.y);

        // We have a weak entity, so just move this one
        if( weak ) {
            var strong = top === weak ? bottom : top;
            weak.vel.y = -weak.vel.y * weak.bounciness + strong.vel.y;

            // Riding on a platform?
            var nudgeX = 0;
            if( weak == top && Math.abs(weak.vel.y - strong.vel.y) < weak.minBounceVelocity ) {
                weak.standing = true;
                nudgeX = strong.vel.x * ig.system.tick;
            }

            var resWeak = ig.game.collisionMap.trace( 
                weak.pos.x, weak.pos.y, nudgeX, weak == top ? -nudge : nudge, weak.size.x, weak.size.y
            );
            weak.pos.y = resWeak.pos.y;
            weak.pos.x = resWeak.pos.x;
        }

        // Bottom entity is standing - just bounce the top one
        else if( ig.game.gravity && (bottom.standing || top.vel.y > 0) ) {	
            var resTop = ig.game.collisionMap.trace( 
                top.pos.x, top.pos.y, 0, -(top.pos.y + top.size.y - bottom.pos.y), top.size.x, top.size.y
            );
            top.pos.y = resTop.pos.y;

            if( top.bounciness > 0 && top.vel.y > top.minBounceVelocity ) {
                top.vel.y *= -top.bounciness;		
            }
            else {
                top.standing = true;
                top.vel.y = 0;
            }
        }

        // Normal collision - both move
        else {
            /*var v2 = (top.vel.y - bottom.vel.y)/2;
            top.vel.y = -v2;
            bottom.vel.y = v2;

            var nudgeX = bottom.vel.x * ig.system.tick;
            var resTop = ig.game.collisionMap.trace( 
                top.pos.x, top.pos.y, nudgeX, -nudge/2, top.size.x, top.size.y
            );
            top.pos.y = resTop.pos.y;

            var resBottom = ig.game.collisionMap.trace( 
                bottom.pos.x, bottom.pos.y, 0, nudge/2, bottom.size.x, bottom.size.y
            );
            bottom.pos.y = resBottom.pos.y;*/
            
            var vel = 0;
            
            if (Math.abs(top.vel.x) > Math.abs(bottom.vel.x)) {
                vel = top.vel.x
            }
            
            if (Math.abs(top.vel.x) < Math.abs(bottom.vel.x)) {
                vel = bottom.vel.x
            }
            
            top.vel.x = vel;
            bottom.vel.x = vel;
        }
    };

I use 0-9 for the entity.collides. (Player is 5, Cattle are 4, Cabin is 9).

As you can see in the following gif, the collision works, but the cattle won't effect each other.

/><br />
<br />
-Andrew Mast			</div>
		</div>
			<div class=

4 years ago by Joncom

You shouldn't need to modify any of those core Impact functions.

Take a look at ig.Entity.collides. By setting your player to ig.Entity.COLLIDES.FIXED and cows to ig.Entity.COLLIDES.ACTIVE, the player should be able to push cows, and the cows should be able to push each other too.

4 years ago by AndrewMast

Quote from Joncom
You shouldn't need to modify any of those core Impact functions.

Take a look at ig.Entity.collides. By setting your player to ig.Entity.COLLIDES.FIXED and cows to ig.Entity.COLLIDES.ACTIVE, the player should be able to push cows, and the cows should be able to push each other too.


Yes, but when you push a cow in to a solid object (cabin) it is pushed to the side, and doesn't stop the player from pushing it.

EDIT:
/><br />
Plus I can now move the cabin, because both the player and cabin are <code>FIXED</code>.<br />
<br />
-Andrew			</div>
		</div>
			<div class=

4 years ago by AndrewMast

Would it be best if I use Box2D?

-Andrew

4 years ago by AndrewMast

Is there a plugin that makes it so the player can't move if another entity is in the way? (Not push it to one side?)

-Andrew

4 years ago by Joncom

Quote from AndrewMast
Would it be best if I use Box2D?
Probably not necessary.

Quote from AndrewMast
Is there a plugin that makes it so the player can't move if another entity is in the way? (Not push it to one side?)
I think I'm not not clear on what you're trying to accomplish...

1) Is the player supposed to be able to move cows?
2) Are cows supposed to be able to move the player?
3) Are cows supposed to be able to move cows?

How come your building is an entity instead of using the collision map?

4 years ago by AndrewMast

Quote from Joncom
Probably not necessary.I think I'm not not clear on what you're trying to accomplish...

1) Is the player supposed to be able to move cows?
2) Are cows supposed to be able to move the player?
3) Are cows supposed to be able to move cows?

How come your building is an entity instead of using the collision map?


1). Yes
2). No
3). Yes

In the generation it would be easier to have the cabin as an entity.

Right now, this is my ig.Entity.solveCollision function: (It's the best I've got so far)
ig.Entity.solveCollision = function( a, b ) {
    var velA = {x: a.pos.x - a.last.x, y: a.pos.y - a.last.y};
    var velB = {x: b.pos.x - b.last.x, y: b.pos.y - b.last.y};

    var max = function (a, b) {
        return Math.max(Math.abs(a), Math.abs(b)) == Math.abs(a) ? a : b;
    };

    var getSign = function (a) {
        return a / Math.abs(a);
    };

    var velX = max(velA.x, velB.x);
    var velY = max(velA.y, velB.y);

    var strongX = velX == velA.x ? a : b;
    var strongY = velY == velA.y ? a : b;

    var weakX = velX == velA.x ? b : a;
    var weakY = velY == velA.y ? b : a;

    if (weakX.collides == 9) {
        var v = strongX;
        strongX = weakX;
        weakX = v;
        velX *= -1;
    }

    if (weakY.collides == 9) {
        var n = strongY;
        strongY = weakY;
        weakY = n;
        velY *= -1;
    }

    if (getSign(velX) === -1) {//LEFT
        weakX.pos.x = strongX.pos.x - weakX.size.x;
    } else if (getSign(velX) === 1) {//RIGHT
        weakX.pos.x = strongX.pos.x + strongX.size.x;
    }

    if (getSign(velY) === -1) {//UP
        weakY.pos.y = strongY.pos.y - weakY.size.y;
    } else if (getSign(velY) === 1) {//DOWN
        weakY.pos.y = strongY.pos.y + strongY.size.y;
    }
}

I think I know why this is not 100% working. It's because of the order of the "solveCollision"s.

4 years ago by Joncom

I can now move the cabin, because both the player and cabin are FIXED
First things first. Why is your cabin an entity? Perhaps try using the collision map for that instead. In other words, create a collision map in Weltmeister, and define what areas of the cabin are not walkable.

http://impactjs.com/documentation/video-tutorial-weltmeister

4 years ago by Krisjet

AndrewMast: Basically, the collision system in Impact is not very advanced. As you've noticed, many entities colliding with each other won't "line up" and push each other, they will stack, which is seldom what you want. Using Box2D would fix this particular problem, but I imagine it would introduce a host of others which you don't want to deal with. I realize that I never really found a great way to solve this problem, I used Box2D for one of my projects and it worked out rather well, but I wouldn't recommend it in your case.

I think you're probably on the right track with doing some modifications to the way Impact handles collisions, hope you figure it out!
Page 1 of 1
« first « previous next › last »