AxeGame expanded with texture, collision issues

I tried to expand AxeGame, the first project of the course. Except now I have a problem with collisions. Seriously, I’ve tried them all, but I just can’t get them to work properly. Another test I had done was to create a rectangle, but even if it worked, it worked poorly. Anyone have any suggestions?

#include "raylib.h"
#include "raymath.h"

int main()
{
	// -- WINDOW -- Screen's Size & Window Initialization
	const int ScreenWidth{ 1920 };
	const int ScreenHeight{ 1080 };

	InitWindow(ScreenWidth, ScreenHeight, "AXE GAME");

	Image Background = LoadImage("Assets/Background.png");
	Texture2D BackgroundTexture = LoadTextureFromImage(Background);
	UnloadImage(Background);

	// -- PLAYER -- We are loading textures for Player
	Texture2D PlayerIdle = LoadTexture("Assets/PlayerIdle.png");
	Texture2D PlayerRun = LoadTexture("Assets/PlayerRun.png");
	Texture2D Player = LoadTexture("Assets/PlayerIdle.png");
	Vector2 PlayerPosition{ 50, 515 };

	double PlayerFace{ 1.0 };	// Player's View: 1 = Right; -1 = Left

	const double UpdateTime{ 1.0 / 12.0 };
	double RunningTime{};

	const int MaxFrame{ 8 };
	int Frame{};

	const int PlayerSpeed{ 3 };

	Rectangle PlayerCollisionBox{ PlayerPosition.x, PlayerPosition.y, Player.width, Player.height };
		
	// -- AXE -- We are loading textures for the three Axes
	Texture2D Axe = LoadTexture("Assets/Axe.png");
	Texture2D Axe1 = LoadTexture("Assets/Axe.png");
	Texture2D Axe2 = LoadTexture("Assets/Axe.png");	

	Vector2 Axe_Pos{ 358, 32 };
	Vector2 Axe1_Pos{ 966, 32 };
	Vector2 Axe2_Pos{ 1542, 32 };

	Rectangle Axe_Rec{ 0, 0, Axe.width, Axe.height };
	Rectangle Axe1_Rec{ 0, 0, Axe1.width, Axe1.height };
	Rectangle Axe2_Rec{ 0, 0, Axe2.width, Axe2.height };

	Rectangle AxeCollisionBox{ Axe_Pos.x, Axe_Pos.y, Axe.width, Axe.height };

	int Axe_Dir{ 9 };
	int Axe1_Dir{ 12 };
	int Axe2_Dir{ 15 };

	Rectangle CollisionBox{ 0 };
	bool Pause = false;
	bool Collision = false;

	SetTargetFPS(60);
	
	// Main Game Loop
	while (!WindowShouldClose())
	{
		BeginDrawing();

		ClearBackground(BLACK);

		DrawTexture(BackgroundTexture, 0, 0, WHITE);

		const double DeltaTime{ GetFrameTime() };		

		/********************************************
		*
		* START GAME LOGIC
		*
		********************************************/

		if (PlayerPosition.x < -40 || PlayerPosition.x > ScreenWidth - 100)
		{
			DrawText("YOU LOOSE", 910, 440, 50, RED);
		}
		else
		{		
			Vector2 Direction{};
			if (IsKeyDown(KEY_A))
			{
				Direction.x -= 1;
				PlayerPosition.x -= PlayerSpeed;
			}
			if (IsKeyDown(KEY_D))
			{
				Direction.x += 1;
				PlayerPosition.x += PlayerSpeed;
			}

			if (Vector2Length(Direction) != 0)
			{
				Direction.x < 0.0 ? PlayerFace = -1.0 : PlayerFace = 1.0;
				Player = PlayerRun;
			}
			else
			{
				Player = PlayerIdle;
			}
			
			// AXE0's Movement
			Axe_Pos.y += Axe_Dir;
			if (Axe_Pos.y > 640 - Axe.height || Axe_Pos.y < 32)
			{
				Axe_Dir = -Axe_Dir;
			}

			Axe1_Pos.y += Axe1_Dir;
			if (Axe1_Pos.y > 640 - Axe1.height || Axe1_Pos.y < 32)
			{
				Axe1_Dir = -Axe1_Dir;
			}

			Axe2_Pos.y += Axe2_Dir;
			if (Axe2_Pos.y > 640 - Axe2.height || Axe2_Pos.y < 32)
			{
				Axe2_Dir = -Axe2_Dir;
			}

			// PLAYER Update Animation Frame
			RunningTime += DeltaTime;
			if (RunningTime >= UpdateTime)
			{
				Frame++;
				RunningTime = 0.0;
				if (Frame > MaxFrame) Frame = 0;
			}

			Collision = false;
			if (PlayerPosition.x >= (Axe_Pos.y >= 608))
			{
				DrawText("COLLISION", 200, 500, 50, GREEN);
			}
									
			// AXE0
			DrawTextureRec(Axe, Axe_Rec, Axe_Pos, WHITE);

			// AXE1
			DrawTextureRec(Axe1, Axe1_Rec, Axe1_Pos, WHITE);

			// AXE2
			DrawTextureRec(Axe2, Axe2_Rec, Axe2_Pos, WHITE);

			// PLAYER
			Rectangle Source{
				Frame * Player.width / 8,
				0,
				PlayerFace * (float)Player.width / 8,
				Player.height
			};

			Rectangle Destination{
				PlayerPosition.x,
				PlayerPosition.y,
				2.0 * (float)Player.width / 8,
				2.0 * (float)Player.height
			};

			DrawTexturePro(Player, Source, Destination, Vector2{}, 0.f, WHITE);
		}

		/********************************************
		*
		* END GAME LOGIC
		*
		********************************************/

		EndDrawing();
	}

	UnloadTexture(BackgroundTexture);
	UnloadTexture(PlayerIdle);
	UnloadTexture(PlayerRun);
	UnloadTexture(Player);
	UnloadTexture(Axe);
	UnloadTexture(Axe1);
	UnloadTexture(Axe2);
	CloseWindow();

	return 0;
}

I would suggest going back to the lecture (“Collision Detection” 15_AG_CPP) on collision for the axe_game section of the course as there seems to be multiple issues here. Both in regards to setup and updating the collision box with each iteration of the game loop. That should be a good place to start.

Overall, though. It’s good to see you trying to improve on previous projects based on what you’ve learned in the course!

Already tried. The collisions weren’t happening in the right places. I had created additional Rectangles:
I had created the bool variable as in the section you indicated. I updated all the variables, but when I inserted the condition the collisions occurred when Player and Axe were not touching. I also tried with the CheckCollisionRecs function as shown in a Raylib example, but nothing.

Great ambition, keep it up!

I can’t try the stuff out right now, but from looking at your code, here are my notes:

I’d say that in particular this line doesn’t do anything meaningful:

It compares the player’s x with a bool that results from comparing the axe’s y.

I don’t see any actual collision checking happening in your code.

You have a collision box for the player, but it’s position does not get updated in the loop.

You did declare one axe collision box where you would instead need one for each axe. Within the loop, you would then need to do the following for each axe, after updating its position:

  • update the position of the corresponding axe collision box position to the axe’s position and
  • use CheckCollisionRecs with the axe’s collision box and the player’s collision box. If the result is true, set Collision to true. (You could skip checking the remaining axes in this case, but it doesn’t hurt to do it redundantly.)

Insert these checks below setting the Collision bool to false. Each check must set Collision to true if it received a true. After the checks, you probably want to do output depending on the overall Collision result:

			if (Collision)
			{
				DrawText("COLLISION", 200, 500, 50, GREEN);
			}

I know you said you tried CheckCollisionRecs, but from the code you showed you didn’t have a collision box for each axe, and the one you had did not get updated, neither did the player’s box.

Yes, that line of code is one of the many tests I have done.
I know that I should create rectangles for each Axe, but I was trying to make the collisions work first with the first, then once the code will work I will create the same code lines for Axe1 and Axe2.
I tried to follow your indications and added these lines of code under the block
// Player Update Animation Frame

// PLAYER COLLISION REC update position
PlayerCollisionBox.x = PlayerPosition.x;
PlayerCollisionBox.y = PlayerPosition.y;
PlayerCollisionBox.width = Player.width;
PlayerCollisionBox.height = Player.height;

// AXE COLLISION REC update position
AxeCollisionBox.x = Axe_Pos.x;
AxeCollisionBox.y = Axe_Pos.y;
AxeCollisionBox.width = Axe.width;
AxeCollisionBox.height = Axe.height;

Collision = false;

// Check Collisions between AXE and PLAYER
CheckCollisionRecs(AxeCollisionBox, PlayerCollisionBox);

if (!Collision)
{
	DrawText("COLLISION", 200, 500, 50, GREEN);
}

II had already done this test and in fact it doesn’t work. As soon as I start the game, even if the player and Axe does not touch the inscription “Collision”. And it remains printed. Something is still missing, but I can’t understand what

CheckCollisionRecs returns a value of type bool, so calling CheckCollisionRecs on its own without storing the return value does is like not calling the function at all.

In your case, you’d want Collision = CheckCollisionRecs(AxeCollisionBox, PlayerCollisioinBox);

Now collisions work but…
they work badly…
I’ll put the updated code here and below a screen of what happens

Collision = CheckCollisionRecs(AxeCollisionBox, PlayerCollisionBox);			

if (Collision)
{
	DrawText("COLLISION", 200, 500, 50, GREEN);
}

The first thing we should confirm is if the rectangles are where you expect them to be. To do that, you can use DrawRectangle with your collision rectangles to see where they actually are.

I just tried it and the rectangle is in the right position. I added this line immediately below where I used DrawTexture for the first Axe:

DrawRectangle(AxeCollisionBox.x, AxeCollisionBox.y, AxeCollisionBox.width, AxeCollisionBox.height, PINK);

The rectangle appears and moves correctly with Axe…
The whole code looks like this now:

#include "raylib.h"
#include "raymath.h"

int main()
{
	// -- WINDOW -- Screen's Size & Window Initialization
	const int ScreenWidth{ 1920 };
	const int ScreenHeight{ 1080 };

	InitWindow(ScreenWidth, ScreenHeight, "AXE GAME");

	Image Background = LoadImage("Assets/Background.png");
	Texture2D BackgroundTexture = LoadTextureFromImage(Background);
	UnloadImage(Background);

	// -- PLAYER -- We are loading textures for Player
	Texture2D PlayerIdle = LoadTexture("Assets/PlayerIdle.png");
	Texture2D PlayerRun = LoadTexture("Assets/PlayerRun.png");
	Texture2D Player = LoadTexture("Assets/PlayerIdle.png");
	Vector2 PlayerPosition{ 50, 515 };

	double PlayerFace{ 1.0 };	// Player's View: 1 = Right; -1 = Left

	const double UpdateTime{ 1.0 / 12.0 };
	double RunningTime{};

	const int MaxFrame{ 8 };
	int Frame{};

	const int PlayerSpeed{ 3 };

	Rectangle PlayerCollisionBox{ PlayerPosition.x, PlayerPosition.y, Player.width, Player.height };
		
	// -- AXE -- We are loading textures for the three Axes
	Texture2D Axe = LoadTexture("Assets/Axe.png");
	Texture2D Axe1 = LoadTexture("Assets/Axe.png");
	Texture2D Axe2 = LoadTexture("Assets/Axe.png");	

	Vector2 Axe_Pos{ 358, 32 };
	Vector2 Axe1_Pos{ 966, 32 };
	Vector2 Axe2_Pos{ 1542, 32 };

	Rectangle Axe_Rec{ 0, 0, Axe.width, Axe.height };
	Rectangle Axe1_Rec{ 0, 0, Axe1.width, Axe1.height };
	Rectangle Axe2_Rec{ 0, 0, Axe2.width, Axe2.height };

	Rectangle AxeCollisionBox{ Axe_Pos.x, Axe_Pos.y, Axe.width, Axe.height };
	Rectangle Axe1CollisionBox{ Axe1_Pos.x, Axe1_Pos.y, Axe1.width, Axe1.height };
	Rectangle Axe2CollisionBox{ Axe2_Pos.x, Axe2_Pos.y, Axe2.width, Axe2.height };

	int Axe_Dir{ 9 };
	int Axe1_Dir{ 12 };
	int Axe2_Dir{ 15 };

	bool Collision = false;
	bool Collision1 = false;
	bool Collision2 = false;

	SetTargetFPS(60);
	
	// Main Game Loop
	while (!WindowShouldClose())
	{
		BeginDrawing();

		ClearBackground(BLACK);

		DrawTexture(BackgroundTexture, 0, 0, WHITE);

		const double DeltaTime{ GetFrameTime() };		

		/********************************************
		*
		* START GAME LOGIC
		*
		********************************************/

		if (PlayerPosition.x < -40 || PlayerPosition.x > ScreenWidth - 100)
		{
			DrawText("YOU LOOSE", 910, 440, 50, RED);
		}
		else
		{		
			Vector2 Direction{};
			if (IsKeyDown(KEY_A))
			{
				Direction.x -= 1;
				PlayerPosition.x -= PlayerSpeed;
			}
			if (IsKeyDown(KEY_D))
			{
				Direction.x += 1;
				PlayerPosition.x += PlayerSpeed;
			}

			if (Vector2Length(Direction) != 0)
			{
				Direction.x < 0.0 ? PlayerFace = -1.0 : PlayerFace = 1.0;
				Player = PlayerRun;
			}
			else
			{
				Player = PlayerIdle;
			}
			
			// AXE0's Movement
			Axe_Pos.y += Axe_Dir;
			if (Axe_Pos.y > 640 - Axe.height || Axe_Pos.y < 32)
			{
				Axe_Dir = -Axe_Dir;
			}

			Axe1_Pos.y += Axe1_Dir;
			if (Axe1_Pos.y > 640 - Axe1.height || Axe1_Pos.y < 32)
			{
				Axe1_Dir = -Axe1_Dir;
			}

			Axe2_Pos.y += Axe2_Dir;
			if (Axe2_Pos.y > 640 - Axe2.height || Axe2_Pos.y < 32)
			{
				Axe2_Dir = -Axe2_Dir;
			}

			// PLAYER Update Animation Frame
			RunningTime += DeltaTime;
			if (RunningTime >= UpdateTime)
			{
				Frame++;
				RunningTime = 0.0;
				if (Frame > MaxFrame) Frame = 0;
			}
			
			// PLAYER COLLISION REC update position
			PlayerCollisionBox.x = PlayerPosition.x;
			PlayerCollisionBox.y = PlayerPosition.y;
			PlayerCollisionBox.width = Player.width;
			PlayerCollisionBox.height = Player.height;

			// AXE COLLISION REC update position
			AxeCollisionBox.x = Axe_Pos.x;
			AxeCollisionBox.y = Axe_Pos.y;
			AxeCollisionBox.width = Axe.width;
			AxeCollisionBox.height = Axe.height;

			// AXE1 COLLISION REC update position
			Axe1CollisionBox.x = Axe1_Pos.x;
			Axe1CollisionBox.y = Axe1_Pos.y;
			Axe1CollisionBox.width = Axe1.width;
			Axe1CollisionBox.height = Axe1.height;

			// AXE COLLISION REC update position
			Axe2CollisionBox.x = Axe2_Pos.x;
			Axe2CollisionBox.y = Axe2_Pos.y;
			Axe2CollisionBox.width = Axe2.width;
			Axe2CollisionBox.height = Axe2.height;

			Collision = CheckCollisionRecs(AxeCollisionBox, PlayerCollisionBox);	
			Collision1 = CheckCollisionRecs(Axe1CollisionBox, PlayerCollisionBox);
			Collision2 = CheckCollisionRecs(Axe2CollisionBox, PlayerCollisionBox);

			if (Collision)
			{
				DrawText("COLLISION", 200, 500, 50, GREEN);
			}
			if (Collision1)
			{
				DrawText("COLLISION1", 600, 500, 50, BLUE);
			}
			if (Collision2)
			{
				DrawText("COLLISION2", 1200, 500, 50, ORANGE);
			}				

			// AXE0
			DrawTextureRec(Axe, Axe_Rec, Axe_Pos, WHITE);

			// AXE1
			DrawTextureRec(Axe1, Axe1_Rec, Axe1_Pos, WHITE);

			// AXE2
			DrawTextureRec(Axe2, Axe2_Rec, Axe2_Pos, WHITE);

			DrawRectangle(AxeCollisionBox.x, AxeCollisionBox.y, AxeCollisionBox.width, AxeCollisionBox.height, GREEN);
			DrawRectangle(Axe1CollisionBox.x, Axe1CollisionBox.y, Axe1CollisionBox.width, Axe1CollisionBox.height, BLUE);
			DrawRectangle(Axe2CollisionBox.x, Axe2CollisionBox.y, Axe2CollisionBox.width, Axe2CollisionBox.height, ORANGE);

			// PLAYER
			Rectangle Source{
				Frame * Player.width / 8,
				0,
				PlayerFace * (float)Player.width / 8,
				Player.height
			};

			Rectangle Destination{
				PlayerPosition.x,
				PlayerPosition.y,
				2.0 * (float)Player.width / 8,
				2.0 * (float)Player.height
			};

			DrawTexturePro(Player, Source, Destination, Vector2{}, 0.f, WHITE);
		}

		/********************************************
		*
		* END GAME LOGIC
		*
		********************************************/

		EndDrawing();
	}

	UnloadTexture(BackgroundTexture);
	UnloadTexture(PlayerIdle);
	UnloadTexture(PlayerRun);
	UnloadTexture(Player);
	UnloadTexture(Axe);
	UnloadTexture(Axe1);
	UnloadTexture(Axe2);
	CloseWindow();

	return 0;
}

I found the problem


It’s not the 3 Axes that are the problem, but the Player…
I had doubts, so I tried adding this line of code

DrawRectangle(PlayerCollisionBox.x, PlayerCollisionBox.y, PlayerCollisionBox.width, PlayerCollisionBox.height, PINK);

The pink rectangle would represent the PlayerCollisionBox… but why?

Thanks to your suggestion I managed to fix the collisions and now the game works perfectly!! ^^ It took a lot of logic but I did it!
A thousand thanks!!!

You’re welcome!

In case others come across this and are curious as to why, if you’re basing the width or height of a rectangle on the Texture2D you can run into a problem where either the width or the height become too large compared to the actual sprite you’re working with. As the Texture2D will have its dimensions be the entire spritesheet.

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.

Privacy & Terms