Blocking Movement On Collision

2019-04-01 20:18发布

问题:

i'm developing a 2d game in XNA and i'm currently working on my physics class. and my current task is to stop an object when it's colliding with another. i have made my game call this function when ever 2 objects collide:

public void BlockMovement(gameObject target) {
    //you can call width by just typing width. same for height
    owner.position.X += (owner.position.X - target.position.X);
    owner.position.Y += (owner.position.Y - target.position.Y);
} 

the problem is that instead of stopping. the object that was moving is pushed back by the amount of it's width. can someone please show/tell me how to do this i have been stuck on this for sooo long in many projects.

thanks

回答1:

You are not putting target's and owner's width and height into calculation. Where is the X,Y of a target/owner? Middle? Left-Top?

If collision is head-to-head then

velocity=sqrt(x_velocity*x_velocity+y_velocity*y_velocity); //some pseudo   

public void BlockMovement(gameObject target) {
    //you can call width by just typing width. same for height
    owner.position.X -=owner.x_velocity*penetration_length/(owner.velocity);
    owner.position.Y -=owner.y_velocity*penetration_length/(owner.velocity);
} 

//so, if big part of speed is in x-direction then the position will
//change mostly on x-direction and opposite to velocity

If you dont have a velocity variable, you can introduce a position history of 2 iterations back to compute actual velocity direction.



回答2:

You have two choices:

1) Predict collision before moving and prevent the collision from ever happening or 2) Move, detect collision, and then resolve the collision accordingly

My game uses method 2 to stop objects when they collide with an impassable tile. Such a procedure is described below.

objectPreviousPosition = object.position
object.move()
if(object.isCollidingWith(wall))
    object.position = objectPreviousPosition

This is extremely basic and doesn't describe how the collision is detected, only what to do if your collision logic returns true. Also, this method will prevent any and all movement if the player's update causes collision. Therefore, you will not be able to achieve a "sliding" affect along walls using this method.

In order to achieve a sliding affect if you desire it, you will need to determine the direction of the player's movement and resolve the collision by adjusting the player's position based on that direction.

For example:

if(object.movementDirection == movementDirection.UpRight)
    if(player colliding with wall to right)
        keep Y coordinate and set X coordinate to put player on left side of wall

This is all pseudocode so don't take the code as literal.