Enemies disappear with out any collision
DJLad16

So I just added two enemies moving on the same platform and when I shoot one, after several seconds the other one disappears with out it hitting anything and vice versa. I know that it is something to do with the collision because I didn't draw the one of the enemies, I shot one and I didn't die when stood on the platform for a while. But I can't see what is wrong with it. Especially as the other enemies work fine (Removed some irrelevant code).

#SelectExpand
1//Prototpyes 2void initPlayer(Player &player); 3 4 5void initEnemy(Enemy &enemy, int x, int y); 6void drawEnemy(Enemy &enemy, ALLEGRO_BITMAP *image); 7void updateEnemy(Enemy &enemy, int posX, int posX2); 8bool collideArrow(Enemy &enemy, Arrow &arrow); 9 10void initCoin(Coin &coin, int x, int y); 11void drawCoin(Coin &coin, ALLEGRO_BITMAP *image); 12bool coinCollide(Coin &coin,Player &player ,int cX, int cY, int cWidth, int cHeight, int pWidth, int pHeight, bool live, int coinCount); 13 14void initArrow(Arrow &arrow); 15void drawArrow(Arrow &arrow, ALLEGRO_BITMAP *image, ALLEGRO_BITMAP *image2); 16void fireArrow(Arrow &arrow, Player &player, ALLEGRO_SAMPLE *bowShot); 17void updateArrow(Arrow &arrow); 18 19void initKey(Key &key); 20void drawKey(Key &key, ALLEGRO_BITMAP *image); 21 22bool collision(Player &player, int ex, int ey, int eWidth, int eHeight, int pWidth, int pHeight); 23 24void cameraUpdate(float *cameraPosition,Player &player, float width, float height); 25 26//Global Variables 27enum direction {LEFT, RIGHT}; 28int dir = LEFT; 29const int NUM_ENEMY = 10; 30 31bool fired = false, firedR = false, firedL = false; 32bool coinLive = false; 33bool left, right = false; 34const float gravity = 1; 35 36int main() 37{ 38 39 Player player; 40 Enemy enemy; 41 Enemy enemy2; 42 Enemy enemy3; 43 Enemy enemy4; 44 Coin coin; 45 Coin coin2; 46 Arrow arrow; 47 Key key; 48 int groundHeight = 535; 49 bool done = false, active = false, draw = true; 50 bool jump = false; 51 bool gotKey = false; 52 int sourceX = 32, sourceY = 0; 53 int coinCount = 0; 54 const float FPS = 60.0; 55 const float frameFPS = 15.0; 56 float jumpSpeed = 15.0; 57 float velX = 0, velY = 0; 58 59 float cameraPosition[2] = {0,0}; 60 61 62 63 al_init_image_addon(); 64 al_init_primitives_addon(); 65 al_install_keyboard(); 66 al_init_font_addon(); 67 al_init_ttf_addon(); 68 al_install_audio(); 69 al_init_acodec_addon(); 70 71 initPlayer(player); 72 initEnemy(enemy, 86, 391); 73 initEnemy(enemy2, 1167, 333); 74 initEnemy(enemy3, 378, 473); 75 initEnemy(enemy4, 649, 473); 76 initArrow(arrow); 77 initCoin(coin, 550, 480); 78 initCoin(coin2, 120, 398); 79 initKey(key); 80 81 ALLEGRO_KEYBOARD_STATE keystate; 82 ALLEGRO_TRANSFORM camera; 83 ALLEGRO_TRANSFORM identity; 84 ALLEGRO_SAMPLE *coinCollect = al_load_sample("Files/coin collect sound.wav"); 85 ALLEGRO_SAMPLE *bowShot = al_load_sample("Files/bow sound effect.wav"); 86 ALLEGRO_SAMPLE *bgSong = al_load_sample("Files/Background song 2.wav"); 87 ALLEGRO_SAMPLE *keyCollection = al_load_sample("Files/key collection.wav"); 88 ALLEGRO_SAMPLE *crocSound = al_load_sample("Files/Crocodile sound effect.wav"); 89 ALLEGRO_SAMPLE_INSTANCE *songInstance = al_create_sample_instance(bgSong); 90 ALLEGRO_BITMAP *enemyImg = al_load_bitmap("Files/enemy.png"); 91 ALLEGRO_BITMAP *background2 = al_load_bitmap("Files/Background 2.png"); 92 ALLEGRO_BITMAP *character = al_load_bitmap("Files/spritesheet(Bow & left + right).png"); 93 ALLEGRO_BITMAP *arrow_r = al_load_bitmap("Files/Arrow(RIGHT).png"); 94 ALLEGRO_BITMAP *arrow_l = al_load_bitmap("Files/Arrow(LEFT).png"); 95 ALLEGRO_BITMAP *coinImg = al_load_bitmap("Files/coin2.png"); 96 ALLEGRO_BITMAP *keyImg = al_load_bitmap("Files/key.png"); 97 ALLEGRO_BITMAP *ground = al_load_bitmap("Files/Ground.png"); 98 ALLEGRO_FONT *font = al_load_font("Files/JUNGBN__.TTF", 23, 0); 99 ALLEGRO_TIMER *timer = al_create_timer(1.0/FPS); 100 ALLEGRO_TIMER *frameTimer = al_create_timer(1.0/frameFPS); 101 ALLEGRO_EVENT_QUEUE *event_queue = al_create_event_queue(); 102 103 al_reserve_samples(5); //Respresents how many audio clips I have in the game 104 105 al_set_sample_instance_playmode(songInstance, ALLEGRO_PLAYMODE_LOOP); 106 al_attach_sample_instance_to_mixer(songInstance, al_get_default_mixer()); 107 al_set_window_title(display, "Australian Outback"); 108 al_register_event_source(event_queue, al_get_keyboard_event_source()); 109 al_register_event_source(event_queue, al_get_timer_event_source(timer)); 110 al_register_event_source(event_queue, al_get_timer_event_source(frameTimer)); 111 al_register_event_source(event_queue, al_get_display_event_source(display)); 112 113 al_play_sample_instance(songInstance); 114 115 al_start_timer(timer); 116 al_start_timer(frameTimer); 117 while(!done) 118 { 119 ALLEGRO_EVENT event; 120 al_wait_for_event(event_queue, &event); 121 al_get_keyboard_state(&keystate); 122 123 if(al_key_down(&keystate, ALLEGRO_KEY_ESCAPE)) 124 { 125 done = true; 126 } 127 else if(event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) 128 { 129 done = true; 130 } 131 132 133 else if(event.type == ALLEGRO_EVENT_TIMER) 134 { 135 if(event.timer.source == timer) 136 { 137 active = true; 138 updateArrow(arrow); 139 updateEnemy(enemy, 238, 78); 140 updateEnemy(enemy2, 1236, 1167); 141 updateEnemy(enemy3, 660, 378); 142 updateEnemy(enemy4, 660, 378); 143 144 if(al_key_down(&keystate, ALLEGRO_KEY_D)) 145 { 146 velX = player.speed; 147 dir = RIGHT; 148 149 } 150 else if(al_key_down(&keystate, ALLEGRO_KEY_A)) 151 { 152 velX = -player.speed; 153 dir = LEFT; 154 } 155 else 156 { 157 velX = 0; 158 active = false; 159 } 160 if(al_key_down(&keystate, ALLEGRO_KEY_W) && jump) 161 { 162 velY = -jumpSpeed; 163 jump = false; 164 } 165 } 166 else if(event.timer.source = frameTimer) 167 { 168 if(active) 169 { 170 sourceX += al_get_bitmap_width(character) / 3; 171 } 172 else 173 { 174 sourceX = 32; 175 } 176 if(sourceX >= al_get_bitmap_width(character)) 177 { 178 sourceX = 0; 179 } 180 sourceY = dir; 181 182 183 } 184 185 if(!jump) 186 velY += gravity; 187 else 188 velY = 0; 189 player.x += velX; 190 player.y += velY; 191 192 jump = (player.y >= groundHeight); 193 194 if(jump) 195 { 196 player.y = groundHeight; 197 } draw = true; 198 199 200 cameraUpdate(cameraPosition, player, 32, 32); 201 al_identity_transform(&camera); 202 al_translate_transform(&camera, -cameraPosition[0], -cameraPosition[1]); 203 al_use_transform(&camera); 204 205 } 206 207 if(al_key_down(&keystate, ALLEGRO_KEY_SPACE)) 208 { 209 fireArrow(arrow, player, bowShot); 210 } 211 if(collision(player, enemy.x, enemy.y, enemy.width, enemy.height, 32, 32))//Player collision with enemy 212 { 213 player.x = 10; 214 player.y = 546; 215 --player.lives; 216 arrow.live = false; 217 dir = RIGHT; 218 } 219 if(collision(player, enemy2.x, enemy2.y, enemy2.width, enemy2.width, 32, 32))//Player collision with enemy 220 { 221 player.x = 10; 222 player.y = 546; 223 --player.lives; 224 arrow.live = false; 225 dir = RIGHT; 226 } 227 if(collision(player, enemy3.x, enemy3.y, enemy3.width, enemy3.width, 32, 32))//Player collision with enemy 228 { 229 player.x = 10; 230 player.y = 546; 231 --player.lives; 232 arrow.live = false; 233 dir = RIGHT; 234 } 235 if(collision(player, enemy4.x, enemy4.y, enemy4.width, enemy4.width, 32, 32))//Player collision with enemy 236 { 237 player.x = 10; 238 player.y = 546; 239 --player.lives; 240 arrow.live = false; 241 dir = RIGHT; 242 } 243 if(player.x == 1090 && player.y == 535 || player.x == 670 && player.y == 535) 244 { 245 al_play_sample(crocSound, 1.0, 0.0, 1.0, ALLEGRO_PLAYMODE_ONCE, 0); 246 } 247 if(collideArrow(enemy, arrow))//Arrow Collision with enemy 248 { 249 enemy.live = false; 250 enemy.x = -500; 251 enemy.y = -500; 252 arrow.live = false; 253 ++player.score; 254 } 255 if(collideArrow(enemy2, arrow))//Arrow Collision with enemy 256 { 257 enemy2.live = false; 258 enemy2.x = -500; 259 enemy2.y = -500; 260 arrow.live = false; 261 ++player.score; 262 } 263 if(collideArrow(enemy3, arrow))//Arrow Collision with enemy 264 { 265 enemy3.live = false; 266 enemy3.x = -500; 267 enemy3.y = -500; 268 arrow.live = false; 269 ++player.score; 270 } 271 if(collideArrow(enemy4, arrow))//Arrow Collision with enemy 272 { 273 enemy4.live = false; 274 enemy4.x = -500; 275 enemy4.y = -500; 276 arrow.live = false; 277 ++player.score; 278 } 279 280 if(draw && al_is_event_queue_empty(event_queue)) 281 { 282 draw = false; 283 al_draw_bitmap(background2, 0, 0, 0); 284 al_draw_bitmap_region(character, sourceX, sourceY * al_get_bitmap_height(character) / 2, 32, 32, player.x, player.y, 0); 285 drawKey(key, keyImg); 286 drawArrow(arrow, arrow_r, arrow_l); 287 drawCoin(coin, coinImg); 288 drawCoin(coin2, coinImg); 289 drawEnemy(enemy, enemyImg); 290 drawEnemy(enemy2, enemyImg); 291 drawEnemy(enemy3, enemyImg); 292 drawEnemy(enemy4, enemyImg); 293 al_identity_transform(&identity); 294 al_use_transform(&identity); 295 al_draw_textf(font, al_map_rgb(252,209, 22), 10, 10, 0, "Arrows: %i", arrow.arrowCount); 296 al_draw_textf(font, al_map_rgb(252, 209, 22), 10, 50, 0, "Coins: %i", coinCount); 297 al_draw_textf(font, al_map_rgb(252, 209, 22), 110, 10, 0, "Lives: %i", player.lives); 298 //al_draw_textf(fps, al_map_rgb(252, 209, 22), 110, 50, 0, "FPS: %i", FPS); 299 al_flip_display(); 300 al_clear_to_color(al_map_rgb(255, 255, 255)); 301 302 } 303 } 304} 305void initPlayer(Player &player) 306{ 307 player.x = 10; 308 player.y = 535; 309 player.lives = 3; 310 player.speed = 5; 311 player.score = 0; 312 dir = RIGHT; 313} 314 315void initEnemy(Enemy &enemy, int x, int y) 316{ 317 enemy.live = true; 318 enemy.speedR = 2; 319 enemy.speedL = -2; 320 enemy.speed = 2; 321 enemy.x = x; 322 enemy.y = y; 323 enemy.width = 29; 324 enemy.height = 29; 325} 326void drawEnemy(Enemy &enemy, ALLEGRO_BITMAP *image) 327{ 328 if(enemy.live) 329 { 330 al_draw_bitmap(image, enemy.x, enemy.y, 0); 331 } 332} 333void updateEnemy(Enemy &enemy, int posX, int posX2) 334{ 335 if(enemy.live) 336 { 337 enemy.x += enemy.speed; 338 if(enemy.x >= posX) 339 { 340 enemy.x = posX; 341 enemy.speed = enemy.speedL; 342 } 343 if(enemy.x <= posX2) 344 { 345 enemy.x = posX2; 346 enemy.speed = enemy.speedR; 347 } 348 } 349} 350bool collideArrow(Enemy &enemy, Arrow &arrow) 351{ 352 if((arrow.x > enemy.x + enemy.width) || (arrow.y > enemy.y + enemy.height) || 353 (enemy.x > arrow.x + arrow.height) || (enemy.y > arrow.y + arrow.height) && (enemy.live) && (arrow.live)) 354 { 355 return false; 356 } 357 return true; 358} 359}

someone972

I believe part of the problem is in your collideArrow function:

if((arrow.x > enemy.x + enemy.width) || (arrow.y > enemy.y + enemy.height) ||
     (enemy.x > arrow.x + arrow.height) || (enemy.y > arrow.y + arrow.height) && (enemy.live) && (arrow.live))

What you probably want it to be is:

if((arrow.x > enemy.x + enemy.width) || (arrow.y > enemy.y + enemy.height) ||
     (enemy.x > arrow.x + arrow.height) || (enemy.y > arrow.y + arrow.height) || !(enemy.live) || !(arrow.live))

Dizzy Egg

I think that's very wrong....your basically saying "if the arrow is further right or higher than the enemy or the enemy is further right or higher than the arrow"...doesn't make sense.

Also someone's advice is terrible!

DJLad16

Thanks, someone, got it working :D What do you mean dizzy? The collision works fine, simple bounding box collision.

Thomas Fjellstrom

It seems like you're just checking each corner in isolation when you should be checking to see if the arrow is inside the bounding rectangle.

Dizzy Egg

No, that ain't no bounding box collision! That's exactly what I said in my post. If you made bounding box collision with that code in someones post, I'll fry myself.

Schyfis

I think what you want to be doing for collision detection is something like the first line of the function I posted over here.
What you have is slightly similar, but wrong in the end.

You should also separate the enemy.live and arrow.live checks from the actual collision detection itself to make things clearer.

if(!enemy.live || !arrow.live) return;
//now, check for collision

Dizzy Egg

I have no idea what any of you are talking about any more. Since when has it ever been possible to do a bounding box collision just using OR's....none of the code you're posting works!?!?

Karadoc ~~

Dizzy Egg is right.

Audric

The two forms are logically the same:

if((arrow.x > enemy.x + enemy.width) || (arrow.y > enemy.y + enemy.height) ||
     (enemy.x > arrow.x + arrow.height) || (enemy.y > arrow.y + arrow.height) || !(enemy.live) || !(arrow.live))
  return false;
return true

// or:

if((arrow.x <= enemy.x + enemy.width) && (arrow.y <= enemy.y + enemy.height) &&
     (enemy.x <= arrow.x + arrow.height) && (enemy.y <= arrow.y + arrow.height) && (enemy.live) && (arrow.live))
  return true;
return false

Dizzy Egg

So it turns out the only Allegroid left with an IQ is Karadoc, because the rest of you are missing the point....bounding box would imply checking within a box!

pkrcel

To me also does not look like a bounding box collision. ???

EDIT: ah OK, the expression is NEGATED by the return values so the logic AND is susbstituted by the equivalent negated logic *N*OR.....haven't checked deeply but MAY be ok.

EWClay

Apparently with all the fuss over logic no one's noticed that it should be arrow.width on the second line.

Audric

Dizzy, I'm sorry but this code is ok... there's a little bug that uses height instead of width once (he couldn't notice it if they are equal), but otherwise it's intended to check if two rectangles overlap :

One rectangle goes
- horizontally from (arrow.x) to (arrow.x + arrow.width)
- vertically from (arrow.y) to (arrow.y + arrow.height)

The other rectangle goes
- horizontally from (enemy.x) to (enemy.x + enemy.width)
- vertically from (enemy.y) to (enemy.y + enemy.height)

Dizzy Egg

Nope. According to his logic, if my arrow is farther right OR higher than the enemy, there's a collision. No box involved.

J-Gamer
Dizzy Egg said:

Nope. According to his logic, if my arrow is farther right OR higher than the enemy, there's a collision. No box involved.

You seem to fail to see that the return statement reached when the condition is true returns false. That code checks for all cases where there is no collision, and returns true otherwise.

pkrcel

AABBCollision can be carried out checking if the two boxes overlap, or if the DO NOT overlap, but in that case you have to return negated values of course.

That is what I failed to see as well (the xchange between return false and return true ;D )

Dizzy Egg

...ooooh....tits. My bad.

Karadoc ~~

I guess Dizzy Egg and I were wrong all along. :(

I had only looked at the snippet someone972 posted, and I wrongly assumed the condition was to test for a collision rather than for a miss.

someone972

Ha, I just came back to this thread to see if it got resolved and I got a good chuckle from the stream of posts ;D.

EDIT: If all that is needed is to check whether two bounding boxes collide, the negated method works fine and is actually a little more optimized since it bails early if one of the checks fails. Of course it's a nearly worthless optimization.

Karadoc ~~

Both methods 'bail early' if one of the checks fails.

someone972

Whoops, that's true. Looks like I'm not thinking strait today either :-X.

Schyfis

I dunno why, but I just like the "opposite way" of checking for bounding box collision. My brain wraps around it easier.

Either way, were you able to figure it out, DJLad16?

Thread #612123. Printed from Allegro.cc