Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » A5 threads - is it what I need ?

This thread is locked; no one can reply to it. rss feed Print
A5 threads - is it what I need ?
William Labbett
Member #4,486
March 2004
avatar

hi Guys,

I've got some code which uses three bitmaps and scrolls them past the screen from bottom to top.

A maximum of two of these bitmaps have parts which get drawn to the screen at any one time. The third one hangs in waiting. A time comes when one of bitmaps needs to be remade (by a function that uses random numbers to make all the bitmaps). When a bitmap has scrolled all the way past the screen - it gets remade. The thing is, when the bitmap is being remade the scrolling jerks becaise it takes time to make.

I thought perhaps I could use an ALLEGRO_THREAD to start making the bitmap at the earliest moment so it's ready when it's needed.

Is this possible ? Am I thinking along the right lines ?

I've no idea how to do it. I've looked at the example on the wiki but don't understand it.

Any help for this would be greatly appreciated.

Matthew Leverton
Supreme Loser
January 1999
avatar

It sounds like you could use a thread. Something like this should get you started:

#SelectExpand
1void *make_bitmap(ALLEGRO_THREAD *me, void *data) 2{ 3 ALLEGRO_BITMAP *bmp = (ALLEGRO_BITMAP *) data; 4 // al_lock_bitmap() 5 // draw on bitmap 6 // al_unlock_bitmap() 7 return NULL; 8} 9 10// when it's okay to build the bitmap: 11ALLEGRO_BITMAP *bmp = al_create_bitmap(640,480); 12ALLEGRO_THREAD *t = al_create_thread(make_bitmap, bmp); 13al_start_thread(t); 14 15// when you need the bitmap: 16al_join_thread(t, NULL); // hopefully the bitmap is already created by now. if not, it will wait for the thread to end 17al_draw_bitmap(bmp, 0,0, 0);

If your "make_bitmap" needs more than one parameter, then you could create a struct and pass that instead:

typedef struct MAKE_BMP_ARGS {
  ALLEGRO_BITMAP *bmp;
  int param1;
} MAKE_BMP_ARGS;

MAKE_BMP_ARGS args;
args.bmp = bmp;
args.param1 = foo;

ALLEGRO_THREAD *t = al_create_thread(make_bitmap, args);

William Labbett
Member #4,486
March 2004
avatar

Thanks Matthew.

If I use a class method for the function pointer can I use class member variables or should do what you said and use a struct ?

Matthew Leverton
Supreme Loser
January 1999
avatar

You won't be able to use a class method directly, unless it's static. You could do something like this instead:

void *make_bitmap(ALLEGRO_THREAD *me, void *data)
{
  MyClass *obj  = (MyClass *) data;
  obj->doSomething();
  return NULL;
}

MyClass *obj = new MyClass();
obj->bmp = bmp;
ALLEGRO_THREAD *t = al_create_thread(make_bitmap, obj);

You could turn make_bitmap into a static method of the class, but it would still need to work like the above example.

Edgar Reynaldo
Member #8,592
May 2007
avatar

William Labbett
Member #4,486
March 2004
avatar

Thanks. I can't quite see how to do it yet (unless I go the struct way).

Here's the method :-

#SelectExpand
1 2void Backdrop::Update_Position(void) 3{ 4 5 ALLEGRO_THREAD *t; 6 7 ++bottom_backdrop_draw_from; 8 9 if(bottom_backdrop_draw_from > BACKDROP_HEIGHT_IN_PIXELS) 10 { 11 12 13 bottom_backdrop_draw_from = 0; 14 15 dinkle_set_up_tiles(); 16 17 switch(current_bottom_backdrop) 18 { 19 case 0: 20 21 b1 = dinkle_get_connecting_blot(backdrop_width, backdrop_height, &ratios, b3_tiles, b1_tiles, bg_colors[0], bg_colors[1]); 22 break; 23 case 1: 24 b2 = dinkle_get_connecting_blot(backdrop_width, backdrop_height, &ratios, b1_tiles, b2_tiles, bg_colors[0], bg_colors[1]); 25 break; 26 case 2: 27 b3 = dinkle_get_connecting_blot(backdrop_width, backdrop_height, &ratios, b2_tiles, b3_tiles, bg_colors[0], bg_colors[1]); 28 break; 29 } 30 31 dinkle_free_tiles(); 32 33 ++current_bottom_backdrop; 34 if(current_bottom_backdrop > 2) current_bottom_backdrop = 0; 35 } 36 37 38}

What I need to happen in the thread is one of the three lines like this :-

b1 = dinkle_get_connecting_blot(backdrop_width, backdrop_height, &ratios, b3_tiles, b1_tiles, bg_colors[0], bg_colors[1]);

b1 is a member of Backdrop as are all the arguments to dinkle_get_connecting_blot().

Matthew Leverton
Supreme Loser
January 1999
avatar

What calls Backdrop::Update_Position? Is that the single function that is slowing everything down?

If so, then take my example and call ->Update_Position() on the void * argument that the thread function gets.

William Labbett
Member #4,486
March 2004
avatar

Thanks again guys. I've gone for Matthews way as I understand it.

I've made some progress - here's what I've got. Something's going wrong though I think because the Update function is taking less time now - I'm not sure the thread finishes before another one starts.

#SelectExpand
1void Backdrop::Update_Position(void) 2{ 3 ++bottom_backdrop_draw_from; 4 5 if(bottom_backdrop_draw_from > BACKDROP_HEIGHT_IN_PIXELS) 6 { 7 bottom_backdrop_draw_from = 0; 8 9 ALLEGRO_THREAD *t; 10 11 t = al_create_thread(make_bitmap, this); 12 al_start_thread(t); 13 14 ++current_bottom_backdrop; 15 if(current_bottom_backdrop > 2) current_bottom_backdrop = 0; 16 } 17 18 19} 20 21 22 23void Backdrop::Make_New_Blot() 24{ 25 dinkle_set_up_tiles(); 26 27 switch(current_bottom_backdrop) 28 { 29 case 0: 30 b1 = dinkle_get_connecting_blot(backdrop_width, backdrop_height, &ratios, b3_tiles, b1_tiles, bg_colors[0], bg_colors[1]); 31 break; 32 case 1: 33 b2 = dinkle_get_connecting_blot(backdrop_width, backdrop_height, &ratios, b1_tiles, b2_tiles, bg_colors[0], bg_colors[1]); 34 break; 35 case 2: 36 b3 = dinkle_get_connecting_blot(backdrop_width, backdrop_height, &ratios, b2_tiles, b3_tiles, bg_colors[0], bg_colors[1]); 37 break; 38 } 39 40 dinkle_free_tiles(); 41 42 43 44} 45 46 47 48 49 50void *make_bitmap(ALLEGRO_THREAD *t, void *data) 51{ 52 Backdrop *obj = (Backdrop *) data; 53 54 obj->Make_New_Blot(); 55 56 return NULL; 57}

EDIT : I put an al_join_thread in there but the problem's still there so it's something else.

Edgar Reynaldo
Member #8,592
May 2007
avatar

Matthew Leverton
Supreme Loser
January 1999
avatar

I cannot tell from your code exactly how things are working. For it to be effective, you must let the thread do its thing while you continue on with the other stuff.

For example this does nothing useful, as you are not doing anything in between the start and join:

t = al_create_thread(make_bitmap, this);
al_start_thread(t);
al_join_thread(t, NULL);

Go to: