-
Notifications
You must be signed in to change notification settings - Fork 1
collision
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