Home Game Development tilemap – Voxel terrain vs AABB collision detection

tilemap – Voxel terrain vs AABB collision detection

0
tilemap – Voxel terrain vs AABB collision detection

[ad_1]

collision on voxel world is very simple.
First you have to calculate the player position and size divide by the block size
Example: player.position.x + player.size / block.size
Then if you’re using any sort of grid then check that position/grid if it has a solid block type in it.

Here is the sample code from my voxel game:

void Camera::collision(float dx, float dy, float dz)
{
    /* AABB collision checker */
    
    float x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, y5;
    x1 = floor((m_position.x - m_width) / m_block.getBlockSize());
    y1 = floor((m_position.y - m_bottom) / m_block.getBlockSize());
    z1 = floor((m_position.z - m_width) / m_block.getBlockSize());
    x2 = floor((m_position.x + m_width) / m_block.getBlockSize());
    y2 = floor((m_position.y + (m_top+2)) / m_block.getBlockSize());
    z2 = floor((m_position.z + m_depth) / m_block.getBlockSize());
    
    // stuck? go up
    if(floor(m_position.y / m_block.getBlockSize()) < m_worldSize.y) {
        while(Types::getSolidBlocks( m_map.getInPosition(floor(m_position.x / m_block.getBlockSize()), floor(m_position.y / m_block.getBlockSize()), floor(m_position.z / m_block.getBlockSize())) )) {
            m_position.y += m_block.getBlockSize();
            y1 = floor((m_position.y - m_bottom) / m_block.getBlockSize());
            y2 = floor((m_position.y + (m_top+2)) / m_block.getBlockSize());
            if(floor(m_position.y / m_block.getBlockSize()) > m_worldSize.y) break;
        }
    }
    
    // vertical collision
    
    if(Types::getSolidBlocks(m_map.getInPosition(x1, y1, z1)) || Types::getSolidBlocks(m_map.getInPosition(x2, y1, z1)) ||
        Types::getSolidBlocks(m_map.getInPosition(x2, y1, z2)) || Types::getSolidBlocks(m_map.getInPosition(x1, y1, z2))) {
        
        if(dy < 0) {
            m_position.y = y1 * m_block.getBlockSize() + m_block.getBlockSize() + m_bottom;
            m_direction.y = 0;
            m_onGround = true;
        }
        m_collision[1] = true;
    }
    
    if(Types::getSolidBlocks(m_map.getInPosition(x1, y2, z1)) || Types::getSolidBlocks(m_map.getInPosition(x2, y2, z1)) ||
        Types::getSolidBlocks(m_map.getInPosition(x2, y2, z2)) || Types::getSolidBlocks(m_map.getInPosition(x1, y2, z2))) {
        
        if(dy > 0) {
            m_position.y = y2 * m_block.getBlockSize() - (m_top+2) - .01;
            m_direction.y = 0;
        }
        m_collision[1] = true;
    }
    
    // horizontal collision
    
    x3 = floor((m_position.x - dx - m_width) / m_block.getBlockSize());
    y3 = floor((m_position.y - dy - m_bottom) / m_block.getBlockSize());
    z3 = floor((m_position.z - dz - m_width) / m_block.getBlockSize());
    x4 = floor((m_position.x - dx + m_width) / m_block.getBlockSize());
    y4 = floor((m_position.y - dy + (m_top+2)) / m_block.getBlockSize());
    z4 = floor((m_position.z - dz + m_depth) / m_block.getBlockSize());
    y5 = round(y3+(y4-y3)/2); // previous y position
    
    if(Types::getSolidBlocks(m_map.getInPosition(x1, y3, z3)) || Types::getSolidBlocks(m_map.getInPosition(x1, y3, z4)) ||
        Types::getSolidBlocks(m_map.getInPosition(x1, y4, z4)) || Types::getSolidBlocks(m_map.getInPosition(x1, y4, z3)) ||
        Types::getSolidBlocks(m_map.getInPosition(x1, y5, z3)) || Types::getSolidBlocks(m_map.getInPosition(x1, y5, z4))) {
        
        if(dx < 0) {
            m_position.x = (x3-1) * m_block.getBlockSize() + m_block.getBlockSize() + m_width;
            m_direction.x = 0;
        }
        m_collision[0] = true;
    }
    
    if(Types::getSolidBlocks(m_map.getInPosition(x2, y3, z3)) || Types::getSolidBlocks(m_map.getInPosition(x2, y3, z4)) ||
        Types::getSolidBlocks(m_map.getInPosition(x2, y4, z4)) || Types::getSolidBlocks(m_map.getInPosition(x2, y4, z3)) ||
        Types::getSolidBlocks(m_map.getInPosition(x2, y5, z3)) || Types::getSolidBlocks(m_map.getInPosition(x2, y5, z4))) {
        
        if(dx > 0) {
            m_position.x = (x4+1) * m_block.getBlockSize() - m_width - .01;
            m_direction.x = 0;
        }
        m_collision[0] = true;
    }
    
    if(Types::getSolidBlocks(m_map.getInPosition(x3, y3, z1)) || Types::getSolidBlocks(m_map.getInPosition(x4, y3, z1)) ||
        Types::getSolidBlocks(m_map.getInPosition(x4, y4, z1)) || Types::getSolidBlocks(m_map.getInPosition(x3, y4, z1)) ||
        Types::getSolidBlocks(m_map.getInPosition(x3, y5, z1)) || Types::getSolidBlocks(m_map.getInPosition(x4, y5, z1))) {
        
        if(dz < 0) {
            m_position.z = (z3-1) * m_block.getBlockSize() + m_block.getBlockSize() + m_depth;
            m_direction.z = 0;
        }
        m_collision[2] = true;
    }
    
    if(Types::getSolidBlocks(m_map.getInPosition(x3, y3, z2)) || Types::getSolidBlocks(m_map.getInPosition(x4, y3, z2)) ||
        Types::getSolidBlocks(m_map.getInPosition(x4, y4, z2)) || Types::getSolidBlocks(m_map.getInPosition(x3, y4, z2)) ||
        Types::getSolidBlocks(m_map.getInPosition(x3, y5, z2)) || Types::getSolidBlocks(m_map.getInPosition(x4, y5, z2))) {
        
        if(dz > 0) {
            m_position.z = (z4+1) * m_block.getBlockSize() - m_depth - .01;
            m_direction.z = 0;
        }
        m_collision[2] = true;
    }
    
}

Btw. The m_map is a grid that checks the block type in the world
and dx, dy, dz are the direction of the player

and here’s how to use the collider:

// player movement
m_position.x += m_direction.x * dt;
collision(m_direction.x, 0, 0); // collision detector
m_position.y += m_direction.y * dt;
collision(0, m_direction.y, 0); // collision detector
m_position.z += m_direction.z * dt;
collision(0, 0, m_direction.z); // collision detector

[ad_2]

Previous article Avatar: Frontiers of Pandora review: practice what you preach
Next article How to exchange a gift with Mateo in Pokémon Go
Hello there! My name is YoleeTeam, and I am thrilled to welcome you to AmazonianGames.com. As the premier destination for all things related to Amazon Games' universe, we are dedicated to providing you with the most exciting and immersive gaming experiences out there. From captivating visuals to exhilarating gameplay, our website is packed with comprehensive insights, updates, and reviews to keep you ahead of the game. Whether you're a seasoned gamer or new to the scene, I am here to guide you through this virtual frontier. If you have any questions or suggestions, feel free to reach out to me at john@yoleesolutions.com. Embark on your Amazon gaming journey today with AmazonianGames.com and let the adventure begin!