Bug (or not) in Allegro
kuarcke

Hello, I'm creating a game with Allegro 5, Visual Studio 8 and Windows XP.
Well, when I run the game, the tiles that are on the screen suffer a deformation, this effect occurs around the display of the Allegro, and only when I move the tiles, when they stopped the deformation disappears.
The effect starts low, rises and deforming the tiles, it happens every 4 seconds or so. Tried to replace the images by the most primitive effect is the same.

A photo of the problem:
{"name":"2w3nfuw.jpg","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/9\/999e772caec7c6f0b2be4a54e280c06a.jpg","w":885,"h":471,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/9\/999e772caec7c6f0b2be4a54e280c06a"}2w3nfuw.jpg

A video of the "bug":
http://youtu.be/Nf-Qa7VaWs0

Below the drawing code of tiles:

#SelectExpand
1//class tile 2 3void tile::draw(){ 4 al_draw_bitmap(image,get_x(),get_y(),0); 5}

In tile class has a std :: vector<tile> contains that all existing tiles on the map, and the method draw () the map I draw them like this:

#SelectExpand
1//class map 2//all_tiles is std::vector<tile> static that contains all of the map tiles 3 4void map::draw(){ 5 al_clear_to_color(WHITE); 6 for(int i = 0 ; i < (int) tile::all_tiles.size() ; i++) 7 tile::all_tiles.at(i)->draw(); 8}

Do not bother to swap the buffers because the documentation says that the Allegro automatically identifies what the current backbuffer. I think be no problem with my computer 'cause I have done some games in Java (which is much slower than c ++) and ran perfectly. Does the problem is because Windows XP? Or am I doing something wrong?

Edgar Reynaldo

Show more relevant code. Where are you flipping the display? Are you using transforms?

Also, have you verified vsync is running?

kuarcke

I have not posted much of anything because the code is very simple.
Swapping buffers to the end of the method repaint() the main class:

void repaint(){
  al_clear_to_color(WHITE);
  mapa.draw();
  al_flip_display();
}

Information that may be important: each object has a pointer to tile corresponds to their respective image. Carry the tileset atlas, he divided the tiles, and move the pointer of each image to its corresponding tile.
That alone, without effects, transformation, rotations, etc ..

LennyLen

Show ALL the code.

This is very unlikely to be a bug with Allegro, or it would be more common.

Edgar Reynaldo

Where are you setting up the display?

kuarcke

Main class:

#SelectExpand
1#include <allegro5/allegro.h> 2#include <allegro5/allegro_image.h> 3#include <allegro5/allegro_primitives.h> 4#include "map.h" 5#include <stdio.h> 6#include <windows.h> 7 8#define WIDTH 1280 9#define HEIGHT 800 10#define GAME_NAME "Game Allegro" 11#define FPS 60.0 12#define LPS 120.0 13 14int load(); 15void main_loop(); 16void events(); 17void update(); 18void repaint(); 19void quit(); 20 21map mapa; 22 23ALLEGRO_DISPLAY *display = NULL; 24ALLEGRO_EVENT_QUEUE *eventqueue = NULL; 25ALLEGRO_TIMER *timer_fps = NULL; 26ALLEGRO_TIMER *timer_lps = NULL; 27 28ALLEGRO_EVENT evento; 29 30bool play = true; 31bool keys[226]; 32 33bool need_redraw = false; 34bool need_update = false; 35 36int main(int argc, char **argv){ 37 if(!load()){ 38 quit(); 39 printf("\nPressione uma tecla para sair."); 40 getchar(); 41 return 0; 42 } 43 main_loop(); 44} 45 46int load(){ 47 48 //ALLEGRO E ADDONS 49 if(!al_init()) 50 { 51 printf("Problema ao iniciar Allegro."); 52 return 0; 53 } 54 55 56 if(!al_init_image_addon()) 57 { 58 printf("Problema ao iniciar Addon de imagem do Allegro."); 59 return 0; 60 } 61 62 if(!al_init_primitives_addon()) 63 { 64 printf("Problema ao iniciar Addon de primitivas do Allegro."); 65 return 0; 66 } 67 68 if(!al_install_keyboard()) 69 { 70 printf("Problema ao instalar teclado."); 71 return 0; 72 } 73 74 //FULL SCREEN 75 //al_set_new_display_flags(ALLEGRO_FULLSCREEN); 76 display = al_create_display(WIDTH, HEIGHT); 77 78 if(!display) 79 { 80 printf("Problema ao criar janela do Allegro."); 81 return 0; 82 } 83 84 85 timer_fps = al_create_timer(1.0 / FPS); 86 timer_lps = al_create_timer(1.0 / LPS); 87 al_set_window_title(display, GAME_NAME); 88 89 eventqueue = al_create_event_queue(); 90 al_register_event_source(eventqueue, al_get_timer_event_source(timer_fps)); 91 al_register_event_source(eventqueue, al_get_timer_event_source(timer_lps)); 92 al_register_event_source(eventqueue, al_get_keyboard_event_source()); 93 94 al_start_timer(timer_fps); 95 al_start_timer(timer_lps); 96 map = al_load_bitmap("mapa.bmp"); 97 //--- 98 99 if(!mapa.load("mapa.bmp",WIDTH, HEIGHT)) 100 return 0; 101 102 return 1; 103} 104 105void main_loop(){ 106 while(play){ 107 if(need_redraw){ 108 repaint(); 109 need_redraw = false; 110 } 111 112 if(need_update){ 113 update(); 114 need_update = false; 115 } 116 events(); 117 } 118 119} 120 121void events(){ 122 al_wait_for_event(eventqueue, &evento); 123 if(evento.type == ALLEGRO_EVENT_KEY_DOWN){ 124 if(evento.keyboard.keycode == ALLEGRO_KEY_ESCAPE) 125 quit(); 126 if(evento.keyboard.keycode == ALLEGRO_KEY_UP) 127 keys[ALLEGRO_KEY_UP] = true; 128 if(evento.keyboard.keycode == ALLEGRO_KEY_DOWN) 129 keys[ALLEGRO_KEY_DOWN] = true; 130 if(evento.keyboard.keycode == ALLEGRO_KEY_LEFT) 131 keys[ALLEGRO_KEY_LEFT] = true; 132 if(evento.keyboard.keycode == ALLEGRO_KEY_RIGHT) 133 keys[ALLEGRO_KEY_RIGHT] = true; 134 135 }else if(evento.type == ALLEGRO_EVENT_KEY_UP){ 136 if(evento.keyboard.keycode == ALLEGRO_KEY_UP) 137 keys[ALLEGRO_KEY_UP] = false; 138 if(evento.keyboard.keycode == ALLEGRO_KEY_DOWN) 139 keys[ALLEGRO_KEY_DOWN] = false; 140 if(evento.keyboard.keycode == ALLEGRO_KEY_LEFT) 141 keys[ALLEGRO_KEY_LEFT] = false; 142 if(evento.keyboard.keycode == ALLEGRO_KEY_RIGHT) 143 keys[ALLEGRO_KEY_RIGHT] = false; 144 145 }else if(evento.timer.source == timer_fps){ 146 need_redraw = true; 147 }else if(evento.timer.source == timer_lps){ 148 need_update= true; 149 } 150} 151 152void update(){ 153 mapa.update(keys); 154} 155 156void repaint(){ 157 al_clear_to_color(WHITE); 158 mapa.draw(); 159 al_flip_display(); 160} 161 162void quit(){ 163 play = false; 164 al_destroy_display(display); 165 al_destroy_timer(timer_fps); 166 al_destroy_timer(timer_lps); 167 al_destroy_event_queue(eventqueue); 168}

map class:

#SelectExpand
1#include "map.h" 2map::map(void) 3{ 4} 5map::~map(void) 6{ 7} 8 9int map::load(const char *file_name, int window_width, int window_height) 10{ 11 xx = 0.0; 12 13 al_init_image_addon(); 14 file = al_load_bitmap(file_name); 15 if(!file){ 16 printf("\nFalha ao ler arquivo %s", file_name); 17 return 0; 18 } 19 width = al_get_bitmap_width(file); 20 height = al_get_bitmap_height(file); 21 22 //todos tiles do mapa 23 //all_tiles = new tile[width * height]; 24 25 //carrega o tileset - imagem / tamanho do tile 26 if(!tile_set.load("tileset.jpg", 32)) 27 return 0; 28 29 tiles_to_show_x = window_width / tile_set.get_tile_size(); 30 tiles_to_show_y = window_height / tile_set.get_tile_size(); 31 32 ALLEGRO_COLOR color; 33 34 tile *tl; 35 36 for(int r = 0 ; r < height ; r++) 37 { 38 for(int c = 0 ; c < width ; c++) 39 { 40 color = al_get_pixel(file, c, r); 41 42 if(color_to_tile(color) == 0) 43 continue; 44 45 int index = r * width + c; 46 tl = new tile(); 47 48 tl->set_x(c * tile_set.get_tile_size()); 49 tl->set_y(r * tile_set.get_tile_size()); 50 tl->set_w(tile_set.get_tile_size()); 51 tl->set_h(tile_set.get_tile_size()); 52 tl->set_tile_index(color_to_tile(color)); 53 tl->set_image(tile_set.get_tile(tl->get_tile_index())); 54 } 55 } 56 printf("%d tiles carregados.",tile::all_tiles.size()); 57 al_destroy_bitmap(file); 58 return 1; 59} 60 61void map::draw(){ 62 for(int i = 0 ; i < (int) tile::all_tiles.size() ; i++) 63 tile::all_tiles.at(i)->draw(); 64} 65 66void map::update(bool keys[]){ 67 for(int i = 0 ; i < (int) tile::all_tiles.size() ; i++) 68 tile::all_tiles.at(i)->update(keys); 69} 70 71int map::color_to_tile(ALLEGRO_COLOR color){ 72 73 int index; 74 75 if(compare_color(color, BLACK)) 76 index = 1; 77 else if(compare_color(color, RED)) 78 index = 2; 79 else if(compare_color(color, GREEN)) 80 index = 3; 81 else if(compare_color(color, BLUE)) 82 index = 4; 83 else if(compare_color(color, YELLOW)) 84 index = 5; 85 else if(compare_color(color, MAGENTA)) 86 index = 6; 87 else if(compare_color(color, CYAN)) 88 index = 7; 89 else 90 index = 0; 91 return index; 92} 93 94bool map::compare_color(ALLEGRO_COLOR color1, ALLEGRO_COLOR color2){ 95 return (color1.r == color2.r) && (color1.g == color2.g) && (color1.b == color2.b); 96}

tileset class:

#SelectExpand
1#include "tileset.h" 2 3tileset::tileset(){} 4tileset::~tileset(){} 5int tileset::load(const char *file, int ts) 6{ 7 tile_size = ts; 8 al_init_image_addon(); 9 image = al_load_bitmap(file); 10 11 if(!image){ 12 printf("\nFalha ao ler tileset %s", file); 13 return 0; 14 } 15 16 width = al_get_bitmap_width(image); 17 height = al_get_bitmap_height(image); 18 19 //caso o tileset nao seja multiplo do tamanho de seus tiles 20 if((width % tile_size != 0) | (height % tile_size != 0)){ 21 printf("\nTileset nao compativel com o tamanho dos tiles."); 22 return 0; 23 } 24 number_tiles = width / height; 25 26 tiles_x = width / tile_size; 27 tiles_y = height / tile_size; 28 29 sub_tiles = new ALLEGRO_BITMAP*[tiles_x * tiles_y]; 30 31 for(int r = 0 ; r < tiles_y ; r++) 32 for(int c = 0 ; c < tiles_x ; c++) 33 sub_tiles[r * tiles_x + c + 1] = al_create_sub_bitmap(image, c * tile_size, r * tile_size, tile_size, tile_size); 34 35 return 1; 36 37} 38int tileset::get_tile_size(){ 39 return tile_size; 40} 41ALLEGRO_BITMAP * tileset::get_tile(int index){ 42 return sub_tiles[index]; 43}

tile class:

#SelectExpand
1#include "tile.h" 2 3std::vector<tile*> tile::all_tiles; 4 5tile::tile(){ 6 all_tiles.push_back(this); 7} 8tile::~tile(){ 9} 10int tile::get_tile_index() 11{ 12 return tile_index; 13} 14bool tile::is_solid() 15{ 16 return solid; 17} 18 19ALLEGRO_BITMAP * tile::get_image() 20{ 21 return image; 22} 23void tile::set_tile_index(int index) 24{ 25 tile_index = index; 26} 27 28void tile::set_solid(bool state) 29{ 30 solid = state; 31} 32void tile::set_image(ALLEGRO_BITMAP * img) 33{ 34 image = img; 35} 36void tile::draw(){ 37 al_draw_bitmap(image,get_x(),get_y(),0); 38} 39void tile::update(bool keys[]){ 40 if(keys[ALLEGRO_KEY_RIGHT]) 41 set_x(get_x() + 5); 42}

It is all.

Arthur Kalliokoski

That video looks like a vsync problem to me. The display is updated while the monitor is halfway through showing the previous frame. Try this before creating the display:

  al_set_new_display_option(ALLEGRO_VSYNC, 1, ALLEGRO_SUGGEST);

and if that doesn't work, there should be a setting in your graphics utility to allow programs to set vsync/flipping and not override it.

kuarcke

al_set_new_display_option (ALLEGRO_VSYNC, 1, ALLEGRO_SUGGEST); worked, the tiles are perfect now, but the game is too slow, the controls are coming with 1 sec delay ???;

Arthur Kalliokoski

Try adjusting your timer values.

kuarcke

Tips? because they seem ok to me.

taronĀ 

Check if your event queue is empty before drawing, that should solve the input delay.

Arthur Kalliokoski

I was thinking that somehow the timer would cause a delay after the vsync or something, so it'd have two delays, one for the vsync and one for the timer itself. If you sped up the timer a bit so it'd always ask for a redraw before a vsync kicked in, then it'd work better I'd think.

kuarcke

It worked guys, is perfect right now with vsync!
I did so:

while (!al_event_queue_is_empty(eventqueue))
{
  al_wait_for_event(eventqueue, & event);
  if (evento.type == ALLEGRO_EVENT_KEY_DOWN)
  {
    //do something ...
  }
}

Many thanks for the help.

Thread #614804. Printed from Allegro.cc