Search code examples
javaopengl3dlwjgl

LWJGL Java collision


I am trying to make a 3D game, but I am having a hard time with the collision. I have worked on a system, but it is not really good. I already have a system for collision with the terrain, but it cannot be used to collide with entities(since the terrain only has height to collide with). I am using blender-models and they consist of triangles. 100% accurate collision would be to use some form of collision detection for each triangle, but there are so many and therefore, the game will lose it's performance. Most of the code is based on ThinMatrix tutorial on YouTube, except some of it which I have created myself. Here is some of the code I use for the current collision:

public boolean collision(Entity e1, Entity e2){


    if(e1.getPosition().x >= e2.getPosition().x && e1.getPosition().x < e2.getPosition().x + e2.getWidth()){
        if(e1.getPosition().z >= e2.getPosition().z && e1.getPosition().z < e2.getPosition().z + e2.getWidth()){
            System.out.println("XXX||&&&||ZZZ");
            return true;
        }
    }

    return false;


}

This method is the collision method. It is based on the X and Z position, and is therefore very inaccurate. In the player-class, I call it:

    public void tick(){
        for(Entity e : entities){
            if(super.collsion(this, e)){
                I haven't gotten to this
            }

        }
    }

This system works, but it has very many problems, one of them being that it is to inaccurate.

EDIT: I have been working on using a new vector(that I made) which I called Vector6f. Using multiple values, it should be easier to store and get the values. It takes the parameters x, y, z, xwidth, zwidth, height. With these, I made a new method I called getBounds, which returns the entities bounds. if the entity does not have bounds, it will not do collision


Solution

  • You could easily bring the Y value into the check you have to make it a bit more precise. Although, this just creates a 3d bounding box around the object, rather than 3d convex hull, which probably should be used. Here's some pseudocode close to java, where lX - length in X axis, hlX - half length in X axis, considering we use the center point of entities to define their position.

    boolean isColliding(Entity other) {
    if (center.y + hlY < other.center.y - other.hlY ||
        center.y - hlY > other.center.y + other.hlY)
        return false;
    
    Rectangle r1 = { center.x - hlX, center.z - hlZ, lX, lZ };
    Rectangle r2 = { other.center.x - other.hlX, other.center.z - other.hlZ, other.lX, other.lZ };
    
    return r1.intersects(r2);
    }
    

    As for the update tick regarding collisions:

        for (int i = 0; i < collidables.size(); i++) {
            Entity e1 = collidables.get(i);
    
            for (int j = i + 1; j < collidables.size(); j++) {
                Entity e2 = collidables.get(j);
    
                if (e1.isColliding(e2)) {
                    CollisionHandler handler = ... // get handler if registered for type of e1 vs type of e2
                    if (handler != null)
                        handler.onCollision(e1, e2);
                }
            }
        }
    

    which gives you n * (n - 1) / 2 loop cycles, where n - number of collidable entities