Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [a5] A doubt about move of image with keyboard

This thread is locked; no one can reply to it. rss feed Print
 1   2   3 
[a5] A doubt about move of image with keyboard
Jefferson Almeida
Member #12,659
March 2011

Now is almost 04:00 in Brazil and I'm totally lost, sleep will not let me think straight, I go to bed and when I wake up I try to solve it, thanks a lot!

Edgar Reynaldo
Member #8,592
May 2007
avatar

Jefferson Almeida
Member #12,659
March 2011

Here, my last code:

#SelectExpand
1int cx = 10; 2int cy = 10; 3 4std::vector<ALLEGRO_BITMAP*> sprites; 5 6class Animation { 7private : 8 ALLEGRO_BITMAP** frames; 9 double duration; 10 double time_passed; 11 int frame_number; 12 int num_frames; 13public : 14 Animation() : 15 frames(0), 16 duration(0.0), 17 time_passed(0.0), 18 frame_number(0), 19 num_frames(0) 20 {} 21 Animation(int framecount , double time_length) : 22 frames(0), 23 duration(0.0), 24 time_passed(0.0), 25 frame_number(0), 26 num_frames(0) 27 { 28 Reallocate(framecount , time_length); 29 } 30 ~Animation() {Free();} 31 void Free() { 32 if (frames) {delete [] frames;frames = 0;} 33 num_frames = 0; 34 } 35 bool Reallocate(int framecount , double time_length) { 36 if (framecount < 1) {return false;} 37 if (time_length <= 0.0) {return false;} 38 Free(); 39 duration = time_length; 40 time_passed = 0.0; 41 frame_number = 0; 42 try { 43 frames = new ALLEGRO_BITMAP*[framecount]; 44 } 45 catch(...) { 46 frames = 0; 47 return false; 48 } 49 num_frames = framecount; 50 } 51 52 void SetBitmap(int index , ALLEGRO_BITMAP* bmp) { 53 assert((index >= 0) && (index < num_frames)); 54 frames[index] = bmp; 55 } 56 57 void AdvanceFrameTime(double delta_time) { 58 SetFrameTime(time_passed + delta_time); 59 } 60 void SetFrameTime(double frame_time) { 61 // simple forward repeating animation 62 time_passed = frame_time; 63 while (time_passed >= duration) {time_passed -= duration;} 64 while (time_passed < 0.0) {time_passed += duration;} 65 frame_number = (int)(time_passed / duration); 66 // shouldn't be necessary, but just in case 67 if (frame_number < 0) {frame_number = 0;} 68 if (frame_number >= num_frames) {frame_number = num_frames - 1;} 69 } 70 71 void Draw(int cx , int cy) { 72 al_draw_bitmap(frames[frame_number] , cx , cy , 0); 73 } 74 75}; 76 77int main(int argc , char** argv) 78{ 79 if(!al_init()) { 80 fprintf(stderr, "Failed al_init"); 81 return -1; 82 } 83 if(!al_init_primitives_addon()) { 84 fprintf(stderr, "Failed to initialize Addon primitives!\n"); 85 return -1; 86 } 87 al_init_font_addon(); 88 al_init_ttf_addon(); 89 if(!al_init_image_addon()) { 90 fprintf(stderr, "Failed to initialize Image addon!\n"); 91 return -1; 92 } 93 if(!al_install_mouse()) { 94 fprintf(stderr, "Failed to initialize Mouse!\n"); 95 return -1; 96 } 97 if(!al_install_keyboard()) { 98 fprintf(stderr, "Failed to initialize Keyboard!\n"); 99 return -1; 100 } 101 if(!al_install_audio()) { 102 fprintf(stderr, "failed to initialize audio!\n"); 103 return -1; 104 } 105 if(!al_init_acodec_addon()) { 106 fprintf(stderr, "failed to initialize audio codecs!\n"); 107 return -1; 108 } 109 if(!al_reserve_samples(1)) { 110 fprintf(stderr, "failed to reserve samples!\n"); 111 return -1; 112 } 113 timer = al_create_timer(1.0 / FPS); 114 if(!timer) { 115 fprintf(stderr, "Failed to created timer!\n"); 116 return -1; 117 } 118 font = al_load_ttf_font("DejaVuSans.ttf", 15, 0); 119 if(!font) { 120 fprintf(stderr, "Failed to load font!\n"); 121 return -1; 122 } 123 124 al_set_target_bitmap(al_get_backbuffer(display)); 125 126 event_queue = al_create_event_queue(); 127 if(!event_queue) { 128 fprintf(stderr, "Failed to create event_queue!\n"); 129 return -1; 130 } 131 132 display = al_create_display(SCREEN_W, SCREEN_H); 133 134 const int NUM_SPRITES = 3; 135 const char* sprite_files[NUM_SPRITES] = { 136 "Sprites/FFT1/21.bmp", 137 "Sprites/FFT1/22.bmp", 138 "Sprites/FFT1/23.bmp" 139 }; 140 for (int i = 0 ; i < NUM_SPRITES ; ++i) { 141 ALLEGRO_BITMAP* bmp = al_load_bitmap(sprite_files[i]); 142 if (!bmp) { 143 printf("Error loading %s\n" , sprite_files[i]); 144 return -1; 145 } 146 al_convert_mask_to_alpha(bmp, (al_map_rgb(255, 0, 255))); 147 sprites.push_back(bmp); 148 } 149 Animation anime(sprites.size() , 1.0); 150 for (int i = 0 ; i < NUM_SPRITES ; ++i) { 151 anime.SetBitmap(i , sprites[i]); 152 } 153 154 al_play_sample(sample, 1.0, 0.0,1.0,ALLEGRO_PLAYMODE_LOOP,NULL); 155 156 al_register_event_source(event_queue, al_get_display_event_source(display)); 157 158 al_register_event_source(event_queue, al_get_timer_event_source(timer)); 159 160 al_register_event_source(event_queue, al_get_keyboard_event_source()); 161 162 al_register_event_source(event_queue, al_get_mouse_event_source()); 163 164 al_flip_display(); 165 166 al_get_timer_count(timer); 167 168 al_start_timer(timer); 169 170 bool redraw; 171 bool quit; 172 while (!quit) { 173 if(redraw) { 174 al_clear_to_color(al_map_rgb(0,0,0)); 175 anime.Draw(cx , cy); 176 break; 177 } 178 al_flip_display(); 179 redraw = false; 180 } 181 while (1) { 182 ALLEGRO_EVENT ev; 183 if (al_event_queue_is_empty(event_queue)) { 184 anime.Draw(cx , cy); 185 al_flip_display(); 186 al_clear_to_color(al_map_rgb(0,0,0)); 187 } 188 al_wait_for_event(event_queue, &ev); 189 switch (ev.type) 190 { 191 case ALLEGRO_EVENT_DISPLAY_CLOSE: 192 quit = true; 193 break; 194 case ALLEGRO_EVENT_KEY_DOWN: 195 if (ev.keyboard.keycode == ALLEGRO_KEY_UP) { 196 cx -= 5; 197 cy -= 5; 198 //frame++; 199 break; 200 } 201 else if (ev.keyboard.keycode == ALLEGRO_KEY_DOWN) { 202 cx += 5; 203 cy += 5; 204 //frame++; 205 break; 206 } 207 else if (ev.keyboard.keycode == ALLEGRO_KEY_RIGHT) { 208 cx += 5; 209 cy ++; 210 //frame++; 211 break; 212 } 213 else if (ev.keyboard.keycode == ALLEGRO_KEY_LEFT) { 214 cx -= 5; 215 cy --; 216 //frame++; 217 break; 218 } 219 else if (ev.keyboard.keycode == ALLEGRO_KEY_F1) { 220 al_draw_bitmap(menuedit, 200, 100, 0); 221 al_flip_display(); 222 } 223 else if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) 224 quit = true; 225 break; 226 case ALLEGRO_EVENT_KEY_CHAR: 227 if (ev.keyboard.keycode == ALLEGRO_KEY_UP) { 228 cx -= 5; 229 cy -= 5; 230 //frame++; 231 break; 232 } 233 else if (ev.keyboard.keycode == ALLEGRO_KEY_DOWN) { 234 cx += 5; 235 cy += 5; 236 //frame++; 237 break; 238 } 239 else if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) { 240 quit = true; 241 break; 242 } 243 case ALLEGRO_EVENT_TIMER: 244 if (ev.type == ALLEGRO_EVENT_TIMER) { 245 anime.AdvanceFrameTime(1.0/FPS); 246 redraw = true; 247 } 248 } 249 } 250 return 0; 251};

Edgar Reynaldo
Member #8,592
May 2007
avatar

    while (!quit) {
        if(redraw) {
            al_clear_to_color(al_map_rgb(0,0,0));
            anime.Draw(cx , cy);
break;
} al_flip_display(); redraw = false; }

Without that break statement, you will be stuck in that loop forever, because quit is always false. With the break statement, you only clear the screen and draw the animation, but don't flip the display.

Your drawing code goes inside your game loop.

Jefferson Almeida
Member #12,659
March 2011

@@"

edit1: So I do not need to do a "if(redraw).." ?

#SelectExpand
1 bool redraw; 2 bool quit; 3 while (1) { 4 ALLEGRO_EVENT ev; 5 if (al_event_queue_is_empty(event_queue)) { 6 anime.Draw(cx , cy); 7 al_flip_display(); 8 al_clear_to_color(al_map_rgb(0,0,0)); 9 } 10 al_wait_for_event(event_queue, &ev); 11 switch (ev.type) 12 { 13 case ALLEGRO_EVENT_DISPLAY_CLOSE: 14 quit = true; 15 break; 16 case ALLEGRO_EVENT_KEY_DOWN: 17 if (ev.keyboard.keycode == ALLEGRO_KEY_UP) { 18 cx -= 5; 19 cy -= 5; 20 //frame++; 21 break; 22 } 23 else if (ev.keyboard.keycode == ALLEGRO_KEY_DOWN) { 24 cx += 5; 25 cy += 5; 26 break; 27 } 28 else if (ev.keyboard.keycode == ALLEGRO_KEY_RIGHT) { 29 cx += 5; 30 cy ++; 31 //frame++; 32 break; 33 } 34 else if (ev.keyboard.keycode == ALLEGRO_KEY_LEFT) { 35 cx -= 5; 36 cy --; 37 //frame++; 38 break; 39 } 40 else if (ev.keyboard.keycode == ALLEGRO_KEY_F1) { 41 al_draw_bitmap(menuedit, 200, 100, 0); 42 al_flip_display(); 43 } 44 else if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) 45 quit = true; 46 break; 47 case ALLEGRO_EVENT_KEY_CHAR: 48 if (ev.keyboard.keycode == ALLEGRO_KEY_UP) { 49 cx -= 5; 50 cy -= 5; 51 //frame++; 52 break; 53 } 54 else if (ev.keyboard.keycode == ALLEGRO_KEY_DOWN) { 55 cx += 5; 56 cy += 5; 57 frame++; 58 //sprites; 59 break; 60 } 61 else if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) { 62 quit = true; 63 break; 64 } 65 case ALLEGRO_EVENT_TIMER: 66 if (ev.type == ALLEGRO_EVENT_TIMER) { 67 anime.AdvanceFrameTime(1.0/FPS); 68 redraw = true; 69 } 70 } 71 } 72 return 0; 73};

Edgar Reynaldo
Member #8,592
May 2007
avatar

Jefferson Almeida
Member #12,659
March 2011

The part of animation is correct?

Edit 1: I can to put the "event timer" and then redraw or is better I to put the timer in a "case" in the end?

#SelectExpand
1 bool redraw; 2 bool quit; 3 while (1) { 4 ALLEGRO_EVENT ev; 5 if (ev.type == ALLEGRO_EVENT_TIMER) { 6 anime.AdvanceFrameTime(1.0/FPS); 7 redraw = true; 8 } 9 if (redraw) { 10 al_clear_to_color(al_map_rgb(0,0,0)); 11 anime.Draw(cx , cy); 12 al_flip_display(); 13 redraw = false; 14 } 15 al_wait_for_event(event_queue, &ev); 16 switch(ev.type) { 17 case ALLEGRO_EVENT_DISPLAY_CLOSE: 18 quit = true; 19 break; 20 case ALLEGRO_EVENT_KEY_DOWN: 21 if (ev.keyboard.keycode == ALLEGRO_KEY_UP) { 22 cx -= 5; 23 cy -= 5; 24 break; 25 } 26 else if (ev.keyboard.keycode == ALLEGRO_KEY_DOWN) { 27 cx += 5; 28 cy += 5; 29 break; 30 } 31 else if (ev.keyboard.keycode == ALLEGRO_KEY_RIGHT) { 32 cx += 5; 33 cy ++; 34 break; 35 } 36 else if (ev.keyboard.keycode == ALLEGRO_KEY_LEFT) { 37 cx -= 5; 38 cy --; 39 break; 40 } 41 else if (ev.keyboard.keycode == ALLEGRO_KEY_F1) { 42 al_draw_bitmap(menuedit, 200, 100, 0); 43 al_flip_display(); 44 } 45 else if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) 46 quit = true; 47 break; 48 case ALLEGRO_EVENT_KEY_CHAR: 49 if (ev.keyboard.keycode == ALLEGRO_KEY_UP) { 50 cx -= 5; 51 cy -= 5; 52 break; 53 } 54 else if (ev.keyboard.keycode == ALLEGRO_KEY_DOWN) { 55 cx += 5; 56 cy += 5; 57 break; 58 } 59 else if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) 60 quit = true; 61 break; 62 //case ALLEGRO_EVENT_TIMER: 63 //if (ev.type == ALLEGRO_EVENT_TIMER) { 64 //anime.AdvanceFrameTime(1.0/FPS); 65 //redraw = true; 66 //break; 67 //} 68 } 69 } 70 return 0; 71}

Edgar Reynaldo
Member #8,592
May 2007
avatar

Game loop :

#SelectExpand
1while (!quit) { 2 while (1) ( 3 ALLEGRO_EVENT ev; 4 al_wait_for_event(event_queue , &ev); 5 if (ev.type == BLAH) { 6 7 } 8 else if (ev.type == ALLEGRO_EVENT_TIMER) { 9 anime.AdvanceFrameTime(1.0/FPS); 10 redraw = true; 11 } 12 if (al_is_event_queue_empty(event_queue)) { 13 break; 14 } 15 } 16 if (redraw) { 17 al_clear_to_color(al_map_rgb(0,0,0)); 18 anime.Draw(x,y); 19 al_flip_display(); 20 redraw = false; 21 } 22}

Jefferson Almeida
Member #12,659
March 2011

Look:

#SelectExpand
1 while (!quit) { 2 while (1) { 3 ALLEGRO_EVENT ev; 4 al_wait_for_event(event_queue , &ev); 5 if (ev.type == ALLEGRO_EVENT_KEY_DOWN) { 6 if(ev.keyboard.keycode == ALLEGRO_KEY_DOWN) { 7 cx += 5; 8 cy += 5; 9 break; 10 } 11 } 12 else if (ev.type == ALLEGRO_EVENT_TIMER) { 13 anime.AdvanceFrameTime(1.0/FPS); 14 redraw = true; 15 } 16 if (al_is_event_queue_empty(event_queue)) { 17 break; 18 } 19 } 20 if (redraw) { 21 al_clear_to_color(al_map_rgb(0,0,0)); 22 anime.Draw(cx,cy); 23 al_flip_display(); 24 redraw = false; 25 } 26 } 27}

Edgar Reynaldo
Member #8,592
May 2007
avatar

Jefferson Almeida
Member #12,659
March 2011

Just to know if it was right =D
The animation I have to add anything ?

class of the another topic

#SelectExpand
1class Animation { 2private : 3 ALLEGRO_BITMAP** frames; 4 double duration; 5 double time_passed; 6 int frame_number; 7 int num_frames; 8public : 9 Animation() : 10 frames(0), 11 duration(0.0), 12 time_passed(0.0), 13 frame_number(0), 14 num_frames(0) 15 {} 16 Animation(int framecount , double time_length) : 17 frames(0), 18 duration(0.0), 19 time_passed(0.0), 20 frame_number(0), 21 num_frames(0) 22 { 23 Reallocate(framecount , time_length); 24 } 25 ~Animation() {Free();} 26 void Free() { 27 if (frames) {delete [] frames;frames = 0;} 28 num_frames = 0; 29 } 30 bool Reallocate(int framecount , double time_length) { 31 if (framecount < 1) {return false;} 32 if (time_length <= 0.0) {return false;} 33 Free(); 34 duration = time_length; 35 time_passed = 0.0; 36 frame_number = 0; 37 try { 38 frames = new ALLEGRO_BITMAP*[framecount]; 39 } 40 catch(...) { 41 frames = 0; 42 return false; 43 } 44 num_frames = framecount; 45 } 46 47 void SetBitmap(int index , ALLEGRO_BITMAP* bmp) { 48 assert((index >= 0) && (index < num_frames)); 49 frames[index] = bmp; 50 } 51 52 void AdvanceFrameTime(double delta_time) { 53 SetFrameTime(time_passed + delta_time); 54 } 55 void SetFrameTime(double frame_time) { 56 // simple forward repeating animation 57 time_passed = frame_time; 58 while (time_passed >= duration) {time_passed -= duration;} 59 while (time_passed < 0.0) {time_passed += duration;} 60 frame_number = (int)(time_passed / duration); 61 // shouldn't be necessary, but just in case 62 if (frame_number < 0) {frame_number = 0;} 63 if (frame_number >= num_frames) {frame_number = num_frames - 1;} 64 } 65 66 void Draw(int cx , int cy) { 67 al_draw_bitmap(frames[frame_number] , cx , cy , 0); 68 } 69 70};

code that I put in the main!

#SelectExpand
1... 2 const int NUM_SPRITES = 3; 3 const char* sprite_files[NUM_SPRITES] = { 4 "Sprites/FFT1/21.bmp", 5 "Sprites/FFT1/22.bmp", 6 "Sprites/FFT1/23.bmp" 7 }; 8 for (int i = 0 ; i < NUM_SPRITES ; ++i) { 9 ALLEGRO_BITMAP* bmp = al_load_bitmap(sprite_files[i]); 10 if (!bmp) { 11 printf("Error loading %s\n" , sprite_files[i]); 12 return -1; 13 } 14 al_convert_mask_to_alpha(bmp, (al_map_rgb(255, 0, 255))); 15 sprites.push_back(bmp); 16 } 17 Animation anime(sprites.size() , 1.0); 18 for (int i = 0 ; i < NUM_SPRITES ; ++i) { 19 anime.SetBitmap(i , sprites[i]); 20 } 21...

Edgar Reynaldo
Member #8,592
May 2007
avatar

Jefferson Almeida
Member #12,659
March 2011

Hi, sorry for delay... I was trying to discover before to ask help!
yeah, My animation no work!

Edit1: Oddly enough... rs... I think this time the indentation are totally right. o_O"

#SelectExpand
1 2int cx = 0; 3int cy = 0; 4float frame = 0; 5std::vector<ALLEGRO_BITMAP*> sprites; 6 7class Animation { 8private : 9 ALLEGRO_BITMAP** frames; 10 double duration; 11 double time_passed; 12 int frame_number; 13 int num_frames; 14public : 15 Animation() : 16 frames(0), 17 duration(0.0), 18 time_passed(0.0), 19 frame_number(0), 20 num_frames(0) 21 {} 22 Animation(int framecount , double time_length) : 23 frames(0), 24 duration(0.0), 25 time_passed(0.0), 26 frame_number(0), 27 num_frames(0) 28 { 29 Reallocate(framecount , time_length); 30 } 31 ~Animation() {Free();} 32 void Free() { 33 if (frames) {delete [] frames;frames = 0;} 34 num_frames = 0; 35 } 36 bool Reallocate(int framecount , double time_length) { 37 if (framecount < 1) {return false;} 38 if (time_length <= 0.0) {return false;} 39 Free(); 40 duration = time_length; 41 time_passed = 0.0; 42 frame_number = 0; 43 try { 44 frames = new ALLEGRO_BITMAP*[framecount]; 45 } 46 catch(...) { 47 frames = 0; 48 return false; 49 } 50 num_frames = framecount; 51 } 52 53 void SetBitmap(int index , ALLEGRO_BITMAP* bmp) { 54 assert((index >= 0) && (index < num_frames)); 55 frames[index] = bmp; 56 } 57 58 void AdvanceFrameTime(double delta_time) { 59 SetFrameTime(time_passed + delta_time); 60 } 61 void SetFrameTime(double frame_time) { 62 // simple forward repeating animation 63 time_passed = frame_time; 64 while (time_passed >= duration) {time_passed -= duration;} 65 while (time_passed < 0.0) {time_passed += duration;} 66 frame_number = (int)(time_passed / duration); 67 // shouldn't be necessary, but just in case 68 if (frame_number < 0) {frame_number = 0;} 69 if (frame_number >= num_frames) {frame_number = num_frames - 1;} 70 } 71 72 void Draw(int cx , int cy) { 73 al_draw_bitmap(frames[frame_number] , cx , cy , 0); 74 } 75 76};

Main:

#SelectExpand
1int main(int argc , char** argv) 2{ 3 if(!al_init()) { 4 fprintf(stderr, "Failed al_init"); 5 return -1; 6 } 7 if(!al_init_primitives_addon()) { 8 fprintf(stderr, "Failed to initialize Addon primitives!\n"); 9 return -1; 10 } 11 al_init_font_addon(); 12 al_init_ttf_addon(); 13 if(!al_init_image_addon()) { 14 fprintf(stderr, "Failed to initialize Image addon!\n"); 15 return -1; 16 } 17 if(!al_install_mouse()) { 18 fprintf(stderr, "Failed to initialize Mouse!\n"); 19 return -1; 20 } 21 if(!al_install_keyboard()) { 22 fprintf(stderr, "Failed to initialize Keyboard!\n"); 23 return -1; 24 } 25 if(!al_install_audio()) { 26 fprintf(stderr, "failed to initialize audio!\n"); 27 return -1; 28 } 29 if(!al_init_acodec_addon()) { 30 fprintf(stderr, "failed to initialize audio codecs!\n"); 31 return -1; 32 } 33 if(!al_reserve_samples(1)) { 34 fprintf(stderr, "failed to reserve samples!\n"); 35 return -1; 36 } 37 timer = al_create_timer(1.0 / FPS); 38 if(!timer) { 39 fprintf(stderr, "Failed to created timer!\n"); 40 return -1; 41 } 42 font = al_load_ttf_font("DejaVuSans.ttf", 15, 0); 43 if(!font) { 44 fprintf(stderr, "Failed to load font!\n"); 45 return -1; 46 } 47 48 al_set_target_bitmap(al_get_backbuffer(display)); 49 50 event_queue = al_create_event_queue(); 51 if(!event_queue) { 52 fprintf(stderr, "Failed to create event_queue!\n"); 53 return -1; 54 } 55 56 display = al_create_display(SCREEN_W, SCREEN_H); 57 58 const int NUM_SPRITES = 3; 59 const char* sprite_files[NUM_SPRITES] = { 60 "Sprites/FFT1/21.bmp", 61 "Sprites/FFT1/22.bmp", 62 "Sprites/FFT1/23.bmp" 63 }; 64 for (int i = 0 ; i < NUM_SPRITES ; ++i) { 65 ALLEGRO_BITMAP* bmp = al_load_bitmap(sprite_files[i]); 66 if (!bmp) { 67 printf("Error loading %s\n" , sprite_files[i]); 68 return -1; 69 } 70 al_convert_mask_to_alpha(bmp, (al_map_rgb(255, 0, 255))); 71 sprites.push_back(bmp); 72 } 73 Animation anime(sprites.size() , 1.0); 74 for (int i = 0 ; i < NUM_SPRITES ; ++i) { 75 anime.SetBitmap(i , sprites[i]); 76 } 77 78 al_play_sample(sample, 1.0, 0.0,1.0,ALLEGRO_PLAYMODE_LOOP,NULL); 79 80 al_register_event_source(event_queue, al_get_display_event_source(display)); 81 82 al_register_event_source(event_queue, al_get_timer_event_source(timer)); 83 84 al_register_event_source(event_queue, al_get_keyboard_event_source()); 85 86 al_register_event_source(event_queue, al_get_mouse_event_source()); 87 88 al_flip_display(); 89 90 al_get_timer_count(timer); 91 92 al_start_timer(timer); 93 94 bool redraw; 95 bool quit; 96 while (!quit) { 97 while (1) { 98 ALLEGRO_EVENT ev; 99 al_wait_for_event(event_queue , &ev); 100 if (ev.type == ALLEGRO_EVENT_KEY_DOWN) { 101 if(ev.keyboard.keycode == ALLEGRO_KEY_DOWN) { 102 cx += 5; 103 cy += 5; 104 //frame++; 105 break; 106 } 107 } 108 else if (ev.type == ALLEGRO_EVENT_TIMER) { 109 anime.AdvanceFrameTime(1.0/FPS); 110 redraw = true; 111 } 112 if (al_is_event_queue_empty(event_queue)) { 113 break; 114 } 115 } 116 if (redraw) { 117 al_clear_to_color(al_map_rgb(0,0,0)); 118 anime.Draw(cx,cy); 119 al_flip_display(); 120 redraw = false; 121 } 122 } 123}

Edgar Reynaldo
Member #8,592
May 2007
avatar

Sorry, there was a bug in the frame setting code in SetFrameTime. This version should work properly. Just replace the old class with this one.

#SelectExpand
1 2class Animation { 3private : 4 ALLEGRO_BITMAP** frames; 5 double duration; 6 double time_passed; 7 int frame_number; 8 int num_frames; 9public : 10 Animation() : 11 frames(0), 12 duration(0.0), 13 time_passed(0.0), 14 frame_number(0), 15 num_frames(0) 16 {} 17 Animation(int framecount , double time_length) : 18 frames(0), 19 duration(0.0), 20 time_passed(0.0), 21 frame_number(0), 22 num_frames(0) 23 { 24 Reallocate(framecount , time_length); 25 } 26 ~Animation() {Free();} 27 void Free() { 28 if (frames) {delete [] frames;frames = 0;} 29 num_frames = 0; 30 } 31 bool Reallocate(int framecount , double time_length) { 32 if (framecount < 1) {return false;} 33 if (time_length <= 0.0) {return false;} 34 Free(); 35 duration = time_length; 36 time_passed = 0.0; 37 frame_number = 0; 38 try { 39 frames = new ALLEGRO_BITMAP*[framecount]; 40 } 41 catch(...) { 42 frames = 0; 43 return false; 44 } 45 num_frames = framecount; 46 return true; 47 } 48 49 void SetBitmap(int index , ALLEGRO_BITMAP* bmp) { 50 assert((index >= 0) && (index < num_frames)); 51 frames[index] = bmp; 52 } 53 54 void AdvanceFrameTime(double delta_time) { 55 SetFrameTime(time_passed + delta_time); 56 } 57 void SetFrameTime(double frame_time) { 58 // simple forward repeating animation 59 time_passed = frame_time; 60 while (time_passed >= duration) {time_passed -= duration;} 61 while (time_passed < 0.0) {time_passed += duration;} 62 frame_number = (int)((float)num_frames*(time_passed / duration)); 63 // shouldn't be necessary, but just in case 64 if (frame_number < 0) {frame_number = 0;} 65 if (frame_number >= num_frames) {frame_number = num_frames - 1;} 66 } 67 68 void Draw(int x , int y) { 69 al_draw_bitmap(frames[frame_number] , x , y , 0); 70 } 71 72 double FrameTime() {return time_passed;} 73 int FrameNum() {return frame_number;} 74 75};

The bug was in SetFrameTime here :

   void SetFrameTime(double frame_time) {
      // simple forward repeating animation
      time_passed = frame_time;
      while (time_passed >= duration) {time_passed -= duration;}
      while (time_passed < 0.0) {time_passed += duration;}
frame_number = (int)((float)num_frames*(time_passed / duration));
// shouldn't be necessary, but just in case if (frame_number < 0) {frame_number = 0;} if (frame_number >= num_frames) {frame_number = num_frames - 1;} }

Neil Walker
Member #210
April 2000
avatar

All your code seems (e.g. the 'sprite' vector, the load function, etc) to be set on having just one sprite. What about other sprites in the game or different animations for the same sprite (e.g. moving left, right, jumping, etc).

What you should do is as well as having an animation class, have an animation manager class to store all your animations (I used a config file that stored each animation in a stl map so you could retrieve by namem this also means you don't hard code bitmap names into the executable).

Regarding the Animation class, in my animation I added a set of actions (e.g. pause, manual increment, frame based increment), a sprite step mode (i.e. what happens when you move from one frame to the next and/or get to the start/end) for example FORWARDONLY (first to last then stay at last from), BACKWARDONLY, FLIPFLOP (repeat forwards, backwards), REPEATFORWARD (at end go back to start) and a basic event (i.e. function pointer) to trigger when animation ends (handy for setting an action, like a dying animation then informing the system that the death throws are finished).

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Jefferson Almeida
Member #12,659
March 2011

Hi... no problem Edgar... Thanks a lot!

Hi Neil, thanks for tips, maybe I use: http://oi54.tinypic.com/2qjvxig.jpg and al_create_sub_bitmap

Edit 1: I saw in the another topic an cool example, I made ​​a small correction!

I realize that this makes the image to animate in all positions, if I want my image to animate for each moviment, RIGHT, LEFT, UP, DOWN I had to do something similar and split into frames?
It would be an animation for each move?

#SelectExpand
1class Animation { 2protected : 3 ALLEGRO_BITMAP** frames; 4 double duration; 5 double frames_per_sec; 6 double frametime; 7 int num_frames; 8 int frame_num; 9 10public : 11 Animation() : 12 frames(0), 13 duration(0.0), 14 frames_per_sec(0.0), 15 frametime(0.0), 16 num_frames(0), 17 frame_num(0) 18 {} 19 ~Animation() {Free();} 20 21 void Free() { 22 if (frames) { 23 delete [] frames; 24 frames = 0; 25 } 26 } 27 28 void Setup(double play_duration , int number_of_frames) { 29 Free(); 30 assert(number_of_frames > 0); 31 assert(play_duration > 0.0); 32 duration = play_duration; 33 num_frames = number_of_frames; 34 frames = new ALLEGRO_BITMAP*[num_frames]; 35 frames_per_sec = (double)num_frames / duration; 36 SetFrameTime(0.0); 37 } 38 void AdvanceFrameTime(double delta_time) { 39 SetFrameTime(frametime + delta_time); 40 } 41 void SetFrameTime(double new_frame_time) { 42 while(new_frame_time < 0.0) {new_frame_time += duration;} 43 while(new_frame_time >= duration) {new_frame_time -= duration;} 44 frametime = new_frame_time; 45 frame_num = (int)(frametime*frames_per_sec); 46 } 47 void SetBitmap(ALLEGRO_BITMAP* bmp, int frame_number) { 48 assert(frames); 49 assert((frame_number >= 0) && (frame_number < num_frames)); 50 frames[frame_number] = bmp; 51 } 52 void Display(int x , int y) { 53 assert(frames); 54 assert(frames[frame_num]); 55 al_draw_bitmap(frames[frame_num] , (float)x , (float)y , 0); 56 } 57 58};

#SelectExpand
1double duration = 10.0; 2int number_of_frames = 40; 3Animation anime; 4anime.Setup(duration , number_of_frames); 5 6ALLEGRO_BITMAP* bmp = al_load_bitmap("player.png"); 7//converts the sprite sheet's magenta background to transparent pixels al_convert_mask_to_alpha(bmp, (al_map_rgb(255, 0, 255))); 8int i = 0; 9ALLEGRO_BITMAP* bmp_array[40]; 10for(int x = 0; x < 8; x++) { 11 for(int y = 0; y < 5; y++) { 12 ALLEGRO_BITMAP* bmp_array[x][y]; 13 bmp_array[x][y] = al_create_sub_bitmap(bmp, 32*x, 32*y, 32, 32); 14 anime.SetBitmap(bmp_array[x][y] , i); 15 ++i; 16 } 17} 18 19// Event loop 20 while (1) { 21 ALLEGRO_EVENT ev; 22 al_wait_for_event(event_queue , &ev); 23 if (ev.type == ALLEGRO_EVENT_TIMER) { 24 anime.AdvanceFrameTime(SECONDS_PER_TICK); 25 redraw = true; 26 } 27 if (al_is_event_queue_empty(event_queue)) {break}; 28 } 29 if (redraw) { 30 al_clear_to_color(al_map_rgb(0,0,0)); 31 anime.Draw(400 - al_get_bitmap_width(bmp)/2 , 300 - al_get_bitmap_height(bmp)/2); 32 al_flip_display(); 33 } 34}

Edgar Reynaldo
Member #8,592
May 2007
avatar

I realize that this makes the image to animate in all positions, if I want my image to animate for each moviment, RIGHT, LEFT, UP, DOWN I had to do something similar and split into frames?
It would be an animation for each move?

Yes, there would be a separate animation for each.

Jefferson Almeida said:

ALLEGRO_BITMAP* bmp_array[40];
for(int x = 0; x < 8; x++) {
   for(int y = 0; y < 5; y++) {
ALLEGRO_BITMAP* bmp_array[x][y];
bmp_array[x][y] = al_create_sub_bitmap(bmp, 32*x, 32*y, 32, 32); anime.SetBitmap(bmp_array[x][y] , i); ++i; } }

That is not good coding. You've declared a shadowed variable named bmp_array, and you are assigning the bitmaps to the local bmp_array, not the bmp_array you declared on the first line. That means every sub bitmap created there will be leaked, because the Animation class does not destroy the ALLEGRO_BITMAP*'s that it holds. If you're using MinGW as your compiler, then you should add the compiler flag -Wshadow to your compilation command. It will tell you when you are shadowing (creating more than one variable with the same name) variables.

Isso não é bom de codificação. Você declarou uma variável chamada bmp_array sombra, e você atribuir o bitmaps para o bmp_array local, não a bmp_array você declarou na primeira linha. Isso significa que cada sub bitmap criado haverá vazamento, porque a classe Animação não é destruir o * ALLEGRO_BITMAP 'que detém. Se você estiver usando MinGW como seu compilador, então você deve adicionar o compilador bandeira Wshadow para o comando de compilação. Ele lhe dirá quando você está sombreamento (criando mais de uma variável com o mesmo nome) variáveis.

Jefferson Almeida
Member #12,659
March 2011

I saw this code this topic: http://www.allegro.cc/forums/thread/607037/913972#target

I stayed curious to see but do not compiled... so I put this way with the leaked just to see.

I'm trying to do of way that I can to have the animations for all movements for when a key is pressed.
I do not know if is better to have all movements in just one image or have all images apart.

Edgar Reynaldo
Member #8,592
May 2007
avatar

If you're going to use my Animation class, you need to have a separate Animation for each movement of the character - one for left, right, up, down. The Animation class is currently not copy-able, so you can't store it directly in a map, but you could use a map of pointers :

#SelectExpand
1#include <map> 2using std::map; 3 4#include <string> 5using std::string; 6 7enum KEYS { 8 LEFT = 0, 9 RIGHT = 1, 10 UP = 2, 11 DOWN = 3, 12 NUMKEYS = 4 13} 14 15bool key[NUMKEYS]; 16for (int i = 0 ; i < NUMKEYS ; ++i) {key[i] = false;} 17 18// in main 19Animation anime[4]; 20anime[0].Reallocate(3 , 3.0); 21// load bitmaps and use SetBitmap 22 23map<string , Animation*> amap; 24amap["left"] = &(anime[0]); 25amap["right"] = &(anime[1]); 26amap["up"] = &(anime[2]); 27amap["down"] = &(anime[3]); 28 29Animation* current = amap["left"]; 30 31// in logic 32if (ev.type == ALLEGRO_EVENT_KEY_DOWN) { 33 if (ev.keyboard.keycode == ALLEGRO_KEY_LEFT) { 34 current = amap["left"]; 35 current->SetFrameTime(0.0); 36 key[LEFT] = true; 37 } 38} 39else if (ev.type == ALLEGRO_EVENT_KEY_UP) { 40 if (ev.keyboard.keycode == ALLEGRO_KEY_LEFT) { 41 key[LEFT] = false; 42 } 43} 44else if (ev.type == ALLEGRO_EVENT_TIMER) { 45 if (key[LEFT] || key[RIGHT] || key[UP] || key[DOWN]) { 46 current->AdvanceFrameTime(1.0/FPS); 47 if (key[LEFT]) { 48 cx -= 5; 49 } 50 if (key[RIGHT]) { 51 cx += 5; 52 } 53 } else { 54 current->SetFrameTime(0.0); 55 } 56 redraw = true; 57}

This is just an example, but it should show you how to switch between animations, and only update the animation when you are moving.

Jefferson Almeida
Member #12,659
March 2011

Hello, to use "SetBitmap" he needs a member, which I use, already there is:
Anime animation [4];
Anime [0]. reallocate (3, 3.0);

Edgar Reynaldo
Member #8,592
May 2007
avatar

Jefferson Almeida
Member #12,659
March 2011

This way?

#SelectExpand
1 ... 2 Animation anime[4]; 3 anime[0].Reallocate(3 , 3.0); 4 // load bitmaps and use SetBitmap 5 ALLEGRO_BITMAP* bmp0 = al_load_bitmap("Sprites/FFT1/41.bmp"); 6 ALLEGRO_BITMAP* bmp1 = al_load_bitmap("Sprites/FFT1/42.bmp"); 7 ALLEGRO_BITMAP* bmp2 = al_load_bitmap("Sprites/FFT1/43.bmp"); 8 if(!bmp0 && bmp1 && bmp2) { 9 fprintf(stderr, "Failed to load left images"); 10 return -1; 11 } 12 al_convert_mask_to_alpha(bmp0, (al_map_rgb(255, 0, 255))); 13 al_convert_mask_to_alpha(bmp1, (al_map_rgb(255, 0, 255))); 14 al_convert_mask_to_alpha(bmp2, (al_map_rgb(255, 0, 255))); 15 anime[0].SetBitmap(0 , bmp0); 16 anime[0].SetBitmap(1 , bmp1); 17 anime[0].SetBitmap(2 , bmp2); 18 ...

Do I have to redraw?
Something like "anime[0].Draw(cx, cy);" ?
or the fact to be a "current frame" him redraw automatically!

Edgar Reynaldo
Member #8,592
May 2007
avatar

Jefferson Almeida
Member #12,659
March 2011

Hi... I put this way and work! "Since last post I just change "anime.Draw(cx,cy)" for "current->Draw(cx, cy);"

I just could not update the sprite at every turn, it updates after a long time the button pressed.

#SelectExpand
1 ... 2 display = al_create_display(SCREEN_W, SCREEN_H); 3 4 bool key[NUMKEYS]; 5 for (int i = 0 ; i < NUMKEYS ; ++i) {key[i] = false;} 6 7 Animation anime[4]; 8 anime[0].Reallocate(3 , 3.0); 9 anime[1].Reallocate(3 , 3.0); 10 // load bitmaps and use SetBitmap 11 ALLEGRO_BITMAP* bmpl0 = al_load_bitmap("Sprites/FFT1/41.bmp"); 12 ALLEGRO_BITMAP* bmpl1 = al_load_bitmap("Sprites/FFT1/42.bmp"); 13 ALLEGRO_BITMAP* bmpl2 = al_load_bitmap("Sprites/FFT1/43.bmp"); 14 ALLEGRO_BITMAP* bmpr0 = al_load_bitmap("Sprites/FFT1/21.bmp"); 15 ALLEGRO_BITMAP* bmpr1 = al_load_bitmap("Sprites/FFT1/22.bmp"); 16 ALLEGRO_BITMAP* bmpr2 = al_load_bitmap("Sprites/FFT1/23.bmp"); 17 if(!bmpl0 && bmpl1 && bmpl2 && bmpr0 && bmpr1 && bmpr2) { 18 fprintf(stderr, "Failed to load left and right images"); 19 return -1; 20 } 21 al_convert_mask_to_alpha(bmpl0, (al_map_rgb(255, 0, 255))); 22 al_convert_mask_to_alpha(bmpl1, (al_map_rgb(255, 0, 255))); 23 al_convert_mask_to_alpha(bmpl2, (al_map_rgb(255, 0, 255))); 24 al_convert_mask_to_alpha(bmpr0, (al_map_rgb(255, 0, 255))); 25 al_convert_mask_to_alpha(bmpr1, (al_map_rgb(255, 0, 255))); 26 al_convert_mask_to_alpha(bmpr2, (al_map_rgb(255, 0, 255))); 27 anime[0].SetBitmap(0 , bmpl0); 28 anime[0].SetBitmap(1 , bmpl1); 29 anime[0].SetBitmap(2 , bmpl2); 30 anime[1].SetBitmap(0 , bmpr0); 31 anime[1].SetBitmap(1 , bmpr1); 32 anime[1].SetBitmap(2 , bmpr2); 33 34 35 map<string , Animation*> amap; 36 amap["left"] = &(anime[0]); 37 amap["right"] = &(anime[1]); 38 amap["up"] = &(anime[2]); 39 amap["down"] = &(anime[3]); 40 41 Animation* current = &(anime[0]); 42 43 al_register_event_source(event_queue, al_get_display_event_source(display)); 44 45 al_register_event_source(event_queue, al_get_timer_event_source(timer)); 46 47 al_register_event_source(event_queue, al_get_keyboard_event_source()); 48 49 al_register_event_source(event_queue, al_get_mouse_event_source()); 50 51 al_get_timer_count(timer); 52 53 al_start_timer(timer); 54 55 bool quit; 56 bool redraw; 57 while (!quit) { 58 while (1) { 59 ALLEGRO_EVENT ev; 60 al_wait_for_event(event_queue , &ev); 61 if (ev.type == ALLEGRO_EVENT_KEY_DOWN) { 62 if (ev.keyboard.keycode == ALLEGRO_KEY_LEFT) { 63 current = amap["left"]; 64 current->SetFrameTime(0.0); 65 key[LEFT] = true; 66 } 67 if (ev.keyboard.keycode == ALLEGRO_KEY_RIGHT) { 68 current = amap["right"]; 69 current->SetFrameTime(0.0); 70 key[RIGHT] = true; 71 } 72 } 73 else if (ev.type == ALLEGRO_EVENT_KEY_UP) { 74 if (ev.keyboard.keycode == ALLEGRO_KEY_LEFT) { 75 key[LEFT] = false; 76 } 77 if (ev.keyboard.keycode == ALLEGRO_KEY_RIGHT) { 78 key[RIGHT] = false; 79 } 80 } 81 else if (ev.type == ALLEGRO_EVENT_TIMER) { 82 if (key[LEFT] || key[RIGHT] || key[UP] || key[DOWN]) { 83 current->AdvanceFrameTime(1.0/FPS); 84 if (key[LEFT]) { 85 cx -= 5; 86 } 87 if (key[RIGHT]) { 88 cx += 5; 89 } 90 } else { 91 current->SetFrameTime(0.0); 92 } 93 redraw = true; 94 } 95 if (redraw) { 96 al_clear_to_color(al_map_rgb(0,0,0)); 97 current->Draw(cx, cy); 98 al_flip_display(); 99 } 100 } 101 } 102};

Edgar Reynaldo
Member #8,592
May 2007
avatar

Your 'if (redraw)' block should not be inside your 'while (1)' loop.

You also need to break out of the 'while (1)' loop when there are no more events, so you can redraw.

Edit
Actually, never mind what I just said. Your code looks like it should do what you want it to. It waits for an event, then processes it appropriately. One thing though - you never set redraw to false, so it redraws every time there is an event. Not really a problem though.

You can try shortening the duration of the animation :

anime[0].Reallocate(3 , 1.0);

 1   2   3 


Go to: