Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Bounding box collision problems.

This thread is locked; no one can reply to it. rss feed Print
Bounding box collision problems.
PamperBoy
Member #15,477
January 2014

Hi there,

Im having some trouble with the bounding box collision using allegro 5. Standing on top of the platform works. But when colide to the left side of the platform i go in the platform (but does stop in centre of it) also when i jump against the platform i either go through completly or stop in the middle of the platform.

I hope i explained it good enough. if yuo have questions or need to see code just ask.

note: hdir 1 right, 2 left, 0 none. vdir 1 up, 2 down 0 none

also the number 1 is the platform.

Here is the collision code i wrote.

#SelectExpand
1#include "Collision.h" 2 3 4Collision::Collision() 5{ 6} 7 8 9Collision::~Collision() 10{ 11} 12 13void Collision::Init() 14{ 15 loadCounterX = loadCounterY = 0; 16 Collision::LoadCollisionMap("ColMap1.txt", 0); 17 Collision::LoadCollisionMap("ColMap2.txt", 1); 18 Collision::LoadCollisionMap("ColMap3.txt", 2); 19} 20 21void Collision::Update(ALLEGRO_DISPLAY *display, Player &player, Map &map) 22{ 23 Collision::PlatformCollision(display, player, map); 24 Collision::LevelReset(player, map); 25 Collision::DirReverse(player, map); 26 Collision::LevelEnd(player, map); 27} 28 29void Collision::Draw(ALLEGRO_DISPLAY *display) 30{ 31 32} 33 34void Collision::LoadCollisionMap(const char *filename, int level) 35{ 36 ifstream openfile(filename); 37 if(openfile.is_open()) 38 { 39 openfile >> mapSizeX >> mapSizeY; 40 while(!openfile.eof()) 41 { 42 openfile >> ColMapFile[level][loadCounterX][loadCounterY]; 43 loadCounterX ++; 44 if (loadCounterX >= mapSizeX) 45 { 46 loadCounterX = 0; 47 loadCounterY ++; 48 } 49 } 50 loadCounterX = loadCounterY = 0; 51 } 52 else 53 { 54 { al_show_native_message_box(NULL, "Error", "Error", 55 "Cannot find collision map file", NULL, NULL); 56 } 57 58 } 59} 60 61void Collision::PlatformCollision(ALLEGRO_DISPLAY *display, Player &player, Map &map) 62{ 63 for (int i = 0; i < mapSizeX; i++) 64 { 65 for(int j = 0; j < mapSizeY; j++) 66 { 67 if(ColMapFile[map.getLevel()][i][j] == 1) 68 { 69 if(player.x > i * blockSize + blockSize || player.y > j*blockSize + blockSize || player.x2 < i*blockSize || player.y2 < j*blockSize) 70 { 71 //no collision 72 player.platform = false; 73 } 74 75 else 76 { 77 if (player.vDir == 1) 78 { 79 player.y += player.speed * 2; 80 player.y2 = player.y + 10; 81 player.vely = 0; 82 player.platform = false; 83 player.jump = false; 84 } 85 86 if(player.vDir == 2 && player.y - player.vely <= j*blockSize) 87 { 88 player.y = j*blockSize - 10; 89 player.y2 = player.y + 10; 90 player.platform = true; 91 player.jump = true; 92 player.vely = 0; 93 94 } 95 96 97 if (player.hDir == 1 && player.platform == false) 98 { 99 player.x -= player.speed; 100 player.x2 = player.x + 10; 101 } 102 103 if (player.hDir == 2 && player.platform == false) 104 { 105 player.x += player.speed; 106 player.x2 = player.x + 10; 107 } 108 } 109 } 110 } 111 } 112 113} 114 115void Collision::LevelReset(Player &player, Map &map) 116{ 117 for (int i = 0; i < mapSizeX; i++) 118 { 119 for(int j = 0; j < mapSizeY; j++) 120 { 121 if(ColMapFile[map.getLevel()][i][j] == 2) 122 { 123 if(player.x > i * blockSize + blockSize || player.y > j*blockSize + blockSize || player.x2 < i*blockSize || player.y2 < j*blockSize) 124 { 125 //no collision 126 } 127 128 else 129 { 130 player.x = player.origX; 131 player.y = player.origY; 132 133 map.setLevel(0); 134 135 player.velx = player.speed; 136 player.hDir = 1; 137 } 138 } 139 } 140 } 141 142} 143 144void Collision::LevelEnd(Player &player, Map &map) 145{ 146 for (int i = 0; i < mapSizeX; i++) 147 { 148 for(int j = 0; j < mapSizeY; j++) 149 { 150 if(ColMapFile[map.getLevel()][i][j] == 3) 151 { 152 if(player.x > i * blockSize + blockSize || player.y > j*blockSize + blockSize || player.x2 < i*blockSize || player.y2 < j*blockSize) 153 { 154 //no collision 155 } 156 157 else 158 { 159 int level = map.getLevel(); 160 level ++; 161 map.setLevel(level); 162 if(level > 2) 163 { 164 map.setLevel(0); 165 player.velx = player.speed; 166 player.hDir = 1; 167 } 168 player.x = player.origX; 169 player.y = player.origY; 170 171 //Wait 1 second (loading new map) 172 al_clear_to_color(al_map_rgb(0, 0, 0)); 173 al_flip_display(); 174 //al_rest(1); 175 } 176 } 177 } 178 } 179 180} 181 182void Collision::DirReverse(Player &player, Map &map) 183{ 184 for (int i = 0; i < mapSizeX; i++) 185 { 186 for(int j = 0; j < mapSizeY; j++) 187 { 188 if(ColMapFile[map.getLevel()][i][j] == 4) 189 { 190 if(player.x > i * blockSize + blockSize || player.y > j*blockSize + blockSize || player.x2 < i*blockSize || player.y2 < j*blockSize) 191 { 192 //no collision 193 } 194 195 else 196 { 197 198 player.velx = -player.speed; 199 player.hDir = 2; 200 } 201 } 202 } 203 } 204 205}

Dizzy Egg
Member #10,824
March 2009
avatar

Your if/else's look a bit screwed up....at one point you say:

if(x > etc etc etc)
{
    //no collision
}
else
{
    //move x/y etc etc
}

...so you're saying "if there is a collision then move the player"...makes no sense!

----------------------------------------------------
Please check out my songs:
https://soundcloud.com/dont-rob-the-machina

PamperBoy
Member #15,477
January 2014

Then what should i do? because the player moves at a constant speed of 5 to the right. Sorry still a beginner hehe

edit

Also ive been trying to change the code for ages. But what ever i do the result is the same. aka nothing new happens. Also ive been looking at a tutorial, the code that was written in there is practically the same. The only difference is that it works in the tutorial...

Dizzy Egg
Member #10,824
March 2009
avatar

So, explain to me exactly what happens, in as much detail as possible, and I'll help you out.

[edit]

Also, show me the code where you draw the player, and map/tiles.

[edit2]

Also, show me how big your player sprite is, and how big your blocks are! 8-)

----------------------------------------------------
Please check out my songs:
https://soundcloud.com/dont-rob-the-machina

PamperBoy
Member #15,477
January 2014

ill explain what happens: i go to the right at a constant speed of 5. When i encouter a tile i will collide with it but it goes within the tile. and then stops in the middle. Same goes for jumping. When i jump i go either through the whole tile or stop in the middle.

Here is the player class:

#SelectExpand
1#include "Player.h" 2 3 4 5 6Player::Player(void) 7{ 8} 9 10 11Player::~Player(void) 12{ 13} 14 15void Player::Init() 16{ 17 movementPressed = false; 18 width = 10; 19 height = 10; 20 x = 100; 21 y = 450; 22 origX = x; 23 origY = y; 24 x2 = x + width; 25 y2 = y + height; 26 speed = 5; 27 jumpspeed = - (10 + (blockSize / (blockSize / 3))); 28 gravity = 1; 29 velx = vely = 0; 30 jump = platform == false; 31 hDir = 0; 32 vDir = 2; 33 34 35} 36 37void Player::Update(ALLEGRO_EVENT ev, InputManager &input) 38{ 39 Player::Controls(ev, input); 40 41} 42 43void Player::Draw(ALLEGRO_DISPLAY *display) 44{ 45 al_draw_filled_rectangle(x , y , x2, y2, al_map_rgb(255, 200, 0)); 46 al_flip_display(); 47 48} 49 50void Player::Controls(ALLEGRO_EVENT ev, InputManager &input) 51{ 52 if (movementPressed == false) { 53 54 if(input.IsKeyPressed(ev, ALLEGRO_KEY_RIGHT)) 55 { 56 velx = speed; 57 hDir = 1; 58 movementPressed = true; 59 //vely = 0; 60 } 61 /* 62 else if(input.IsKeyPressed(ev, ALLEGRO_KEY_LEFT)) 63 { 64 velx = -speed; 65 hDir = 2; 66 } 67 */ 68 } 69 70 71 if(jump == true && input.IsKeyPressed(ev, ALLEGRO_KEY_UP)) 72 { 73 vely = jumpspeed; 74 platform = false; 75 jump = false; 76 } 77} 78 79void Player::SetPosition() 80{ 81 if (vely >= 0) 82 { 83 vDir = 2; 84 } 85 86 if(platform == false) 87 { 88 vely += gravity; 89 } 90 91 else 92 { 93 vely = 0; 94 } 95 96 x += velx; 97 y += vely; 98 x2 = x + width; 99 y2 = y + height; 100}

Collision class:

#SelectExpand
1#include "Collision.h" 2 3 4Collision::Collision() 5{ 6} 7 8 9Collision::~Collision() 10{ 11} 12 13void Collision::Init() 14{ 15 loadCounterX = loadCounterY = 0; 16 Collision::LoadCollisionMap("ColMap1.txt", 0); 17 Collision::LoadCollisionMap("ColMap2.txt", 1); 18 Collision::LoadCollisionMap("ColMap3.txt", 2); 19} 20 21void Collision::Update(ALLEGRO_DISPLAY *display, Player &player, Map &map) 22{ 23 Collision::PlatformCollision(display, player, map); 24 Collision::LevelReset(player, map); 25 Collision::DirReverse(player, map); 26 Collision::LevelEnd(player, map); 27} 28 29void Collision::Draw(ALLEGRO_DISPLAY *display) 30{ 31 32} 33 34void Collision::LoadCollisionMap(const char *filename, int level) 35{ 36 ifstream openfile(filename); 37 if(openfile.is_open()) 38 { 39 openfile >> mapSizeX >> mapSizeY; 40 while(!openfile.eof()) 41 { 42 openfile >> ColMapFile[level][loadCounterX][loadCounterY]; 43 loadCounterX ++; 44 if (loadCounterX >= mapSizeX) 45 { 46 loadCounterX = 0; 47 loadCounterY ++; 48 } 49 } 50 loadCounterX = loadCounterY = 0; 51 } 52 else 53 { 54 { al_show_native_message_box(NULL, "Error", "Error", 55 "Cannot find collision map file", NULL, NULL); 56 } 57 58 } 59} 60 61void Collision::PlatformCollision(ALLEGRO_DISPLAY *display, Player &player, Map &map) 62{ 63 for (int i = 0; i < mapSizeX; i++) 64 { 65 for(int j = 0; j < mapSizeY; j++) 66 { 67 if(ColMapFile[map.getLevel()][i][j] == 1) 68 { 69 if(player.x > i * blockSize + blockSize || player.y > j*blockSize + blockSize || player.x2 < i*blockSize || player.y2 < j*blockSize) 70 { 71 //no collision 72 player.platform = false; 73 } 74 75 else 76 { 77 if (player.vDir == 1) 78 { 79 player.y += player.speed * 2; 80 player.y2 = player.y + 10; 81 player.vely = 0; 82 player.platform = false; 83 player.jump = false; 84 } 85 86 if(player.vDir == 2 && player.y - player.vely <= j*blockSize) 87 { 88 player.y = j*blockSize - 10; 89 player.y2 = player.y + 10; 90 player.platform = true; 91 player.jump = true; 92 player.vely = 0; 93 94 } 95 96 97 if (player.hDir == 1 && player.platform == false) 98 { 99 player.x -= player.speed; 100 player.x2 = player.x ; 101 } 102 103 if (player.hDir == 2 && player.platform == false) 104 { 105 player.x += player.speed; 106 player.x2 = player.x + 10; 107 } 108 } 109 } 110 } 111 } 112} 113 114void Collision::LevelReset(Player &player, Map &map) 115{ 116 for (int i = 0; i < mapSizeX; i++) 117 { 118 for(int j = 0; j < mapSizeY; j++) 119 { 120 if(ColMapFile[map.getLevel()][i][j] == 2) 121 { 122 if(player.x > i * blockSize + blockSize || player.y > j*blockSize + blockSize || player.x2 < i*blockSize || player.y2 < j*blockSize) 123 { 124 //no collision 125 } 126 127 else 128 { 129 player.x = player.origX; 130 player.y = player.origY; 131 132 map.setLevel(0); 133 134 player.velx = player.speed; 135 player.hDir = 1; 136 } 137 } 138 } 139 } 140 141} 142 143void Collision::LevelEnd(Player &player, Map &map) 144{ 145 for (int i = 0; i < mapSizeX; i++) 146 { 147 for(int j = 0; j < mapSizeY; j++) 148 { 149 if(ColMapFile[map.getLevel()][i][j] == 3) 150 { 151 if(player.x > i * blockSize + blockSize || player.y > j*blockSize + blockSize || player.x2 < i*blockSize || player.y2 < j*blockSize) 152 { 153 //no collision 154 } 155 156 else 157 { 158 int level = map.getLevel(); 159 level ++; 160 map.setLevel(level); 161 if(level > 2) 162 { 163 map.setLevel(0); 164 player.velx = player.speed; 165 player.hDir = 1; 166 } 167 player.x = player.origX; 168 player.y = player.origY; 169 170 //Wait 1 second (loading new map) 171 al_clear_to_color(al_map_rgb(0, 0, 0)); 172 al_flip_display(); 173 //al_rest(1); 174 } 175 } 176 } 177 } 178 179} 180 181void Collision::DirReverse(Player &player, Map &map) 182{ 183 for (int i = 0; i < mapSizeX; i++) 184 { 185 for(int j = 0; j < mapSizeY; j++) 186 { 187 if(ColMapFile[map.getLevel()][i][j] == 4) 188 { 189 if(player.x > i * blockSize + blockSize || player.y > j*blockSize + blockSize || player.x2 < i*blockSize || player.y2 < j*blockSize) 190 { 191 //no collision 192 } 193 194 else 195 { 196 197 player.velx -= player.speed; 198 player.hDir = 2; 199 } 200 } 201 } 202 } 203 204}

Global.h:

#SelectExpand
1#define ScreenWidth 800 2#define ScreenHeight 600 3#define blockSize 25

Dizzy Egg
Member #10,824
March 2009
avatar

Ok, first off, adding 5 pixels a time is mega fast! Can you show me your main game loop, where you call all the functions please? :D

----------------------------------------------------
Please check out my songs:
https://soundcloud.com/dont-rob-the-machina

PamperBoy
Member #15,477
January 2014

Hehe it's a freaking mess and not commented hope you can find what you are looking for XD

#SelectExpand
1#include<iostream> 2#include<allegro5\allegro5.h> 3#include<fstream> 4//#include"Map.h" 5#include"Global.h" 6#include"Player.h" 7#include"InputManager.h" 8#include"Collision.h" 9#include<allegro5\keyboard.h> 10#include "Cam.h" 11 12using namespace std; 13 14int main() 15{ 16 ALLEGRO_DISPLAY *display; 17 18 const float FPS = 60.0; 19 bool done = false; 20 21 //initialize Allegro & Display. If not you get error message. 22 23 if(!al_init()) 24 { al_show_native_message_box(NULL, "Error", "Error", 25 "Cannot initialize Allegro", NULL, NULL); 26 return -1; 27 } 28 29 display = al_create_display(ScreenWidth, ScreenHeight); 30 31 if(!display) 32 { 33 al_show_native_message_box(NULL, "Error", "Error", 34 "Cannot create display", NULL, NULL); 35 return -1; 36 } 37 38 //al_set_window_position(display, 200, 200); //If window doesnt appear on screen 39 40 al_init_primitives_addon(); 41 al_install_keyboard(); 42 43 ALLEGRO_TIMER *timer = al_create_timer(1.0 / FPS); 44 ALLEGRO_EVENT_QUEUE *event_queue = al_create_event_queue(); 45 ALLEGRO_KEYBOARD_STATE keyState; 46 47 ALLEGRO_TRANSFORM camera; 48 49 al_register_event_source(event_queue, al_get_keyboard_event_source()); 50 al_register_event_source(event_queue, al_get_timer_event_source(timer)); 51 al_register_event_source(event_queue, al_get_display_event_source(display)); 52 53 InputManager input; 54 Player player; 55 Map map; 56 Collision collision; 57 Cam cam; 58 59 map.Init(); 60 player.Init(); 61 collision.Init(); 62 cam.Init(); 63 float cameraPosition[2] = { 0, 0 }; 64 65 66 67 al_start_timer(timer); 68 69while(!done) 70 { 71 ALLEGRO_EVENT ev; 72 al_wait_for_event(event_queue, &ev); 73 al_get_keyboard_state(&keyState); 74 75 76 if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) 77 { 78 done = true; 79 } 80 81 else if(input.IsKeyPressed(ev, ALLEGRO_KEY_ESCAPE)) 82 { 83 done = true; 84 } 85 86 87 player.Controls(ev, input); 88 map.Draw(display); 89 player.SetPosition(); 90 player.Draw(display); 91 cam.Update(cameraPosition, player); 92 93 al_identity_transform(&camera); 94 al_translate_transform(&camera, -(player.x + 16) , -(player.y + 16)); 95 al_translate_transform(&camera, - cameraPosition[0] + (player.x+ 16), 96 -cameraPosition[1] + (player.y + 16)); 97 al_use_transform(&camera); 98 99 collision.Update(display, player, map); 100 101 } 102 103 104 105 al_destroy_display(display); 106 al_destroy_timer(timer); 107 al_destroy_event_queue(event_queue); 108 109 return 0; 110}

Dizzy Egg
Member #10,824
March 2009
avatar

Ok, there's a couple of things going on here that aren't quite right; and that doesn't mean anything negative with regards to you, there's things I do wrong all the time, that's the beauty of this forum, there's so much knowledge you can just keep getting better!...

...ok, first off, do you see that you're updating your player's x & y twice each loop? Once in the player.setPosition, and also in the collision class...

...don't change the players x/y in the collision function, that's what player.setPosition is for!...

...instead, give the player class a new bool, and call it canMove...set it to true when you call the player constructor, and set it to false when you have a collision; then, in your player.setPosition, ONLY allow the change of x/y if player.canMove == true...

...after you've done that, let me know what happens!

[EDIT]

(You're not using the timers quite right either, and a few other bits, but let's do this a problem at a time! :P)

[EDIT2]

updated!! ;)

----------------------------------------------------
Please check out my songs:
https://soundcloud.com/dont-rob-the-machina

PamperBoy
Member #15,477
January 2014

lets see. I dont think i get it... (this gives me the same result. when i colide to the left side of a tile i go in there in stop in the middle.)

this is an if statement in the collision.cpp

#SelectExpand
1if(player.hDir == 1 && player.platform == false) 2 { 3 player.canMove = false; 4 }

this is the player setPosition

#SelectExpand
1void Player::SetPosition() 2{ 3 if (vely >= 0) 4 { 5 vDir = 2; 6 } 7 8 if(canMove == false) 9 { 10 x -= speed; 11 x2 = x + 10; 12 } 13 14 if(platform == false) 15 { 16 vely += gravity; 17 } 18 19 else 20 { 21 vely = 0; 22 } 23 24 x += velx; 25 y += vely; 26 x2 = x + width; 27 y2 = y + height; 28 29}

Dizzy Egg
Member #10,824
March 2009
avatar

I suppose the best way to get this solved fast is if you can send me your code? I could compile it here and find out why it's happening, and send you back the fixed code? Because at the moment I can't see enough to understand why...!

----------------------------------------------------
Please check out my songs:
https://soundcloud.com/dont-rob-the-machina

Go to: