About Collision: Moving player collided the wall and then the direction

Please see diagram first:







I’ve viewed some corresponding code in Flagrushtut Lession10, and I didn’t found the resolution there :frowning:

The vehicle just stop or bouncing off when it catch the wall, what I want it to do is keep moving along with the wall.

Thank you for whatever help :slight_smile:

What you want is referred to as "wall sliding". In order to do that, you will need to know the point of collision and the normal of collision (which can be determined easily from the point of collision if the player is a sphere). Then you can compute the new direction toward which the player should be moving.

I think I've found where the answer is :slight_smile:



Thank you very much.



http://wiki.jmephysics.irrisor.net/tiki-index.php?page=Lesson+3


gzbadboy said:

I think I've found where the answer is :)

That only works if you are using jmephysics2, momokos hint also works without physics.

I will try both way to do that , thank you :slight_smile:

Hi



I have alredy implemented wall sliding in jme2 using the normals of the collided triangles of the wall (or walls) to change the position and orientation of the player. As the code is a little messy, I'll try to clean it up and post this evening or tomorrow just in case you still need it.

joliver82 said:

Hi

I have alredy implemented wall sliding in jme2 using the normals of the collided triangles of the wall (or walls) to change the position and orientation of the player. As the code is a little messy, I'll try to clean it up and post this evening or tomorrow just in case you still need it.


Yes I still would like to konw how to implement that  , thank you very much :)

HI!



I think I'm toooooooo late… Anyway, I attach the code I used. It's a little messy still but I think it's readable. Just to give you a little background, this code snippet is from my first attempt using jme2, a simple 3D pacman.



I extended Node to make my pacman class in order to have the code clearer. In this class I wanted to have information about current position and previous frame position among other this… I implemented it this way:



public class PacMan extends Node
{
    private static final long serialVersionUID = 1L;
    private Vector3f previousTranslation=new Vector3f();
..................
    public void update()
    {
        previousTranslation.set(this.getLocalTranslation());
        ..................
    }
..................
    public Vector3f getPreviousTranslation()
    {
        return previousTranslation;
    }
}



Dotted lines is code not needed to get wall sliding working.

Also I created a "collision manager" class to be able to handle player-walls collisions easily. This class has a method call "processCollisions" in which all/most of the work is done and knows about rootNode, pacman and walls. I used simple boxes as walls in the game, but I think this algorithm should work for almost any scene.

This algorithm checks collisions with all walls using bounding boxes. After a collision is found, it searches for the triangle/s and gets their normals. Later it calculates the direction to go backwards using each normal and later on it sums up all the backwards directions. Finally it adds that backwards movement to the current position avoiding going through the walls.


public class CollisionProcessor
{
    private Node rootNode;
    private PacMan pacman;
    private Vector<Node> walls;
   
    public void processCollisions()
    {
        int numWalls=walls.size();
        int i,j,k;
        boolean wallCollision=false;
        Vector<Vector3f> backwardMovements=new Vector<Vector3f>();

        if(!pacman.getLocalTranslation().equals(pacman.getPreviousTranslation()))
       
            for(i=-1;++i<numWalls; )
            {
                //Check for PacMan-Wall collision
                Node wall=walls.get(i);
                if(pacman.hasCollision(wall, false))
                {
                    wallCollision=true;
                    CollisionResults results = new TriangleCollisionResults() {
                        @Override
                        public void processCollisions() {;}
                    };

                    FloatBuffer normalBuffer;
                    float[]triangleNormal=new float[3];
                    Vector3f triNormal=new Vector3f();

                    pacman.findCollisions(wall, results);
                    for (j=-1;++j<results.getNumber(); )
                    { //If we have a collision between bounding boxes
                        CollisionData collisionData = results.getCollisionData(j); //get the collision data
                        int numTris=collisionData.getTargetTris().size();
                       
                        for(k=-1;++k<numTris; ) //If an actual triangle has collided (rather than just the bounding box)
                        {
                            TriMesh geom=(TriMesh)collisionData.getTargetMesh();
                            int triIndex=collisionData.getTargetTris().get(k);
                       
                            int[]vertices=new int[3];
                            geom.getTriangle(triIndex, vertices);

                            normalBuffer=geom.getWorldNormals(null);
                       
                            normalBuffer.position(vertices[0]*3);
                            normalBuffer.get(triangleNormal);
                            triNormal.addLocal(triangleNormal[0],triangleNormal[1],triangleNormal[2]);
                            normalBuffer.position(vertices[1]*3);
                            normalBuffer.get(triangleNormal);
                            triNormal.addLocal(triangleNormal[0],triangleNormal[1],triangleNormal[2]);
                            normalBuffer.position(vertices[2]*3);
                            normalBuffer.get(triangleNormal);
                            triNormal.addLocal(triangleNormal[0],triangleNormal[1],triangleNormal[2]);
                        }
                    }
               
                    //We only want to collide horizontally. so Y dir is not needed
                    triNormal.y=0;
               
                    //If normal is not Zero, we can calculate the direction in which
                    //the player "should" have go ;)
                    if(!triNormal.equals(Vector3f.ZERO))
                    {
                        Vector3f movement=pacman.getLocalTranslation().subtract(pacman.getPreviousTranslation());
                        triNormal.normalizeLocal();
                       
                        Vector3f newMovement=triNormal.mult(FastMath.abs(triNormal.dot(movement)/triNormal.lengthSquared()));

                        backwardMovements.add(newMovement);
                    }
                }
            }
       
        if(wallCollision)
        {
            int numMovements=backwardMovements.size();
                for(i=-1;++i<numMovements; )
                {
                    pacman.setLocalTranslation(pacman.getLocalTranslation().add(backwardMovements.get(i)));
                }
        }
    }
}



An to finish, I called pacman.update() and collisionProcessor.processCollisions() in my main stateUpdate() method.

I think this can be optimized, rewritten for readability and many things, but it worked for me....

Hope this help you and others going through the forums  :mrgreen:

Nice code, and nice hair :slight_smile: thank you

Finally, did you used this code and did it work for you?


joliver82 said:

Finally, did you used this code and did it work for you?




Yes I did , but the character may go through the walls , I dont know why but I am trying to figure out that .
You gave me a good recipe of implementing wall sliding , thank you very much and happy new year (I am in Chinese new year vacation :) )