Skip to content

collision

Lulezer edited this page Apr 3, 2025 · 1 revision

Collisions Tutorial in Echlib In this tutorial, we will learn how to implement basic collision detection using Echlib.

Step 1: Setup We start by setting up a window and defining the player's properties, such as position, speed, and texture size. We will also create a simple static object that the player will collide with.

#include <echlib.h>
#include <cmath>  // For sqrt
#include <iostream>

using namespace ech;

int main()
{
    float PlayerX = 50.0f;
    float PlayerY = 50.0f;

    // Texture Size
    float PlayerTextureWidth = 90.0f;
    float PlayerTextureHeight = 90.0f;

    // Collision Box Size (Can be different from texture size)
    float PlayerCollWidth = 50.0f;  
    float PlayerCollHeight = 80.0f;

    float Speed = 400.0f;
    int WindowWidth = 800;
    int WindowHeight = 800;

    // Create the window
    MakeWindow(WindowWidth, WindowHeight, "Echlib Collision Example");
    SetTargetFps(60);

    // Load textures
    LoadTexture(RESOURCES_PATH "Player/Player_Back.png", "playerback");
    LoadTexture(RESOURCES_PATH "Map/Map.png", "background");

    // Initialize camera centered around player
    camera.x = PlayerX - WindowWidth / 2.0f;
    camera.y = PlayerY - WindowHeight / 2.0f;
    camera.zoom = 5.0f;

Step 2: Movement Input Here, we define movement for the player based on key inputs. The movement is normalized to ensure the player moves at a consistent speed in all directions, including diagonals.

    while (!WindowShouldClose())
    {
        float DeltaTime = GetDeltaTime();
        float moveX = 0.0f, moveY = 0.0f;

        if (IsKeyHeld(KEY_RIGHT)) moveX += 1.0f;
        if (IsKeyHeld(KEY_LEFT)) moveX -= 1.0f;
        if (IsKeyHeld(KEY_UP)) moveY += 1.0f;
        if (IsKeyHeld(KEY_DOWN)) moveY -= 1.0f;

        // Normalize diagonal movement
        float magnitude = sqrt(moveX * moveX + moveY * moveY);
        if (magnitude > 0.0f)
        {
            moveX /= magnitude;
            moveY /= magnitude;
        }

        // Update player position
        PlayerX += moveX * Speed * DeltaTime;
        PlayerY += moveY * Speed * DeltaTime;


Step 3: Collision Detection We create a collision shape for the player and a static obstacle. The player's position is adjusted if no collision occurs when moving in either axis.

        // Collision Box centered under the player
        CollisionShape playerShape{
            PlayerX + (PlayerTextureWidth - PlayerCollWidth) / 2,
            PlayerY + (PlayerTextureHeight - PlayerCollHeight) / 2,
            PlayerCollWidth, PlayerCollHeight
        };

        CollisionShape rectShape{ 100.0f, 370.0f, 20.0f, 20.0f }; // Static obstacle

        // Predict new position
        float nextPlayerX = playerShape.x + moveX * Speed * DeltaTime;
        float nextPlayerY = playerShape.y + moveY * Speed * DeltaTime;

        // Check collisions on X-axis
        CollisionShape nextPlayerShapeX = { nextPlayerX, playerShape.y, PlayerCollWidth, PlayerCollHeight };
        if (!nextPlayerShapeX.CheckCollision(rectShape))
        {
            playerShape.x = nextPlayerX;
        }

        // Check collisions on Y-axis
        CollisionShape nextPlayerShapeY = { playerShape.x, nextPlayerY, PlayerCollWidth, PlayerCollHeight };
        if (!nextPlayerShapeY.CheckCollision(rectShape))
        {
            playerShape.y = nextPlayerY;
        }

Step 4: Camera Update After updating the player's position, we update the camera to follow the player.

        // Update Camera position
        camera.x = playerShape.x - WindowWidth / 2.0f;
        camera.y = playerShape.y - WindowHeight / 2.0f;

Step 5: Drawing Now we draw the player and the static obstacle on the screen. The player's texture is drawn with respect to the camera position, ensuring the movement appears smoothly.

        StartDrawing();
        ClearBackground(GRAY);

        // Draw background and player relative to the camera
        DrawTexturedRectangle(-camera.x, -camera.y, 2000, 2000, "background");
        DrawTexturedRectangle(PlayerX - camera.x, PlayerY - camera.y, PlayerTextureWidth, PlayerTextureHeight, "playerback");

        // Draw obstacle
        DrawRectangle(
            rectShape.x - camera.x,
            rectShape.y - camera.y,
            rectShape.width,
            rectShape.height,
            LIGHT_BLUE
        );

        // Draw player collision box (for debugging)
        DrawRectangle(
            playerShape.x - camera.x,
            playerShape.y - camera.y,
            playerShape.width, playerShape.height,
            TRANSPARENT
        );

        EndDrawing();
    }

    CloseWindow();
    return 0;
}

Full Example Code

#include <echlib.h>
#include <cmath>  // For sqrt
#include <iostream>

using namespace ech;

int main()
{
    float PlayerX = 50.0f;
    float PlayerY = 50.0f;

    // Texture Size
    float PlayerTextureWidth = 90.0f;
    float PlayerTextureHeight = 90.0f;

    // Collision Box Size (Can be different from texture size)
    float PlayerCollWidth = 50.0f;  
    float PlayerCollHeight = 80.0f;

    float Speed = 400.0f;
    int WindowWidth = 800;
    int WindowHeight = 800;

    // Create the window
    MakeWindow(WindowWidth, WindowHeight, "Echlib Collision Example");
    SetTargetFps(60);

    // Load textures
    LoadTexture(RESOURCES_PATH "Player/Player_Back.png", "playerback");
    LoadTexture(RESOURCES_PATH "Map/Map.png", "background");

    // Initialize camera centered around player
    camera.x = PlayerX - WindowWidth / 2.0f;
    camera.y = PlayerY - WindowHeight / 2.0f;
    camera.zoom = 5.0f;

    while (!WindowShouldClose())
    {
        float DeltaTime = GetDeltaTime();
        float moveX = 0.0f, moveY = 0.0f;

        if (IsKeyHeld(KEY_RIGHT)) moveX += 1.0f;
        if (IsKeyHeld(KEY_LEFT)) moveX -= 1.0f;
        if (IsKeyHeld(KEY_UP)) moveY += 1.0f;
        if (IsKeyHeld(KEY_DOWN)) moveY -= 1.0f;

        // Normalize diagonal movement
        float magnitude = sqrt(moveX * moveX + moveY * moveY);
        if (magnitude > 0.0f)
        {
            moveX /= magnitude;
            moveY /= magnitude;
        }

        // Update player position
        PlayerX += moveX * Speed * DeltaTime;
        PlayerY += moveY * Speed * DeltaTime;

        // Collision Box centered under the player
        CollisionShape playerShape{
            PlayerX + (PlayerTextureWidth - PlayerCollWidth) / 2,
            PlayerY + (PlayerTextureHeight - PlayerCollHeight) / 2,
            PlayerCollWidth, PlayerCollHeight
        };

        CollisionShape rectShape{ 100.0f, 370.0f, 20.0f, 20.0f }; // Static obstacle

        // Predict new position
        float nextPlayerX = playerShape.x + moveX * Speed * DeltaTime;
        float nextPlayerY = playerShape.y + moveY * Speed * DeltaTime;

        // Check collisions on X-axis
        CollisionShape nextPlayerShapeX = { nextPlayerX, playerShape.y, PlayerCollWidth, PlayerCollHeight };
        if (!nextPlayerShapeX.CheckCollision(rectShape))
        {
            playerShape.x = nextPlayerX;
        }

        // Check collisions on Y-axis
        CollisionShape nextPlayerShapeY = { playerShape.x, nextPlayerY, PlayerCollWidth, PlayerCollHeight };
        if (!nextPlayerShapeY.CheckCollision(rectShape))
        {
            playerShape.y = nextPlayerY;
        }

        // Update Camera position
        camera.x = playerShape.x - WindowWidth / 2.0f;
        camera.y = playerShape.y - WindowHeight / 2.0f;

        StartDrawing();
        ClearBackground(GRAY);

        // Draw background and player relative to the camera
        DrawTexturedRectangle(-camera.x, -camera.y, 2000, 2000, "background");
        DrawTexturedRectangle(PlayerX - camera.x, PlayerY - camera.y, PlayerTextureWidth, PlayerTextureHeight, "playerback");

        // Draw obstacle
        DrawRectangle(
            rectShape.x - camera.x,
            rectShape.y - camera.y,
            rectShape.width,
            rectShape.height,
            LIGHT_BLUE
        );

        // Draw player collision box (for debugging)
        DrawRectangle(
            playerShape.x - camera.x,
            playerShape.y - camera.y,
            playerShape.width, playerShape.height,
            TRANSPARENT
        );

        EndDrawing();
    }

    CloseWindow();
    return 0;
}

Yo

Clone this wiki locally