Allegro.cc - Online Community

Allegro.cc Forums » The Depot » Basic Turret Defense Game

This thread is locked; no one can reply to it. rss feed Print
 1   2 
Basic Turret Defense Game
Mark Oates
Member #1,146
March 2001
avatar

Wuh!?

Original idea from this thread

OK, the tank idea was cool but it eventually turned into a a turret game. The tank moving/aiming controls didn't work so well in a single player, a little slow, so I turned the tanks into turrets and did a turret-defense type game.

The game is bare-bones. It's for testing the "robustness" of my little framework thing I'm working on. Technically, the game came together quickly! If I feel like it, I might add damage to the turrets, shields (shields are drawn but they serve no purpose), power-ups, etc.

Screenshot

{"name":"600036","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/9\/09fc3b48d9ef600f6449dde51a2f5ba7.png","w":626,"h":491,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/9\/09fc3b48d9ef600f6449dde51a2f5ba7"}600036

Download

Basic Turret Defense Game V1

Instructions

  1. shoot with the left turret using mouse b1

  2. shoot with the right using mouse b2

  3. there can only be 4 bullets on the screen at a time.

  4. have fun watching in debug mode (F1) 8-)

  5. starts slow, speeds up for difficulty

  6. enemy bombs are positioned randomly, so you may experience an even distribution in one game only to have massive waves of bombs in another.

  7. no sound

  8. press ESC to quit, or use the close button in your window. (I recommend ESC, the close button can still get backed up from events)

  9. only one "level"

  10. if you lose, close and start again.

  11. on the top left is the number of enemies left

Questions

  1. How many tries does it take you to win?

  2. Do you experience any slow-downs or serious time stutters?

  3. Does it run? :P need dlls?

Malinus
Member #11,332
September 2009

1. First attempt, with not even one that manged to get by my furious burst of fire.

2. None (2ghz laptop)
3. It does run, I would even say smooth.

Slartibartfast
Member #8,789
June 2007
avatar

Dario ff
Member #10,065
August 2008
avatar

1) I never winned. I tried twice. I suck at double coordination games. :(
2) Nope. Athlon X2 2.7 GHZ
3) Yes, pretty smoothly.

I like the idea of your framework(I red your other post). Maybe I'll start a fresh one after CH. It'd be so much cleaner than the mess I have actually :-/

TranslatorHack 2010, a human translation chain in a.cc.
My games: [GiftCraft] - [Blocky Rhythm[SH2011]] - [Elven Revolution] - [Dune Smasher!]

Trent Gamblin
Member #261
April 2000
avatar

Slart: There's been a screenshot there since he started the thread ::)

Matthew Leverton
Supreme Loser
January 1999
avatar

Is the sourcecode in the screenshot?

Trent Gamblin
Member #261
April 2000
avatar

Oh, the meaning of NSND changed? I didn't get the memo. ???

MiquelFire
Member #3,110
January 2003
avatar

It changed for this topic at least.

---
Febreze (and other air fresheners actually) is just below perfumes/colognes, and that's just below dead skunks in terms of smells that offend my nose.
MiquelFire.red | +Me
If it doesn't resolve the issue, we'll evaluate whether the latest round of anti-speculative-execution patches we've had to apply could somehow be responsible. (The performance impact of this fix is estimated to be just a couple of percent, but a banana on a football field isn't even that much and yet woe unto the quarterback who steps on it.) Gonna have to start looking at AMD CPUs. ~Owner of Nearly Free Speech.net

Slartibartfast
Member #8,789
June 2007
avatar

Dario ff
Member #10,065
August 2008
avatar

What's the Einstein image in the data folder used for? ;D

TranslatorHack 2010, a human translation chain in a.cc.
My games: [GiftCraft] - [Blocky Rhythm[SH2011]] - [Elven Revolution] - [Dune Smasher!]

BAF
Member #2,981
December 2002
avatar

Holy shit, when did Allegro become bloated with 10+ dlls?

Anyway, I didn't win, only tried a few times though. Ran smoothly, ran fine. The bursts were weird, and the game was difficult at spots where you'd have a bunch of dots bunched together but can only shoot 4 bullets (also, the bullets slowing down near their destination seemed really weird at first).

Trent Gamblin
Member #261
April 2000
avatar

1) only tried once, was pretty hard with a trackpad (especially since it only has one button!)
2) Nice and smooth
3) Probably too many dlls :P

MiquelFire
Member #3,110
January 2003
avatar

BAF said:

Holy shit, when did Allegro become bloated with 10+ dlls?

You haven't been paying attention to Allegro 5's development, have you?

---
Febreze (and other air fresheners actually) is just below perfumes/colognes, and that's just below dead skunks in terms of smells that offend my nose.
MiquelFire.red | +Me
If it doesn't resolve the issue, we'll evaluate whether the latest round of anti-speculative-execution patches we've had to apply could somehow be responsible. (The performance impact of this fix is estimated to be just a couple of percent, but a banana on a football field isn't even that much and yet woe unto the quarterback who steps on it.) Gonna have to start looking at AMD CPUs. ~Owner of Nearly Free Speech.net

Mark Oates
Member #1,146
March 2001
avatar

Quote:

So you expect me to boot into windows just to see your game?

Either that or buy a copy if Windows if you don't have it. ;)

Quote:

NSND; No Source No Download.

No download then. My source code is still top secret. :o:o Not to say that I don't support Linux, just not for this purpose. If I were to make a real game then I'd look into providing some kind of support for the other platforms.

Apart from the framework code, here's the code I wrote for the actual game:

#SelectExpand
1Object tank1; 2Object turret1; 3 4Object tank2; 5Object turret2; 6 7Object bullet1; 8Object bullet2; 9Object bullet3; 10Object bullet4; 11 12Object title_text; 13 14Object sheild1; 15Object sheild2; 16 17#define TURRET_ROTATION_SPEED 0.01f 18 19 20int tank_strength = 5; 21 22 23float sheild_max_scale = 1.2; 24float sheild_min_scale = 0.9; 25 26 27 28Object win_notification; 29Object win_notification_2; 30 31 32Object fail_notification; 33Object fail_notification_2; 34 35 36 37enum { GAME_STATE_PLAYING, GAME_STATE_WIN, GAME_STATE_FAIL }; 38int game_state = GAME_STATE_PLAYING; 39 40 41 42vector<Object *> enemies; 43 44 45 46void init_bullet_position(Object *bullet) 47{ 48 bullet->position(-300, -300); 49} 50 51 52void initialize() 53{ 54 tank1.set_image("data/images/tank.png"); 55 tank1.position(100, screen_h-160); 56 tank1.align(ALIGN_CENTER, ALIGN_MIDDLE); 57 tank1.scale_x = 0.75; 58 tank1.scale_y = 0.75; 59 tank1.position_z = 2; 60 61 tank2.set_image("data/images/tank.png"); 62 tank2.position(screen_w-100, screen_h-160); 63 tank2.align(ALIGN_CENTER, ALIGN_MIDDLE); 64 tank2.scale_x = 0.75; 65 tank2.scale_y = 0.75; 66 tank2.position_z = 2; 67 68 turret1.set_image("data/images/turret.png"); 69 turret1.position(screen_w/2, screen_h/2); 70 turret1.align(ALIGN_CENTER, 0.75); 71 turret1.position_z = 3; 72 73 turret2.set_image("data/images/turret.png"); 74 turret2.position(screen_w/2, screen_h/2); 75 turret2.align(ALIGN_CENTER, 0.75); 76 turret2.position_z = 3; 77 78 bullet1.set_image("data/images/bullet.png"); 79 bullet1.align(ALIGN_CENTER, ALIGN_MIDDLE); 80 bullet1.opacity = 0.0; 81 init_bullet_position(&bullet1); 82 83 bullet2.set_image("data/images/bullet.png"); 84 bullet2.align(ALIGN_CENTER, ALIGN_MIDDLE); 85 bullet2.opacity = 0.0; 86 init_bullet_position(&bullet2); 87 88 bullet3.set_image("data/images/bullet.png"); 89 bullet3.align(ALIGN_CENTER, ALIGN_MIDDLE); 90 bullet3.opacity = 0.0; 91 init_bullet_position(&bullet3); 92 93 bullet4.set_image("data/images/bullet.png"); 94 bullet4.align(ALIGN_CENTER, ALIGN_MIDDLE); 95 bullet4.opacity = 0.0; 96 init_bullet_position(&bullet4); 97 98 99 100 sheild1.set_image("data/images/sheild.png"); 101 sheild1._blending_mode = BLENDER_ADDITIVE; 102 sheild1.align(ALIGN_CENTER, ALIGN_MIDDLE); 103 sheild1.opacity = 0.3; 104 sheild1.position_z = 4; 105 sheild1.scale_x = sheild_min_scale; 106 sheild1.scale_y = sheild_min_scale; 107 108 109 sheild2.set_image("data/images/sheild.png"); 110 sheild2._blending_mode = BLENDER_ADDITIVE; 111 sheild2.align(ALIGN_CENTER, ALIGN_MIDDLE); 112 sheild2.opacity = 0.3; 113 sheild2.position_z = 4; 114 sheild2.scale_x = sheild_min_scale; 115 sheild2.scale_y = sheild_min_scale; 116 117 118 119 120 title_text.set_image(get_text_render("data/fonts/StencilStd.otf", -110, "TANK")); 121 title_text.position(screen_w/2, screen_h/2); 122 title_text.align(ALIGN_CENTER, ALIGN_MIDDLE); 123 title_text.hide(0); 124 125 title_text.show(0.4, ANIMATION_CURVE_DOUBLE_SLOW); 126 127 128 129 win_notification.set_image(get_text_render("data/fonts/StencilStd.otf", -200, "WIN")); 130 win_notification.align_center(); 131 win_notification.align_middle(); 132 win_notification.tint = al_color_name("green"); 133 win_notification.position(screen_w/2, screen_h/2); 134 win_notification.hide(0); 135 win_notification.bring_to_top(); 136 137 win_notification_2.set_image(get_text_render("data/fonts/StencilStd.otf", -40, "That's all for now folks!")); 138 win_notification_2.align_center(); 139 win_notification_2.align_middle(); 140 win_notification_2.tint = al_color_name("green"); 141 win_notification_2.position(screen_w/2, screen_h/3*2); 142 win_notification_2.hide(0); 143 win_notification_2.bring_to_top(); 144 145 146 147 fail_notification.set_image(get_text_render("data/fonts/StencilStd.otf", -200, "FAIL")); 148 fail_notification.align_center(); 149 fail_notification.align_middle(); 150 fail_notification.tint = al_color_name("red"); 151 fail_notification.position(screen_w/2, screen_h/2); 152 fail_notification.hide(0); 153 fail_notification.bring_to_top(); 154 155 fail_notification_2.set_image(get_text_render("data/fonts/StencilStd.otf", -40, "The ESC key is your only way out.")); 156 fail_notification_2.align_center(); 157 fail_notification_2.align_middle(); 158 fail_notification_2.tint = al_color_name("red"); 159 fail_notification_2.position(screen_w/2, screen_h/3*2); 160 fail_notification_2.hide(0); 161 fail_notification_2.bring_to_top(); 162 163 164 165 Object *obj; 166 int multiplier = 5; 167 for (int i=0; i<20*multiplier; i++) 168 { 169 enemies.push_back(new Object()); 170 obj = enemies[enemies.size()-1]; 171 obj->position_x = random_int(100, screen_w-100); 172 obj->position_y = random_int(-1500*multiplier, 0); 173 obj->set_image("data/images/enemy_bullet.png"); 174 obj->align_center(); 175 obj->align_middle(); 176 } 177} 178 179 180 181 182void win_game() 183{ 184 if (game_state != GAME_STATE_PLAYING) return; 185 game_state = GAME_STATE_WIN; 186 win_notification.show(); 187 win_notification_2.show(); 188} 189 190 191void lose_game() 192{ 193 if (game_state != GAME_STATE_PLAYING) return; 194 game_state = GAME_STATE_FAIL; 195 fail_notification.show(); 196 fail_notification_2.show(); 197} 198 199 200 201#define BULLET_VELOCITY 350.0 202 203void fire_bullet(Object &gun) 204{ 205 Object *obj = NULL; 206 if (!bullet1.visible()) obj = &bullet1; 207 else if (!bullet2.visible()) obj = &bullet2; 208 else if (!bullet3.visible()) obj = &bullet3; 209 else if (!bullet4.visible()) obj = &bullet4; 210 211 if (!obj) return; 212 213 obj->opacity.animate(0.0, 1.0, 0.0, 0.2, ANIMATION_CURVE_DOUBLE_FAST); 214 obj->opacity.animate(1.0, 0.0, 0.6, 0.4, ANIMATION_CURVE_SLOW); 215 obj->position(gun._position_x, gun._position_y); 216 obj->rotation = gun._rotation; 217 218 vec2d destination = PolarCoords(gun._rotation - ALLEGRO_PI/2, BULLET_VELOCITY); 219 220 obj->position_x.animate(gun._position_x, gun._position_x+destination.x, 0.0, 1.0, ANIMATION_CURVE_FAST); 221 obj->position_y.animate(gun._position_y, gun._position_y+destination.y, 0.0, 1.0, ANIMATION_CURVE_FAST); 222} 223 224 225 226 227void update_shield_animation(Object &sheild) 228{ 229 if (sheild._scale_x == sheild_max_scale) 230 { 231 sheild.scale_x.animate(sheild_max_scale, sheild_min_scale, 0.0, 0.5, ANIMATION_CURVE_SLOW_IN_OUT); 232 sheild.scale_y.animate(sheild_max_scale, sheild_min_scale, 0.0, 0.5, ANIMATION_CURVE_SLOW_IN_OUT); 233 } 234 else if (sheild._scale_x == sheild_min_scale) 235 { 236 sheild.scale_x.animate(sheild_min_scale, sheild_max_scale, 0.0, 0.5, ANIMATION_CURVE_SLOW_IN_OUT); 237 sheild.scale_y.animate(sheild_min_scale, sheild_max_scale, 0.0, 0.5, ANIMATION_CURVE_SLOW_IN_OUT); 238 } 239} 240 241 242 243 244float enemy_falling_speed = 1.0f; 245float enemy_falling_accel = 0.0005; 246 247 248 249void detonate_enemy(Object *obj) 250{ 251 obj->opacity.animate(1.0, 0.0, 0.0, 0.5, ANIMATION_CURVE_FAST); 252 obj->tint.animate(al_color_name("white"), al_color_name("red"), 0.1, 0.5, ANIMATION_CURVE_DOUBLE_FAST); 253 obj->scale_x.animate(1.001, 20.0, 0.0, 0.5, ANIMATION_CURVE_DOUBLE_FAST); 254 obj->scale_y.animate(1.001, 20.0, 0.0, 0.5, ANIMATION_CURVE_DOUBLE_FAST); 255} 256 257 258 259void detonate_bullet(Object *bullet) 260{ 261 bullet->opacity = 0.0; 262 init_bullet_position(bullet); 263 bullet->clear_animations(); 264} 265 266 267 268void update_enemy_positions() 269{ 270 Object *obj; 271 for (int i=0; i<(int)enemies.size(); i++) 272 { 273 obj = enemies<i>; 274 obj->position_y += enemy_falling_speed; 275 if (obj->_position_y > screen_h) 276 { 277 if (obj->_scale_x == 1.0) 278 { 279 detonate_enemy(obj); 280 tank_strength -= 1; 281 if (tank_strength <= 0) { tank_strength = 0; lose_game(); } 282 } 283 } 284 } 285} 286 287 288 289 290void test_bullet_collision(Object *obj, Object *bullet) 291{ 292 if (!obj->visible_on_screen()) return; 293 if (obj->_opacity == 1.0 && bullet->_opacity != 0.0 && collides(*obj, *bullet)) 294 { 295 detonate_enemy(obj); 296 detonate_bullet(bullet); 297 } 298} 299 300 301int num_active; 302 303int test_win_condition() 304{ 305 int num_visible = (int)enemies.size(); 306 for (int i=0; i<(int)enemies.size(); i++) 307 { 308 if (!enemies<i>->visible()) num_visible--; 309 } 310 if (num_visible == 0) win_game(); 311 return num_visible; 312} 313 314 315 316void test_bullet_enemy_collisions() 317{ 318 Object *obj; 319 for (int i=0; i<(int)enemies.size(); i++) 320 { 321 obj = enemies<i>; 322 323 test_bullet_collision(obj, &bullet1); 324 test_bullet_collision(obj, &bullet2); 325 test_bullet_collision(obj, &bullet3); 326 test_bullet_collision(obj, &bullet4); 327 } 328} 329 330 331 332#define TANK_VELOCITY 1.0 333 334void update_logic() 335{ 336 if (game_state == GAME_STATE_PLAYING) 337 { 338 update_enemy_positions(); 339 test_bullet_enemy_collisions(); 340 enemy_falling_speed += enemy_falling_accel; 341 } 342 343 vec2d mouse_pos = vec2d(mouse_x(), mouse_y()); 344 vec2d tank1_pos = vec2d(tank1._position_x, tank1._position_y); 345 vec2d tank2_pos = vec2d(tank2._position_x, tank2._position_y); 346 347 tank1._rotation = (mouse_pos-tank1_pos).GetAngle() + ALLEGRO_PI /2; 348 tank2._rotation = (mouse_pos-tank2_pos).GetAngle() + ALLEGRO_PI /2; 349 350 turret1.rotation = tank1._rotation; 351 turret1.position(tank1._position_x, tank1._position_y); 352 turret1.position(tank1._position_x, tank1._position_y); 353 sheild1.position(tank1._position_x, tank1._position_y); 354 355 turret2.rotation = tank2._rotation; 356 turret2.position(tank2._position_x, tank2._position_y); 357 turret2.position(tank2._position_x, tank2._position_y); 358 sheild2.position(tank2._position_x, tank2._position_y); 359 360 update_shield_animation(sheild1); 361 update_shield_animation(sheild2); 362 363 if (just_pressed(MOUSE_B1)) fire_bullet(tank1); 364 if (just_pressed(MOUSE_B2)) fire_bullet(tank2); 365 366 num_active = test_win_condition(); 367} 368 369 370 371void draw() 372{ 373 //draw("data/images/einstein.png", 50, 50); 374 375 object_manager.draw_all(); 376 377 font_manager.use_font("data/fonts/lacuna.ttf", -40); 378 print("Energy", 30, screen_h-100); 379 string energy_string = ""; 380 381 for (int i=0; i<tank_strength; i++) energy_string += "."; 382 383 font_manager.use_font("data/fonts/lacuna.ttf", -130); 384 print(energy_string, 30, screen_h-140); 385 386 387 //font_manager.destroy_text_render("data/fonts/lacuna.ttf", -130, tostring(num_active-1)); 388 font_manager.use_font("data/fonts/lacuna.ttf", -16); 389 print(tostring(num_active), 30, 30); 390 391 392 draw("data/images/crosshair.png", mouse_x(), mouse_y(), ALIGN_CENTER); 393 al_hide_mouse_cursor(); 394 395 draw("data/images/vignette2.png", 0, 0); 396} 397}

Quote:

Anyway, I didn't win, only tried a few times though. Ran smoothly, ran fine. The bursts were weird, and the game was difficult at spots where you'd have a bunch of dots bunched together but can only shoot 4 bullets (also, the bullets slowing down near their destination seemed really weird at first).

I agree. Game balance is pretty much non-existent in this demo. If anyone can beat it, I don't believe them, unless they can post a screenshot of the win screen ;)

Quote:

Probably too many dlls :P

Yea, I think half of them don't even get used. I wish I could dump them in a folder or something so the EXE is the only file in the root of the folder.

So from what I hear, no technical problems? Awesome! :D While making it, I noticed some slowdown when I went to about 80 enemies and 4 bullets on the screen. That's 320 separating-axis tests, so I limited the collisions tests to on-screen objects and it fixed it.

Quote:

What's the Einstein image in the data folder used for? ;D

Ah, just forgot to take it out.

BAF
Member #2,981
December 2002
avatar

The more I play it, the more I grow to hate your bullet acceleration/deceleration. It throws me off shooting thingies that are further away.

Dario ff
Member #10,065
August 2008
avatar

I Won!
{"name":"600042","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/2\/0\/20de9ddd1116732a8532b60ceb1d8917.jpg","w":791,"h":598,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/2\/0\/20de9ddd1116732a8532b60ceb1d8917"}600042

TranslatorHack 2010, a human translation chain in a.cc.
My games: [GiftCraft] - [Blocky Rhythm[SH2011]] - [Elven Revolution] - [Dune Smasher!]

Mark Oates
Member #1,146
March 2001
avatar

Here you go Baf, an EXE with linear bullet trajectory.

Nice dario. I haven't even beat it, yet.

Matthew Leverton
Supreme Loser
January 1999
avatar

Is the game for "Now Folks," or is it a direct address?

Mark Oates
Member #1,146
March 2001
avatar

Dario ff
Member #10,065
August 2008
avatar

Malinus said:

1. First attempt, with not even one that manged to get by my furious burst of fire.

I don't believe him. But how can he prove it? He could easily copy my screenshot. :'(

TranslatorHack 2010, a human translation chain in a.cc.
My games: [GiftCraft] - [Blocky Rhythm[SH2011]] - [Elven Revolution] - [Dune Smasher!]

Fishcake
Member #8,704
June 2007
avatar

The game runs without any problem for me. I couldn't win the game though.

blargmob
Member #8,356
February 2007
avatar

:o

Sorry Oates, but your lack for OOP makes me want to cry :'(

---
"No amount of prayer would have produced the computers you use to spread your nonsense." Arthur Kalliokoski

Matthew Leverton
Supreme Loser
January 1999
avatar

{"name":"600044","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/f\/b\/fb1bccf96ee6a62d14a47f2dff6269cd.png","w":791,"h":598,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/f\/b\/fb1bccf96ee6a62d14a47f2dff6269cd"}600044

I won too!

Trent Gamblin
Member #261
April 2000
avatar

I beat it twice in a row!!

{"name":"fb1bccf96ee6a62d14a47f2dff6269cd.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/f\/b\/fb1bccf96ee6a62d14a47f2dff6269cd.png","w":791,"h":598,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/f\/b\/fb1bccf96ee6a62d14a47f2dff6269cd"}fb1bccf96ee6a62d14a47f2dff6269cd.png

{"name":"fb1bccf96ee6a62d14a47f2dff6269cd.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/f\/b\/fb1bccf96ee6a62d14a47f2dff6269cd.png","w":791,"h":598,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/f\/b\/fb1bccf96ee6a62d14a47f2dff6269cd"}fb1bccf96ee6a62d14a47f2dff6269cd.png

Mark Oates
Member #1,146
March 2001
avatar

blargmob said:

your lack for OOP makes me want to cry

You'll be OK. ;) All the OOP is under the hood in this example.

Matthew, your kerning is a mess. :-/

Hey everybody, try the version with linear bullet trajectories. It's easier. I find the trick is to aim with the cursor and shoot below the bullets.

 1   2 


Go to: