Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » How can I draw multiple bitmaps to the backbuffer at the same time?

Credits go to Edgar Reynaldo for helping out!
This thread is locked; no one can reply to it. rss feed Print
How can I draw multiple bitmaps to the backbuffer at the same time?
Anatta
Member #16,686
June 2017

Hello everyone, ;D;D;D

I've just finished the Allegro 5 API Tutorials. I decide to write a simple snake game to strengthen what I've learnt.

But I hit a big wall just after I get start :-/:'(:-[:'(::):o I tried to draw 2 bitmaps to the backbuffer but after flipping the display, just only 1 bitmap (head) showed up. I went back to the tutorials but cannot find the way, then do a lot of searches but helpless.

#SelectExpand

Full code:

#SelectExpand
1// Compiled with C++14 // Using Allegro 5 API // 2////////////////////////////////////////////////////////////////////////// 3//---------------------------- libraries --------------------------------- 4#include "allegro5\allegro.h" 5#include "allegro5\allegro_native_dialog.h" 6#include <random> 7//---------------------------- constants --------------------------------- 8#define W 1218 9#define H 685 10#define FPS 61 11//---------------------------- global vars ------------------------------- 12ALLEGRO_TIMER* timer {nullptr}; 13ALLEGRO_EVENT_QUEUE* evque {nullptr}; 14ALLEGRO_DISPLAY* disp {nullptr}; 15bool redraw {false}; 16bool quit {false}; 17 // snake's head 18ALLEGRO_BITMAP* head {nullptr}; 19float heads {16}; 20float headx {W / 2 - heads / 2}; 21float heady {H / 2 - heads / 2}; 22float headd {4}; 23 // food 24ALLEGRO_BITMAP* food {nullptr}; 25float foods {16}; 26float foodx {W / 3 - foods / 3}; 27float foody {H / 3 - foods / 3}; 28 // control keys 29enum CTRL_KEYS {LEFT, UP, RIGHT, DOWN}; 30bool key[4] {{false}}; 31 // random miscs 32std::random_device rd; 33std::mt19937 gen(rd()); 34std::uniform_int_distribution<int> disx(0, W - 1); 35std::uniform_int_distribution<int> disy(0, H - 1); 36 // score 37int score {0}; 38//---------------------------- functions --------------------------------- 39int init_all(); 40void reg_all(); 41void setup_first_frame(); 42void game_loop(); 43void clean_up(); 44//============================ main ====================================== 45int main() { 46 if (init_all() < 0) { 47 return -1; 48 } 49 reg_all(); 50 setup_first_frame(); 51 game_loop(); 52 clean_up(); 53 return 0; 54} 55//======================================================================== 56int init_all() { 57 if (!al_init()) { 58 al_show_native_message_box(disp, "Error!", "Error:", 59 "Failed to initialize Allegro!", nullptr, 60 ALLEGRO_MESSAGEBOX_ERROR); 61 return -1; 62 } 63 timer = al_create_timer(0.99 / FPS); 64 if (!timer) { 65 al_show_native_message_box(disp, "Error!", "Error:", 66 "Failed to initialize timer!", nullptr, 67 ALLEGRO_MESSAGEBOX_ERROR); 68 return -1; 69 } 70 evque = al_create_event_queue(); 71 if (!evque) { 72 al_show_native_message_box(disp, "Error!", "Error:", 73 "Failed to initialize event queue!", nullptr, 74 ALLEGRO_MESSAGEBOX_ERROR); 75 al_destroy_timer(timer); 76 return -1; 77 } 78 disp = al_create_display(W, H); 79 if (!disp) { 80 al_show_native_message_box(disp, "Error!", "Error:", 81 "Failed to initialize display!", nullptr, 82 ALLEGRO_MESSAGEBOX_ERROR); 83 al_destroy_timer(timer); 84 al_destroy_event_queue(evque); 85 return -1; 86 } 87 head = al_create_bitmap(heads, heads); 88 if (!head) { 89 al_show_native_message_box(disp, "Error!", "Error:", 90 "Failed to initialize head bitmap!", nullptr, 91 ALLEGRO_MESSAGEBOX_ERROR); 92 al_destroy_timer(timer); 93 al_destroy_event_queue(evque); 94 al_destroy_display(disp); 95 return -1; 96 } 97 al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP); 98 food = al_create_bitmap(foods, foods); 99 if (!food) { 100 al_show_native_message_box(disp, "Error!", "Error:", 101 "Failed to initialize food bitmap!", nullptr, 102 ALLEGRO_MESSAGEBOX_ERROR); 103 al_destroy_timer(timer); 104 al_destroy_event_queue(evque); 105 al_destroy_display(disp); 106 al_destroy_bitmap(head); 107 return -1; 108 } 109 al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP); 110 if (!al_install_keyboard()) { 111 al_show_native_message_box(disp, "Error!", "Error:", 112 "Failed to initialize keyboard!", nullptr, 113 ALLEGRO_MESSAGEBOX_ERROR); 114 al_destroy_timer(timer); 115 al_destroy_event_queue(evque); 116 al_destroy_display(disp); 117 al_destroy_bitmap(head); 118 al_destroy_bitmap(food); 119 return -1; 120 } 121 return 0; 122} 123 124void reg_all() { 125 al_register_event_source(evque, al_get_timer_event_source(timer)); 126 al_register_event_source(evque, al_get_display_event_source(disp)); 127 al_register_event_source(evque, al_get_keyboard_event_source()); 128} 129 130void setup_first_frame() { 131 al_set_target_bitmap(head); 132 al_clear_to_color(al_map_rgb(255, 255, 255)); 133 al_set_target_bitmap(food); 134 al_clear_to_color(al_map_rgb(0, 255, 0)); 135 al_set_target_backbuffer(disp); 136 al_clear_to_color(al_map_rgb(0, 0, 0)); 137 al_flip_display(); 138} 139 140void game_loop() { 141 al_start_timer(timer); 142 while (!quit) { 143 ALLEGRO_EVENT ev; 144 al_wait_for_event(evque, &ev); 145 if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { 146 break; 147 } else if (ev.type == ALLEGRO_EVENT_KEY_DOWN) { 148 switch (ev.keyboard.keycode) { 149 case ALLEGRO_KEY_A: 150 case ALLEGRO_KEY_LEFT: 151 if (key[RIGHT]) { 152 key[LEFT] = false; 153 } else { 154 key[LEFT] = true; 155 } 156 key[UP] = false; 157 key[DOWN] = false; 158 break; 159 case ALLEGRO_KEY_W: 160 case ALLEGRO_KEY_UP: 161 if (key[DOWN]) { 162 key[UP] = false; 163 } else { 164 key[UP] = true; 165 } 166 key[LEFT] = false; 167 key[RIGHT] = false; 168 break; 169 case ALLEGRO_KEY_D: 170 case ALLEGRO_KEY_RIGHT: 171 if (key[LEFT]) { 172 key[RIGHT] = false; 173 } else { 174 key[RIGHT] = true; 175 } 176 key[UP] = false; 177 key[DOWN] = false; 178 break; 179 case ALLEGRO_KEY_S: 180 case ALLEGRO_KEY_DOWN: 181 if (key[UP]) { 182 key[DOWN] = false; 183 } else { 184 key[DOWN] = true; 185 } 186 key[LEFT] = false; 187 key[RIGHT] = false; 188 break; 189 default: 190 quit = true; 191 break; 192 } 193 } else if (ev.type == ALLEGRO_EVENT_TIMER) { 194 al_clear_to_color(al_map_rgb(0, 0, 0)); 195 if (key[LEFT] && headx >= headd) { 196 headx -= headd; 197 } else if (key[UP] && heady >= headd) { 198 heady -= headd; 199 } else if (key[RIGHT] && headx <= W - 1 - heads - headd) { 200 headx += headd; 201 } else if (key[DOWN] && heady <= H - 1 - heads - headd) { 202 heady += headd; 203 } 204 al_draw_bitmap(head, headx, heady, 0); 205 if ((headx + heads == foodx && heady == foody) || 206 (heady + heads == foody && headx == foodx) || 207 (headx - foods == foodx && heady == foody) || 208 (heady - foods == foody && headx == foodx)) { 209 ++score; 210 foodx = disx(gen); 211 foody = disx(gen); 212 al_draw_bitmap(food, foodx, foody, 0); 213 } 214 redraw = true; 215 } 216 if (redraw && al_is_event_queue_empty(evque)) { 217 al_flip_display(); 218 redraw = false; 219 } 220 } 221} 222 223void clean_up() { 224 al_destroy_timer(timer); 225 al_destroy_event_queue(evque); 226 al_destroy_display(disp); 227 al_destroy_bitmap(head); 228 al_destroy_bitmap(food); 229}

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

You're mixing drawing and logic. Learn to break that habit and separate the two and you'll be much better off.

Anatta said:

#SelectExpand
1/// LOGIC GOES HERE 2 } else if (ev.type == ALLEGRO_EVENT_TIMER) { 3 al_clear_to_color(al_map_rgb(0, 0, 0)); 4 if (key[LEFT] && headx >= headd) { 5 headx -= headd; 6 } else if (key[UP] && heady >= headd) { 7 heady -= headd; 8 } else if (key[RIGHT] && headx <= W - 1 - heads - headd) { 9 headx += headd; 10 } else if (key[DOWN] && heady <= H - 1 - heads - headd) { 11 heady += headd; 12 } 13 /// you're drawing inside logic
14 al_draw_bitmap(head, headx, heady, 0);
15 if ((headx + heads == foodx && heady == foody) || 16 (heady + heads == foody && headx == foodx) || 17 (headx - foods == foodx && heady == foody) || 18 (heady - foods == foody && headx == foodx)) { 19 ++score; 20 foodx = disx(gen); 21 foody = disx(gen); 22 /// you're drawing inside logic
23 al_draw_bitmap(food, foodx, foody, 0);
24 } 25 redraw = true; 26 } 27/// DRAWING GOES HERE 28 if (redraw && al_is_event_queue_empty(evque)) { 29 al_flip_display(); 30 redraw = false; 31 }

Anatta
Member #16,686
June 2017

Hi! Thank you for the advice. I've just fixed it.

#SelectExpand
1 } else if (ev.type == ALLEGRO_EVENT_TIMER) { 2 if (key[LEFT] && headx >= headd) { 3 headx -= headd; 4 } else if (key[UP] && heady >= headd) { 5 heady -= headd; 6 } else if (key[RIGHT] && headx <= W - 1 - heads - headd) { 7 headx += headd; 8 } else if (key[DOWN] && heady <= H - 1 - heads - headd) { 9 heady += headd; 10 } 11 if ((headx + heads == foodx && heady == foody) || 12 (heady + heads == foody && headx == foodx) || 13 (headx - foods == foodx && heady == foody) || 14 (heady - foods == foody && headx == foodx)) { 15 ++score; 16 foodx = disx(gen); 17 foody = disx(gen); 18 food_eaten = true; 19 } 20 redraw = true; 21 } 22 // draw 23 if (redraw && al_is_event_queue_empty(evque)) { 24 al_clear_to_color(al_map_rgb(0, 0, 0)); 25 al_draw_bitmap(head, headx, heady, 0); 26 if (food_eaten) { 27 al_draw_bitmap(food, foodx, foody, 0); 28 food_eaten = false; 29 } 30 al_flip_display(); 31 redraw = false; 32 }

But still haven't figured out how to draw 2 bitmaps at same time to backbuffer :'(

#SelectExpand
1// after this function I only see head bitmap on the black screen. 2void setup_first_frame() { 3 al_set_target_bitmap(head); 4 al_clear_to_color(al_map_rgb(255, 255, 255)); 5 6 al_set_target_bitmap(food); 7 al_clear_to_color(al_map_rgb(0, 255, 0)); 8 9 al_set_target_backbuffer(disp); 10 al_clear_to_color(al_map_rgb(0, 0, 0)); 11 12 al_flip_display(); 13}

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Anatta
Member #16,686
June 2017

Thank you I've figured out.

#SelectExpand
1 } else if (ev.type == ALLEGRO_EVENT_TIMER) { 2 if (key[LEFT] && headx >= headd) { 3 headx -= headd; 4 } else if (key[UP] && heady >= headd) { 5 heady -= headd; 6 } else if (key[RIGHT] && headx <= W - 1 - heads - headd) { 7 headx += headd; 8 } else if (key[DOWN] && heady <= H - 1 - heads - headd) { 9 heady += headd; 10 } 11 if (is_collide_head_food()) { 12 ++score; 13 foodx = disx(gen); 14 foody = disy(gen); 15 } 16 redraw = true; 17 } 18 if (redraw && al_is_event_queue_empty(evque)) { 19 al_clear_to_color(al_map_rgb(0, 0, 0)); 20 al_draw_bitmap(head, headx, heady, 0); 21 al_draw_bitmap(food, foodx, foody, 0); 22 al_flip_display(); 23 redraw = false; 24 }

Go to: