JOSMALO MAMA
JOSMALO MAMA

Reputation: 21

Unexpected Collision & No-Clipping Issue

i been trying to make a collision for the player i did use some ai for it but i came to a problem that idk how to fix at some blocks that face north and east i can noclip in 1 block deep in the wall if there is two block tick wall and sometimes when i fall i noclip 1 block into the ground. i'm using C with a 3D opengl renderer

#include "Player.h"
#include <stdio.h>
#include "Utils.h"
#include "Camera.h"
#include "WorldGenerator.h"

void Player_Init(Player* player, vec3 startPos) {
    glm_vec3_copy(startPos, player->position);
    glm_vec3_zero(player->velocity);
    player->isOnGround = 0;

    while (!CheckAABBCollision(player, (vec3) { player->position[0], player->position[1] - 1.0f, player->position[2] })) {
        player->position[1] -= 1.0f;
        if (player->position[1] <= 0.0f) break;
    }
    if (CheckAABBCollision(player, player->position)) {
        player->position[1] += 0.1f;
    }

    player->isOnGround = 1;
    player->velocity[1] = 0;
}

int CheckCollision(vec3 position) {
    int x = (int)floorf(position[0]);
    int y = (int)floorf(position[1]);
    int z = (int)floorf(position[2]);

    if (x < 0 || x >= CHUNK_SIZE * NUM_CHUNKS ||
        y < 0 || y >= CHUNK_HEIGHT ||
        z < 0 || z >= CHUNK_SIZE * NUM_CHUNKS) {
        return 0;
    }

    int chunkX = x / CHUNK_SIZE;
    int chunkZ = z / CHUNK_SIZE;
    int localX = x % CHUNK_SIZE;
    int localZ = z % CHUNK_SIZE;

    return world[chunkX][chunkZ].blocks[localX][y][localZ] != 0;
}

int CheckAABBCollision(Player* player, vec3 newPos) {
    float halfWidth = PLAYER_WIDTH / 2;
    float expand = 0.05f;

    float minX = newPos[0] - halfWidth - expand;
    float maxX = newPos[0] + halfWidth + expand;
    float minY = newPos[1];
    float maxY = newPos[1] + PLAYER_HEIGHT;
    float minZ = newPos[2] - halfWidth - expand;
    float maxZ = newPos[2] + halfWidth + expand;

    vec3 checkPoints[8] = {
        {minX, minY, minZ}, {maxX, minY, minZ}, {minX, minY, maxZ}, {maxX, minY, maxZ},
        {minX, maxY, minZ}, {maxX, maxY, minZ}, {minX, maxY, maxZ}, {maxX, maxY, maxZ} 
    };

    for (int i = 0; i < 8; i++) {
        if (CheckCollision(checkPoints[i])) {
            return 1; 
        }
    }

    return 0;
}

void ResolveCollision(Player* player, float deltaTime) {
    vec3 newPos;
    glm_vec3_copy(player->position, newPos);

    if (!player->isOnGround) {
        player->velocity[1] += GRAVITY * deltaTime;
    }

    newPos[1] += player->velocity[1] * deltaTime;

    if (CheckAABBCollision(player, newPos)) {
        if (player->velocity[1] < 0) {
            player->isOnGround = 1;
            player->velocity[1] = 0;

            while (CheckAABBCollision(player, (vec3) { newPos[0], newPos[1] - 0.01f, newPos[2] })) {
                newPos[1] += 0.01f;
            }
        }
        else if (player->velocity[1] > 0) {
            player->velocity[1] = 0;
        }
    }
    else {
        player->position[1] = newPos[1];
        player->isOnGround = 0;
    }

    newPos[0] += player->velocity[0] * deltaTime;

    if (CheckAABBCollision(player, (vec3) { newPos[0], player->position[1], player->position[2] })) {
        printf("X Collision at %.2f\n", newPos[0]);

        if (player->velocity[0] > 0) {
            newPos[0] = floor(newPos[0]) - 0.01f;
        }
        else if (player->velocity[0] < 0) {  
            newPos[0] = ceil(newPos[0]) + 0.01f;
        }

        player->velocity[0] = 0;
    }
    else {
        player->position[0] = newPos[0];
    }
    newPos[2] += player->velocity[2] * deltaTime;

    if (CheckAABBCollision(player, (vec3) { player->position[0], player->position[1], newPos[2] })) {
        printf("Z Collision at %.2f\n", newPos[2]);
        if (player->velocity[2] > 0) { 
            newPos[2] = floor(newPos[2]) - 0.01f;
        }
        else if (player->velocity[2] < 0) {
            newPos[2] = ceil(newPos[2]) + 0.01f;
        }

        player->velocity[2] = 0;
    }
    else {
        player->position[2] = newPos[2];
    }
}

void Player_Update(Player* player, float deltaTime) {
    if (!player->isOnGround) {
        player->velocity[1] += GRAVITY * deltaTime;
    }

    if (player->velocity[1] < -MAX_FALL_SPEED) {
        player->velocity[1] = -MAX_FALL_SPEED;
    }

    ResolveCollision(player, deltaTime);
}

i was expecting to player collides with the cubes.

Upvotes: 0

Views: 58

Answers (0)

Related Questions