My first game! (pong)
Havacore

I just got into allegro this week and by the looks of it, allegro 5 is brand new and so their are very few tutorials for it (at least as far as what I can find). After going through the few tutorials on the allegro.cc wiki, I decided to say to heck with it and try to make pong, and I've actually gone quite a bit further than I thought I would.

Now here is the problem, I've managed to get 3 bitmaps: 2 paddles and a bouncer.

I got the two paddles mapped to the keyboard so I can move them up and down, and the bouncer is happily bouncing around all over the place. Now I'm trying to make the bouncer bounce off the paddles. I've included my code, the logic for the bouncing starts at line 132.

I've got the bouncer bouncing at the same x-coordinate as the paddles, which means it bounces even when it's not hitting the paddle, no good!

BTW, I'm new to the forum, so let me know if this isn't the place to post this, since it's kind of a coding question along with a concept one.

J-Gamer

Make line 141:
if((bouncer_x <= left_paddle_x + paddle_width / 2.0 + bouncer_size/2.0 && bouncer_y >= left_paddle_y - bouncer_size/2.0 && bouncer_y <= left_paddle_y + paddle_height - bouncer_width/2.0) || (bouncer_x >= right_paddle_x - (paddle_width / 2.0)) - bouncer_size/2.0 && bouncer_y >= right_paddle_y - bouncer_size/2.0 && bouncer_y <= right_paddle_y + paddle_height - bouncer_width/2.0))
You also want to check if it's y value is in the boundaries of the paddle.

Havacore

Great! The bouncer is now bouncing off the paddles!

Now as far as changes go from allegro4 to 5, should I be able to figure out the rest of what I need from reading examples from allegro 4 for things like, a scoreboard, restarting the board when the bouncer hits the edge of the screen, a title screen etc?

Thanks for the help btw!

Mark Oates
Quote:

My first game!

Yay! :D

Rather than create bitmaps for the paddles and fill them with color, you could just draw them with primitives instead. Bust out some rounded rectangles, add a little shine-shine! 8-)

{"name":"603455","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/1\/a\/1a49b8bc2a314928768582ec86377c39.png","w":672,"h":530,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/1\/a\/1a49b8bc2a314928768582ec86377c39"}603455

I made some examples:

#SelectExpand
1void draw_paddle(float x, float y) 2{ 3 // fill 4 al_draw_filled_rounded_rectangle(x, y, 5 x+paddle_width, y+paddle_height, 6, 6, al_color_html("729fcf")); 6 // outline 7 al_draw_rounded_rectangle(x, y, 8 x+paddle_width, y+paddle_height, 6, 6, al_color_html("b5edff"), 1.0); 9 // shine 10 al_draw_filled_rounded_rectangle(x, y, 11 x+paddle_width/2, y+paddle_height-10, 6, 6, al_color_html("8abbef")); 12} 13 14void draw_ball(float x, float y) 15{ 16 // fill 17 al_draw_filled_circle(x, y, bouncer_size, al_color_html("6be97d")); 18 // shadow 19 al_draw_filled_circle(x+bouncer_size/4, y+bouncer_size/4, 20 bouncer_size/3*2, al_color_html("59ce76")); 21 // shine 22 al_draw_filled_circle(x-bouncer_size/3, y-bouncer_size/3, 23 bouncer_size/4, al_color_html("9bffaa")); 24}

I used

#include <allegro5/allegro_primitives.h>
#include <allegro5/allegro_color.h>

and don't forget to call al_init_primitives_addon().

Also, I used

al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST);
al_set_new_display_option(ALLEGRO_SAMPLES, 4, ALLEGRO_SUGGEST);

before setting up the display to make the lines draw smoothly.

Havacore

Ok I can't for the life of me figure out how you did that. I've never used primitives before, and all I have to work off of is the allegro5 manual. Do you still draw a bitmap and then draw the primitive on top of it?

It makes sense to me to put the draw_paddle function in another file to avoid clutter but does that mean that I should put the al_init_primitives_addon() in both .cc files?

Basically, how do I go about implementing those primitives into my code? Do I just add the draw_paddle function at the end of the main loop where I draw the bitmaps?

Mark Oates

I'll do a step by step from your original code attachment. :)

1.

First, I added

#include <allegro5/allegro_primitives.h>
#include <allegro5/allegro_color.h>

just below your #include <allegro5/allegro.h>. All allegro_color does is gives me the function al_color_html(). You could just as easily take this out and use al_map_rgba_f() or other similar function for your colors.

2.

Those two functions I made, draw_paddle(float x, float y) and draw_ball(float x, float y) (same as they are in the last post), I placed them just before main. This is also below your constants and enums. Usually my code structure works out like this:

# includes
# contants and other definitions
# functions
# main

3.

before you create the display, (eg. before display = al_create_display(SCREEN_W, SCREEN_H);, I added three lines

and

al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST);
al_set_new_display_option(ALLEGRO_SAMPLES, 4, ALLEGRO_SUGGEST);

al_init_primitives_addon(); can go anywhere after al_init(), and it's best to keep it with the rest of your init()s if you have more.

4.

Then, way down where you have

  al_draw_bitmap(right_paddle, right_paddle_x, right_paddle_y, 0);
  al_draw_bitmap(left_paddle, left_paddle_x, left_paddle_y, 0);
  al_draw_bitmap(bouncer, bouncer_x, bouncer_y, 0);

I commented those out and put in:

  //al_draw_bitmap(right_paddle, right_paddle_x, right_paddle_y, 0);
  //al_draw_bitmap(left_paddle, left_paddle_x, left_paddle_y, 0);
  //al_draw_bitmap(bouncer, bouncer_x, bouncer_y, 0);
  draw_paddle(right_paddle_x, right_paddle_y);
  draw_paddle(left_paddle_x, left_paddle_y);
  draw_ball(bouncer_x, bouncer_y);

5.

Profit!

#SelectExpand
1#include <stdio.h> 2#include <allegro5/allegro.h> 3#include <allegro5/allegro_primitives.h> 4#include <allegro5/allegro_color.h> 5 6 7 8/* constants and definitions */ 9 10const int SCREEN_W = 640; 11const int SCREEN_H = 480; 12const float FPS = 60; 13const int paddle_height = 96; 14const int paddle_width = 16; 15const int bouncer_size = 16; 16 17enum MYKEYS { 18 KEY_UP, KEY_DOWN, KEY_W, KEY_S 19}; 20 21 22/* functions */ 23 24void draw_paddle(float x, float y) 25{ 26 // fill 27 al_draw_filled_rounded_rectangle(x, y, 28 x+paddle_width, y+paddle_height, 3, 3, al_color_html("729fcf")); 29 // outline 30 al_draw_rounded_rectangle(x, y, 31 x+paddle_width, y+paddle_height, 3, 3, al_color_html("b5edff"), 1.0); 32 // shine 33 al_draw_filled_rounded_rectangle(x, y, 34 x+paddle_width/2, y+paddle_height-10, 3, 3, al_color_html("8abbef")); 35} 36 37void draw_ball(float x, float y) 38{ 39 // fill 40 al_draw_filled_circle(x, y, bouncer_size, al_color_html("6be97d")); 41 // shadow 42 al_draw_filled_circle(x+bouncer_size/4, y+bouncer_size/4, bouncer_size/3*2, al_color_html("59ce76")); 43 // shine 44 al_draw_filled_circle(x-bouncer_size/3, y-bouncer_size/3, bouncer_size/4, al_color_html("9bffaa")); 45} 46 47 48 49 50int main(int argc, char **argv) 51{ 52 ALLEGRO_DISPLAY *display = NULL; 53 ALLEGRO_EVENT_QUEUE *event_queue = NULL; 54 ALLEGRO_TIMER *timer = NULL; 55 ALLEGRO_BITMAP *right_paddle = NULL; 56 ALLEGRO_BITMAP *left_paddle = NULL; 57 ALLEGRO_BITMAP *bouncer = NULL; 58 59 float right_paddle_x = (SCREEN_W * 4/5) - (paddle_width / 2.0); 60 float right_paddle_y = (SCREEN_H / 2.0) - (paddle_height / 2.0); 61 62 float left_paddle_x = (SCREEN_W * 1/5) - (paddle_width / 2.0); 63 float left_paddle_y = (SCREEN_H / 2.0) - (paddle_height / 2.0); 64 65 float bouncer_x = SCREEN_W / 2.0 - bouncer_size / 2.0; 66 float bouncer_y = SCREEN_H / 2.0 - bouncer_size / 2.0; 67 float bouncer_dx = 4.0, bouncer_dy = -4.0; 68 69 bool key[4] = {false, false, false, false }; 70 bool redraw = true; 71 bool doexit = false; 72 73 if(!al_init()) { 74 fprintf(stderr, "failed to initialized allegro\n"); 75 return -1; 76 } 77 78 if(!al_install_keyboard()) { 79 fprintf(stderr, "failed to install keyboard\n"); 80 return -1; 81 } 82 83 84 al_init_primitives_addon(); 85 86 al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST); 87 al_set_new_display_option(ALLEGRO_SAMPLES, 4, ALLEGRO_SUGGEST); 88 89 90 //initialize display (w, h) 91 display = al_create_display(SCREEN_W, SCREEN_H); 92 if(!display) { 93 fprintf(stderr, "failed to create display\n"); 94 return -1; 95 } 96 97 timer = al_create_timer(1.0/FPS); 98 if(!timer) { 99 fprintf(stderr, "failed to create timer\n"); 100 return -1; 101 } 102 103 right_paddle = al_create_bitmap(paddle_width, paddle_height); 104 if(!right_paddle) { 105 fprintf(stderr, "failed to create right paddle bitmap\n"); 106 return -1; 107 } 108 109 left_paddle = al_create_bitmap(paddle_width, paddle_height); 110 if(!left_paddle) { 111 fprintf(stderr, "failed to create left paddle bitmap\n"); 112 return -1; 113 } 114 bouncer = al_create_bitmap(bouncer_size, bouncer_size); 115 if(!bouncer) { 116 fprintf(stderr, "failed to create bouncer bitmap\n"); 117 return -1; 118 } 119 120 al_set_target_bitmap(left_paddle); 121 al_clear_to_color(al_map_rgb (0,255,0)); 122 123 al_set_target_bitmap(right_paddle); 124 al_clear_to_color(al_map_rgb (0,255,0)); 125 126 al_set_target_bitmap(bouncer); 127 al_clear_to_color(al_map_rgb (0,0,255)); 128 129 al_set_target_bitmap(al_get_backbuffer(display)); 130 131 event_queue = al_create_event_queue(); 132 if(!event_queue) { 133 fprintf(stderr, "failed to create event queue\n"); 134 return -1; 135 } 136 137 al_register_event_source(event_queue, al_get_display_event_source(display)); 138 139 al_register_event_source(event_queue, al_get_timer_event_source(timer)); 140 141 al_register_event_source(event_queue, al_get_keyboard_event_source()); 142 143 al_clear_to_color(al_map_rgb(0, 0, 0)); 144 145 al_flip_display(); 146 147 al_start_timer(timer); 148 149 while(!doexit) 150 { 151 ALLEGRO_EVENT ev; 152 153 al_wait_for_event(event_queue, &ev); 154 155 if(ev.type == ALLEGRO_EVENT_TIMER) { 156 157 //logic for moving the paddles on input 158 if(key[KEY_UP] && right_paddle_y >= 4.0) { 159 right_paddle_y -= 4.0; 160 } 161 162 if(key[KEY_DOWN] && right_paddle_y <= SCREEN_H - paddle_height - 4.0){ 163 right_paddle_y += 4.0; 164 } 165 166 if(key[KEY_W] && left_paddle_y >= 4.0) { 167 left_paddle_y -= 4.0; 168 } 169 170 if(key[KEY_S] && left_paddle_y <= SCREEN_H - paddle_height - 4.0){ 171 left_paddle_y += 4.0; 172 } 173 174 //logic for the bouncer 175 if(bouncer_x < 0 || bouncer_x > SCREEN_W - bouncer_size) { 176 bouncer_dx = -bouncer_dx; 177 } 178 179 if(bouncer_y < 0 || bouncer_y > SCREEN_H - bouncer_size) { 180 bouncer_dy = -bouncer_dy; 181 } 182 183 if(bouncer_x == left_paddle_x + (paddle_width / 2.0) || bouncer_x == right_paddle_x - (paddle_width / 2.0)) { 184 bouncer_dx = -bouncer_dx; 185 } 186 187 188 bouncer_x += bouncer_dx; 189 bouncer_y += bouncer_dy; 190 191 redraw = true; 192 } 193 194 else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { 195 break; 196 } 197 198 else if(ev.type == ALLEGRO_EVENT_KEY_DOWN) { 199 switch(ev.keyboard.keycode) { 200 case ALLEGRO_KEY_UP: 201 key[KEY_UP] = true; 202 break; 203 204 case ALLEGRO_KEY_DOWN: 205 key[KEY_DOWN] = true; 206 break; 207 208 case ALLEGRO_KEY_W: 209 key[KEY_W] = true; 210 break; 211 212 case ALLEGRO_KEY_S: 213 key[KEY_S] = true; 214 break; 215 } 216 } 217 218 else if(ev.type == ALLEGRO_EVENT_KEY_UP) { 219 switch(ev.keyboard.keycode) { 220 case ALLEGRO_KEY_UP: 221 key[KEY_UP] = false; 222 break; 223 224 case ALLEGRO_KEY_DOWN: 225 key[KEY_DOWN] = false; 226 break; 227 228 case ALLEGRO_KEY_W: 229 key[KEY_W] = false; 230 break; 231 232 case ALLEGRO_KEY_S: 233 key[KEY_S] = false; 234 break; 235 236 case ALLEGRO_KEY_ESCAPE: 237 doexit = true; 238 break; 239 } 240 } 241 242 if(redraw && al_is_event_queue_empty(event_queue)) { 243 redraw = false; 244 245 al_clear_to_color(al_map_rgb(0,0,0)); 246 247 draw_paddle(right_paddle_x, right_paddle_y); 248 draw_paddle(left_paddle_x, left_paddle_y); 249 draw_ball(bouncer_x, bouncer_y); 250 251 //al_draw_bitmap(right_paddle, right_paddle_x, right_paddle_y, 0); 252 //al_draw_bitmap(left_paddle, left_paddle_x, left_paddle_y, 0); 253 //al_draw_bitmap(bouncer, bouncer_x, bouncer_y, 0); 254 255 al_flip_display(); 256 } 257 } 258 259 al_destroy_bitmap(bouncer); 260 al_destroy_bitmap(right_paddle); 261 al_destroy_bitmap(left_paddle); 262 al_destroy_timer(timer); 263 al_destroy_display(display); 264 al_destroy_event_queue(event_queue); 265 266 return 0; 267}

Havacore said:

Do you still draw a bitmap and then draw the primitive on top of it?

Nope. Primitives draw themselves. Of course, you're drawing the primitives to the display, which technically is a bitmap. But you don't need to have any extra surfaces to render primitives.

Quote:

It makes sense to me to put the draw_paddle function in another file to avoid clutter but does that mean that I should put the al_init_primitives_addon() in both .cc files?

al_init_primitives_addon() is like al_init(). You only need to call it once when you setup your program and you're good to go.

Quote:

Do I just add the draw_paddle function at the end of the main loop where I draw the bitmaps?

Yeaup. 8-)

Havacore

:D Thanks for the help!!!

Now I'm trying to figure out how to add font so that I can add in a scoreboard. I took a look at the code in the allegro wiki on how to do fonts, but I can't seem to compile it properly. Here is the error

jason@Wally:~/Documents/game dev/allegro wiki lessons/lesson 6$ gcc lesson6fonts.cc -o lesson $(pkg-config --libs allegro-5.0 allegro_font-5.0 allegro_ttf-5.0)
jason@Wally:~/Documents/game dev/allegro wiki lessons/lesson 6$ ./lesson
lesson: /home/jason/Documents/games/allegro-5.0/addons/font/text.c:73: al_draw_ustr: Assertion `font' failed.
Aborted
jason@Wally:~/Documents/game dev/allegro wiki lessons/lesson 6$

Looking at this terminal panic, it's looking for the fonts config in a folder called jason/Documents/games, which doesn't exist. My allegro folder is in Documents/game dev/allegro-5.0/etc...

Michael Faerber

Do you mean that page?

Anyway, it seems that the compilation is not the problem, but loading the font is. Have you tried putting the font file into the directory where you call your program from? This would most probably be the directory where you have your executable.

Havacore

Just tried that, but it didn't work :-[

Neil Roy

Which front end/compiler are you using? CodeBlocks likes to create a bin folder for your executable, but keep the root folder for your project by default.

Also, what is the code you're using to try and initialize the font?

Havacore

I'm using gcc

The code that I'm using is from the allegro wiki

Just trying to get that code to work so that I can implement it into my game

Thread #606480. Printed from Allegro.cc