Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [A5] A question regarding set_target_bitmap and clear_to_color

This thread is locked; no one can reply to it. rss feed Print
[A5] A question regarding set_target_bitmap and clear_to_color
Ninjarobot
Member #12,640
March 2011

Hello!

I will begin with some quick facts to help you understand my problem. For now I am trying to make a circle, used as a crosshair on the game screen and when I press Space the game will "drop sand"(basically paint the place the crosshair aims with a sandy colour).

I would like to add that I am a beginner with Allegro so it's all Greek to me(well not really as I am Greek myself...). I am suspecting that I'm doing something insanely stupid but after 2 days of trying to figure it out I decided to give up and seek answers because Allegro5 is fairly new and there aren't many tutorials about it.
Since I am a beginner I used an Allegro5 "Pong" code and started editing stuff around. Felt much easier than coding everything from scratch and I actually learned something from it. I did read Allegro5 tutorials about Bitmaps and Display though.

What my problem is:
Basically I have a very simple goal. The cursor needs to be redrawn but the sand that the cursor drops shouldn't. I would like to add that I kept the ball code of "Pong" for experimental reasons so the ball needs to be redrawn too. However while playing around with the code I was juggling around:
A) Nothing showing up(cursor and ball was invisible)but pressing Space actually proved that everything was there as I could paint sand on screen normally.
B) Ball and Cursor not getting redrawn properly, they were drawn but not deleted so there is an endless trail for both when they move. "Sand" works normally here.

From what I understood to redraw something you have to use al_set_target_bitmap to select it, then use al_clear_to_color to "wipe" it and then proceed to redraw it. This is why I select both the ball and the cursor individually, clear them and then select the backbuffer and draw them again. This however is causing the problem of B case. What am I doing wrong?

Thanks in advance

PS. I am aware some of my code is not needed. It is legacy code from Pong I didn't delete either because it wasn't needed yet or because I am planning to use/fix in the future, however any tips are welcome of course!

#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; 16const int cursor_size=18; 17 18enum MYKEYS { 19 KEY_UP, KEY_DOWN, KEY_W, KEY_S,KEY_A,KEY_D,KEY_SPACE,KEY_P 20}; 21 22/* functions */ 23 24void draw_cursor(float x,float y) 25{ 26 al_draw_circle(x , y, cursor_size, al_color_html("ff0000"), 2.0); 27} 28 29void drop_sand(float x,float y) 30{ 31 al_draw_filled_circle( x, y, cursor_size-3, al_color_html("ffcc66")); 32} 33 34 35 36void draw_ball(float x, float y) 37{ 38 // fill 39 al_draw_filled_circle(x, y, bouncer_size, al_color_html("6be97d")); 40 // shadow 41 al_draw_filled_circle(x+bouncer_size/4, y+bouncer_size/4, bouncer_size/3*2, al_color_html("59ce76")); 42 // shine 43 al_draw_filled_circle(x-bouncer_size/3, y-bouncer_size/3, bouncer_size/4, al_color_html("9bffaa")); 44} 45 46 47 48 49int main(int argc, char **argv) 50{ 51 ALLEGRO_DISPLAY *display = NULL; 52 ALLEGRO_EVENT_QUEUE *event_queue = NULL; 53 ALLEGRO_TIMER *timer = NULL; 54 ALLEGRO_BITMAP *sand = NULL; 55 ALLEGRO_BITMAP *bouncer = NULL; 56 ALLEGRO_BITMAP *cursor= NULL; 57 58 59 60 float bouncer_x = SCREEN_W / 2.0 - bouncer_size / 2.0; 61 float bouncer_y = SCREEN_H / 2.0 - bouncer_size / 2.0; 62 float bouncer_dx = 4.0, bouncer_dy = -4.0; 63 64 float cursor_x=(SCREEN_W / 2.0); 65 float cursor_y=(SCREEN_H / 2.0); 66 67 bool key[8] = {false, false, false, false, false, false, false, false}; 68 bool redraw = true; 69 bool doexit = false; 70 71 if(!al_init()) { 72 fprintf(stderr, "failed to initialized allegro\n"); 73 return -1; 74 } 75 76 if(!al_install_keyboard()) { 77 fprintf(stderr, "failed to install keyboard\n"); 78 return -1; 79 } 80 81 82 al_init_primitives_addon(); 83 84 al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST); 85 al_set_new_display_option(ALLEGRO_SAMPLES, 4, ALLEGRO_SUGGEST); 86 87 88 //initialize display (w, h) 89 display = al_create_display(SCREEN_W, SCREEN_H); 90 if(!display) { 91 fprintf(stderr, "failed to create display\n"); 92 return -1; 93 } 94 95 timer = al_create_timer(1.0/FPS); 96 if(!timer) { 97 fprintf(stderr, "failed to create timer\n"); 98 return -1; 99 } 100 101 draw_cursor(300,200); 102 103 104 105 cursor = al_create_bitmap(cursor_size,cursor_size); 106 sand = al_create_bitmap(cursor_size-3,cursor_size-3); 107 bouncer = al_create_bitmap(bouncer_size, bouncer_size); 108 if(!bouncer) { 109 fprintf(stderr, "failed to create bouncer bitmap\n"); 110 return -1; 111 } 112 113 114 115 al_set_target_bitmap(bouncer); 116 al_clear_to_color(al_map_rgb (0,0,0)); 117 al_set_target_bitmap(cursor); 118 al_clear_to_color(al_map_rgb (0,0,0)); 119 120 al_set_target_bitmap(al_get_backbuffer(display)); 121 122 event_queue = al_create_event_queue(); 123 if(!event_queue) { 124 fprintf(stderr, "failed to create event queue\n"); 125 return -1; 126 } 127 128 al_register_event_source(event_queue, al_get_display_event_source(display)); 129 130 al_register_event_source(event_queue, al_get_timer_event_source(timer)); 131 132 al_register_event_source(event_queue, al_get_keyboard_event_source()); 133 134 al_clear_to_color(al_map_rgb(0, 0, 0)); 135 136 al_flip_display(); 137 138 al_start_timer(timer); 139 140 while(!doexit) 141 { 142 ALLEGRO_EVENT ev; 143 144 al_wait_for_event(event_queue, &ev); 145 146 if(ev.type == ALLEGRO_EVENT_TIMER) { 147 148 //DROP SAND 149 if (key[KEY_SPACE]==true) 150 { 151 drop_sand(cursor_x,cursor_y); 152 redraw=true; 153 } 154 155 //CURSOR 156 if (key[KEY_W] && cursor_y >= 22.0) 157 { 158 cursor_y -= 4.0; 159 } 160 if(key[KEY_S] && cursor_y <= SCREEN_H - cursor_size - 4.0) 161 { 162 cursor_y += 4.0; 163 } 164 if(key[KEY_A] && cursor_x >= 22.0) 165 { 166 cursor_x -= 4.0; 167 } 168 if(key[KEY_D] && cursor_x <= SCREEN_W - cursor_size - 4.0) 169 { 170 cursor_x += 4.0; 171 } 172 //CURSOR 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 184 185 bouncer_x += bouncer_dx; 186 bouncer_y += bouncer_dy; 187 188 redraw = true; 189 } 190 191 else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { 192 break; 193 } 194 195 else if(ev.type == ALLEGRO_EVENT_KEY_DOWN) { 196 switch(ev.keyboard.keycode) { 197 case ALLEGRO_KEY_UP: 198 key[KEY_UP] = true; 199 break; 200 201 case ALLEGRO_KEY_DOWN: 202 key[KEY_DOWN] = true; 203 break; 204 205 case ALLEGRO_KEY_W: 206 key[KEY_W] = true; 207 break; 208 209 case ALLEGRO_KEY_S: 210 key[KEY_S] = true; 211 break; 212 213 case ALLEGRO_KEY_A: 214 key[KEY_A] = true; 215 break; 216 217 case ALLEGRO_KEY_D: 218 key[KEY_D] = true; 219 break; 220 221 case ALLEGRO_KEY_SPACE: 222 key[KEY_SPACE] = true; 223 break; 224 } 225 } 226 227 else if(ev.type == ALLEGRO_EVENT_KEY_UP) { 228 switch(ev.keyboard.keycode) { 229 case ALLEGRO_KEY_UP: 230 key[KEY_UP] = false; 231 break; 232 233 case ALLEGRO_KEY_DOWN: 234 key[KEY_DOWN] = false; 235 break; 236 237 case ALLEGRO_KEY_W: 238 key[KEY_W] = false; 239 break; 240 241 case ALLEGRO_KEY_S: 242 key[KEY_S] = false; 243 break; 244 245 case ALLEGRO_KEY_A: 246 key[KEY_A] = false; 247 break; 248 249 case ALLEGRO_KEY_D: 250 key[KEY_D] = false; 251 break; 252 253 case ALLEGRO_KEY_SPACE: 254 key[KEY_SPACE] = false; 255 break; 256 257 case ALLEGRO_KEY_ESCAPE: 258 doexit = true; 259 break; 260 } 261 } 262 263 if(redraw && al_is_event_queue_empty(event_queue)) { 264 redraw = false; 265 al_set_target_bitmap(cursor); 266 al_clear_to_color(al_map_rgb(0,0,0)); 267 268 al_set_target_bitmap(bouncer); 269 al_clear_to_color(al_map_rgb(0,0,0)); 270 271 al_set_target_bitmap(al_get_backbuffer(display)); 272 273 draw_cursor(cursor_x,cursor_y); 274 draw_ball(bouncer_x, bouncer_y); 275 276 277 al_rest(0.02); 278 279 al_flip_display(); 280 } 281 } 282 al_destroy_bitmap(cursor); 283 al_destroy_bitmap(bouncer); 284 al_destroy_bitmap(sand); 285 al_destroy_timer(timer); 286 al_destroy_display(display); 287 al_destroy_event_queue(event_queue); 288 289 return 0; 290}

Billybob
Member #3,136
January 2003

It looks like you're kind of making a painting app; like MS Paint, etc.

In that case, you need an ALLEGRO_BITMAP that acts as a canvas for the user to draw to. So, let's get started.

Add this towards the top of main, as another variable:

ALLEGRO_BITMAP *canvas = NULL;

Add this during initialization, probably right after creating the cursor, sand, bouncer bitmaps:

canvas = al_create_bitmap(SCREEN_W, SCREEN_H);

This creates a canvas the size of the screen.

Add this after the code for clearing bouncer and cursor:

That clears the canvas to black.

Inside the code where you call drop_sand do this instead:

al_set_target_bitmap(canvas);
drop_sand(cursor_x, cursor_y);
al_set_target_bitmap(al_get_backbuffer(display));
redraw = true;

This will draw the sand to the canvas.

Now in the code where you redraw the screen (line 271 in the code you posted), modify to this:

al_set_target_bitmap(al_get_backbuffer(display));
al_draw_bitmap(canvas, 0, 0, 0);    // Draw the canvas over the entire screen
draw_cursor(cursor_x, cursor_y);    // Draw the cursor on top (on the screen)
draw_ball(bouncer_x, bouncer_y);

That will "refresh" the screen with the current canvas, and draw the cursor and ball.

Right now, you're using the screen as your canvas. These new modifications just create an actual bitmap for the canvas, so you don't overwrite it every time :)

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

What are you planning to do with the sand after the user drops it?

If you're using C++, you might want to have a container that keeps track of where the sand has been dropped. Or if you go with a canvas idea like BillyBob suggested, then you could read a pixel location and compare it to your sand color.

Ninjarobot
Member #12,640
March 2011

Thanks for the help, gonna try it in a while as I just woke up!

As about the use of the sand, I guess I should have been more clear. My current goal is to only have a cursor and space to drop the sand as I said in the first post. However it's aimed to be a game where you have a secondary colour in the background(let's say blue)and you fill the coloured background with sand. I was even thinking of having a more complicated system like like :
Blue background: Drop sand once
Yellow: Drop sand twice
Green: Drop thrice

It should end up a precision game against time.

Go to: