Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Enemies disappear with out any collision

This thread is locked; no one can reply to it. rss feed Print
Enemies disappear with out any collision
DJLad16
Member #14,857
January 2013

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
Member #7,719
August 2006
avatar

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))

______________________________________
As long as it remains classified how long it took me to make I'll be deemed a computer game genius. - William Labbett
Theory is when you know something, but it doesn't work. Practice is when something works, but you don't know why. Programmers combine theory and practice: Nothing works and they don't know why. -Unknown
I have recklessly set in motion a chain of events with the potential to so-drastically change the path of my life that I can only find it to be beautifully frightening.

Dizzy Egg
Member #10,824
March 2009
avatar

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!

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

DJLad16
Member #14,857
January 2013

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

Thomas Fjellstrom
Member #476
June 2000
avatar

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.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Dizzy Egg
Member #10,824
March 2009
avatar

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.

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

Schyfis
Member #9,752
May 2008
avatar

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

________________________________________________________________________________________________________
[freedwill.us]
[unTied Games]

Dizzy Egg
Member #10,824
March 2009
avatar

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!?!?

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

Karadoc ~~
Member #2,749
September 2002
avatar

Dizzy Egg is right.

-----------

Audric
Member #907
January 2001

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
Member #10,824
March 2009
avatar

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!

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

pkrcel
Member #14,001
February 2012

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.

It is unlikely that Google shares your distaste for capitalism. - Derezo
If one had the eternity of time, one would do things later. - Johan Halmén

EWClay
Member #14,750
December 2012

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

Audric
Member #907
January 2001

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
Member #10,824
March 2009
avatar

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

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

J-Gamer
Member #12,491
January 2011
avatar

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.

" There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo
"If your body was a business, thought would be like micro-management and emotions would be like macro-management. If you primarily live your life with emotions, then you are prone to error on the details. If you over-think things all the time you tend to lose scope of priorities." - Mark Oates

pkrcel
Member #14,001
February 2012

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 )

It is unlikely that Google shares your distaste for capitalism. - Derezo
If one had the eternity of time, one would do things later. - Johan Halmén

Dizzy Egg
Member #10,824
March 2009
avatar

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

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

Karadoc ~~
Member #2,749
September 2002
avatar

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
Member #7,719
August 2006
avatar

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.

______________________________________
As long as it remains classified how long it took me to make I'll be deemed a computer game genius. - William Labbett
Theory is when you know something, but it doesn't work. Practice is when something works, but you don't know why. Programmers combine theory and practice: Nothing works and they don't know why. -Unknown
I have recklessly set in motion a chain of events with the potential to so-drastically change the path of my life that I can only find it to be beautifully frightening.

Karadoc ~~
Member #2,749
September 2002
avatar

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

-----------

someone972
Member #7,719
August 2006
avatar

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

______________________________________
As long as it remains classified how long it took me to make I'll be deemed a computer game genius. - William Labbett
Theory is when you know something, but it doesn't work. Practice is when something works, but you don't know why. Programmers combine theory and practice: Nothing works and they don't know why. -Unknown
I have recklessly set in motion a chain of events with the potential to so-drastically change the path of my life that I can only find it to be beautifully frightening.

Schyfis
Member #9,752
May 2008
avatar

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?

________________________________________________________________________________________________________
[freedwill.us]
[unTied Games]

Go to: