Allegro.cc - Online Community
Post Reply

Allegro.cc Forums » Programming Questions » Vivace extra points. Its there a better way of doing this one.

rss feed Print
Vivace extra points. Its there a better way of doing this one.
AceBlkwell
Member #13,038
July 2011
avatar

I am working through the Vivace tutorial. I am at the point of animation, or moving things around the screen. At the end of the lesson it states extra points for preventing the randomly bouncing objects from drifting off screen.
I manage to get it to work but thanks to the circle and inverted (up ramped) line I ended up with code addressing things individually instead of a system group approach. Maybe this is good as it gets but I thought I'd ask if others had a better approach I didn't consider. Any input would be appreciated.
I tried to comment the sections I added or altered. Thanks.

#SelectExpand
1#include <stdio.h> 2#include <stdlib.h> 3#include <allegro5/allegro5.h> 4#include <allegro5/allegro_font.h> 5#include <allegro5/allegro_image.h> 6#include <allegro5/allegro_primitives.h> 7 8void must_init(bool test, const char *description) 9{ 10 if(test) return; 11 12 printf("couldn't initialize %s\n", description); 13 exit(1); 14} 15 16enum BOUNCER_TYPE { 17 BT_HELLO = 0, 18 BT_MYSHA, 19 BT_TRIANGLE, 20 BT_RECTANGLE_1, 21 BT_RECTANGLE_2, 22 BT_CIRCLE, 23 BT_LINE1, 24 BT_LINE2, 25 BT_N 26}; 27 28typedef struct BOUNCER 29{ 30 float x, y; 31 float dx, dy; 32 float sx, sy; // Lower right corner of object square 33 int type; 34} BOUNCER; 35 36int main() 37{ 38 float limit_x; //Offset limits to prevent going off screen 39 float limit_y; 40 41 must_init(al_init(), "allegro"); 42 must_init(al_install_keyboard(), "keyboard"); 43 44 ALLEGRO_TIMER* timer = al_create_timer(1.0 / 30.0); 45 must_init(timer, "timer"); 46 47 ALLEGRO_EVENT_QUEUE* queue = al_create_event_queue(); 48 must_init(queue, "queue"); 49 50 al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST); 51 al_set_new_display_option(ALLEGRO_SAMPLES, 8, ALLEGRO_SUGGEST); 52 al_set_new_bitmap_flags(ALLEGRO_MIN_LINEAR | ALLEGRO_MAG_LINEAR); 53 54 ALLEGRO_DISPLAY* disp = al_create_display(640, 480); 55 must_init(disp, "display"); 56 57 ALLEGRO_FONT* font = al_create_builtin_font(); 58 must_init(font, "font"); 59 60 must_init(al_init_image_addon(), "image addon"); 61 ALLEGRO_BITMAP* mysha = al_load_bitmap("mysha.png"); 62 must_init(mysha, "mysha"); 63 64 must_init(al_init_primitives_addon(), "primitives"); 65 66 al_register_event_source(queue, al_get_keyboard_event_source()); 67 al_register_event_source(queue, al_get_display_event_source(disp)); 68 al_register_event_source(queue, al_get_timer_event_source(timer)); 69 70 bool done = false; 71 bool redraw = true; 72 ALLEGRO_EVENT event; 73 74 BOUNCER obj[BT_N]; 75 76 obj[0].sx = 100; obj[0].sy = 10; // used with X and Y, SX and SY create a square to encompass the shapes 77 obj[1].sx = 318; obj[1].sy = 200; // took them from the draw commands below 78 obj[2].sx = 50; obj[2].sy = 50; 79 obj[3].sx = 100; obj[3].sy = 80; 80 obj[4].sx = 120; obj[4].sy = 100; 81 obj[5].sx = 30; obj[5].sy = 30; 82 obj[6].sx = 20; obj[6].sy = 100; 83 obj[7].sx = 70; obj[7].sy = 0; 84 85 for(int i = 0; i < BT_N; i++) 86 { 87 BOUNCER* b = &obj[i]; 88 b->x = rand() % 320; // Changed from 640x480, Once outer limits were established I had to prevent the first draw to be out of bounds. It would lock the 89 b->y = rand() % 250; // the shape in the out of bound condition. Used the largest shape for the difference. (Mysha = 320x200) 90 b->dx = ((((float)rand()) / RAND_MAX) - 0.5) * 2 * 4; 91 b->dy = ((((float)rand()) / RAND_MAX) - 0.5) * 2 * 4; 92 b->type = i; 93 } 94 95 al_start_timer(timer); 96 while(1) 97 { 98 al_wait_for_event(queue, &event); 99 100 switch(event.type) 101 { 102 case ALLEGRO_EVENT_TIMER: 103 for(int i = 0; i < BT_N; i++) 104 { 105 BOUNCER* b = &obj[i]; 106 b->x += b->dx; 107 b->y += b->dy; 108 109 limit_x = 640-b->sx; // Limit isn't 640x480. limit x and y takes in consideration the lower square point of the shape. 110 limit_y = 480-b->sy; 111 112 if(i==5 && b->x < 30) //Created for Circle to prevent X and Y from going below the R30 113 { 114 b->dx *= -1; 115 } 116 if(i==5 && b->y < 30) //Created for Circle to prevent X and Y from going below the R30 117 { 118 b->dy *= -1; 119 } 120 if(i==7 && b->y < 20) //Created for Line 2 prevent Y from getting in less than 20 which is the second point location (-20) 121 { 122 b->dy *= -1; 123 } 124 if(b->x < 0) 125 { 126 b->x *= -1; 127 b->dx *= -1; 128 } 129 130 if(b->x > limit_x) 131 { 132 b->dx *= -1; 133 } 134 if(b->y < 0) 135 { 136 b->y *= -1; 137 b->dy *= -1; 138 } 139 if(b->y > limit_y) 140 { 141 142 b->dy *= -1; 143 } 144 } 145 146 redraw = true; 147 break; 148 149 case ALLEGRO_EVENT_KEY_DOWN: 150 case ALLEGRO_EVENT_DISPLAY_CLOSE: 151 done = true; 152 break; 153 } 154 155 if(done) 156 break; 157 158 if(redraw && al_is_event_queue_empty(queue)) 159 { 160 ALLEGRO_VERTEX v[4]; 161 al_clear_to_color(al_map_rgb(0, 0, 0)); 162 163 for(int i = 0; i < BT_N; i++) 164 { 165 BOUNCER* b = &obj[i]; 166 switch(b->type) 167 { 168 case BT_HELLO: 169 al_draw_text(font, al_map_rgb(255, 255, 255), b->x, b->y, 0, "Hello world!"); 170 break; 171 172 case BT_MYSHA: 173 al_draw_bitmap(mysha, b->x, b->y, 0); 174 break; 175 176 case BT_TRIANGLE: 177 al_draw_filled_triangle(b->x, b->y, b->x + 50, b->y + 25, b->x, b->y + 50, al_map_rgb_f(0, 1, 0)); 178 break; 179 180 case BT_RECTANGLE_1: 181 al_draw_filled_rectangle(b->x, b->y, b->x + 100, b->y + 80, al_map_rgba_f(0, 0, 0.5, 0.5)); 182 break; 183 184 case BT_RECTANGLE_2: 185 v[0].x = b->x; v[0].y = b->y; v[0].z = 0; v[0].color = al_map_rgb_f(1, 0, 0); 186 v[1].x = b->x + 120; v[1].y = b->y; v[1].z = 0; v[1].color = al_map_rgb_f(0, 1, 0); 187 v[2].x = b->x; v[2].y = b->y + 100; v[2].z = 0; v[2].color = al_map_rgb_f(0, 0, 1); 188 v[3].x = b->x + 120; v[3].y = b->y + 100; v[3].z = 0; v[3].color = al_map_rgb_f(1, 1, 0); 189 190 al_draw_prim(v, NULL, NULL, 0, 4, ALLEGRO_PRIM_TRIANGLE_STRIP); 191 break; 192 193 case BT_CIRCLE: 194 al_draw_circle(b->x, b->y, 30, al_map_rgb_f(1, 0, 1), 2); 195 break; 196 197 case BT_LINE1: 198 al_draw_line(b->x, b->y, b->x + 20, b->y + 100, al_map_rgb_f(1, 0, 0), 1); 199 break; 200 201 case BT_LINE2: 202 al_draw_line(b->x, b->y, b->x + 70, b->y - 20, al_map_rgb_f(1, 1, 0), 1); 203 break; 204 } 205 } 206 207 al_flip_display(); 208 redraw = false; 209 } 210 } 211 212 al_destroy_bitmap(mysha); 213 al_destroy_font(font); 214 al_destroy_display(disp); 215 al_destroy_timer(timer); 216 al_destroy_event_queue(queue); 217 218 return 0; 219}

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Since you're using objects, you can try OOP.

Give Each object a GetLeft, SetLeft, GetRight, SetRight, GetTop, SetTop, GetBottom, and SetBottom function. Now you can easily constrain any object to the boundaries of the screen.

AceBlkwell
Member #13,038
July 2011
avatar

Sounds good. I was thinking there was a more systemic way than using a line by line deviation. Thanks.

Post Reply
Go to: