Hello all, I have questions regarding multithreading. I’ve tried for quite a while now to get a loading screen set-up. I think I’m really close to getting it to work but I can’t figure out what’s going wrong.
My idea for how it should work conceptually is like so:
Make a thread that will:
sit idle till i need it
deletes the old map
loads the new one
changes the player's stats as needed (loacation, etc...)
repeat
while my main simply takes care of all the normal stuff: updating animations, drawing, input, etc...
My code mostly works. When my character enters a new area for the first time, the loading screen is displayed and the animation runs smoothly. When it’s done loading the new map is displayed but my game becomes extremely laggy and jumpy. My FPS counter stays at around 90, when I have it set to run at 60. When i attempt to move my character back through the door he came in the screen goes black and no animation is displayed. But the map does load and I can walk around but the game is still extremely laggy. When I attempt to go back through the door the loading screen shows, and plays smoothly.
I’ve tried a lot of different things but I cannot figure this one out. Here’s the thread related code I have currently:
NOTE: I am using mappy to handle all the map loading stuff.
NOTE: The lines of "......." in my code are simply areas of code that I deleted.
If anyone would like to see any other parts of my code, ask. I hope there's just a stupid thing that missed in there. If anyone see's any potential logic errors in my code please tell me.
also, I'm new to this multithreading stuff, so any pointers/tips with using them are welcomed.
Thanks for any and all help,
-Ryan
You can't access graphics stuff from two threads at the same time, or without releasing the display from one thread and claiming it in the other. I've never tried this with Direct3D so I don't know if it works there, but you can do something like:
thread 1
al_set_target_bitmap(NULL); // release context // signal other thread it's ok to grab context
thread 2
// receive signal from thread 1 al_set_target_bitmap(some_bitmap_or_backbuffer);
Then when you're done do it in reverse.
But the problem here is, it may be pointless. If thread 1 can't do anything (drawing) while thread 2 is loading the level, it's not going to give you a speed boost and will just complicate your code. That may not be the case for you though, I don't know... threading is just pointless when both threads can't execute at the same time.
If LoadMap is creating ALLEGRO_BITMAP's and passing them to the main thread then that will cause the game to slow down a lot during rendering. Make sure you convert memory bitmaps to video on the main thread where you render stuff.
You can use al_convert_bitmap as long as the new bitmap flags are set up properly (the default is ok).
if (al_get_bitmap_flags(b) & ALLEGRO_MEMORY_BITMAP){ al_convert_bitmap(b); }
Converting to memory to video bitmap is relatively fast and only needs to be done once.
@kazzmir: Seems like that might be what's causing me problems. I'll check it out when i get home tonight. Thank you for pointing that out to me.
-Ryan
I see now that my post doesn't have enough context, so for anyone else reading if you create an ALLEGRO_BITMAP in a thread that doesn't have a context set (because the target bitmap is NULL) then Allegro will create a memory bitmap by default.
Bitmaps created in threads that have a target bitmap set with a display will generally create a video bitmap (although you can change this by setting the new bitmap flags).
Sorry for the late reply (got caught up with family stuff last night). I just did some checks in my code and it turns out that the bitmaps that it is drawing after the first loading sequence are indeed memory bitmaps.
Now my problem is how do I convert them to video bitmaps? I'm using Allegro 5.0.5 at the moment. And it looks like the al_convert_bitmap(); feature is only in version 5.1. Any advice? Should I just switch to using 5.1? I'm not too deep into this project so switching now would be the best time, I think.
I think you can just call al_clone_bitmap then and destroy the old one.
ALLEGRO_BITMAP* video = al_clone_bitmap(b); al_destroy_bitmap(b); b = video;
@kazzmir: THANK YOU SO MUCH! That completely took away the lag/unresponsive problem. I've never needed to convert bitmaps before so that was new to me. Thank you for explaining the converting process.
I've got a new problem now but I'll try to hammer that out on my own.
Thanks again,
-Ryan
Yes the difference between video and memory bitmaps was the most painful thing I had to get accustomed to when using A5.
You can read more about my experience here: http://www.allegro.cc/forums/thread/607477
@kazzmir: That was a good read, thanks. I feel I'm starting to understand this converting stuff a lot better now.
-Ryan