I'm student and I just finished my 2nd year in computer engineering and I'm working for my teacher for the summer and one of the task he gave me was to port a game from Allegro 4.4 to Allegro 5.0. He don't know anything about Allegro and the person who code the game (let's call him John) left so I have no reference at all. The game is 4 automated robot fighting with lasers and missiles and the student have to code their behaviour using C. As of now I think I did everything right using Allegro 4.4 and Allegro 5.0 User guide but there is some question I have that I can't seem to find any answer so I'll ask them here.
First : timers
In Allegro 4.4 John use LOCK_VARIABLE and LOCK_FUNCTION which from what I understand are needed in Allegro 4.4 for timers and are not used in Allegro 5.0 anymore. He also use install_int_ex function.
My question is : Do install_int_ex do the same thing as al_create_timer(timerName)? What does the LOCK function did in Allegro 4.4?
Here is the code:
Second : floodfill
Floodfill was a function in Allegro 4.4 that did the same thing the fill bucket do in MSpaint.
floodfill(BITMAP targetBitmap, int x, int y, int color);
I did find a solution on the forum but the person told that it use alot of memory to draw pixel by pixel on a BITMAP.
My question : Is there any way to implement this function without using too much memory?
Third and last : do_line
This one is trickier. This function calculate all the point on a line and do a function along this line. In the game this is use to check if there is a something along a line sensor. If so the line stop at the first pixel it encounter that is not the background color.
void do_line(BITMAP *bmp, int x1, y1, x2, y2, int d, void (*proc)(BITMAP *bmp, int x, int y, int d));
My question : Is there a way to do this? If not how should I do it using a minimum of memory.
*Sorry for my English.
First : timers
In Allegro 4.4 John use LOCK_VARIABLE and LOCK_FUNCTION which from what I understand are needed in Allegro 4.4 for timers and are not used in Allegro 5.0 anymore. He also use install_int_ex function.
My question is : Do install_int_ex do the same thing as al_create_timer(timerName)? What does the LOCK function did in Allegro 4.4?
You don't need to worry about locking any functions or data with Allegro 5, unless you're working with bitmap data directly, but there are functions for that.
install_int_ex doesn't do the same thing as al_create_timer. It installs a call back function that gets called every time the timer ticks. You can do the same thing in allegro 5 by doing this :
al_register_event_queue(queue , al_get_timer_event_source(timer); //... ALLEGRO_EVENT ev; al_wait_for_event(queue , &ev); if (ev.type == ALLEGRO_EVENT_TIMER) { /// Put the code from install_int_ex inside here for the same effect /// Eg... /// ++count; }
Third and last : do_line
This one is harder but can still be done using al_draw_soft_line. I can't give you the exact details though.
Thank you! That help a lot for the timer.
Check out these for some differences between the two library versions:
https://wiki.allegro.cc/index.php?title=Porting_from_A4_to_A5
https://www.allegro.cc/forums/thread/610896/964091
http://stackoverflow.com/questions/6418757/porting-allegro-4-to-allegro-5
I'm not sure if this is helpful, or rambling and confusing, so if the latter, feel free to disregard:
Basically, in Allegro 4, everything was double buffered (draw everything to a memory bitmap, and then when you're entirely done, blit that to the screen at the right time with vsync so it doesn't flicker) or page flipped. (Rare, everything is in video memory and VRAM-to-VRAM copied to a off-screen page of VRAM. Then when ready, change the videocard's "screen" to point to that new page. It uses two pages, and they are flipped between each other.)
I believe Allegro 5 is page flipped because modern Direct3D and OpenGL do that. Allegro is a thin layer over those. Whereas Allegro 4 had to "re-invent the wheel" with specific routines for everything because in general, there were no frameworks for that.
There are two ways to do things:
The old way, you either used double buffering (everyhthing was kept locally in RAM), or page flipping (everything in VRAM so it's hardware accelerated 2-D if the card supports it.).
The new way goes through OpenGL/DirectX, which then go through the native graphics driver. So instead of fiddling with registers, you're calling API's which call driver API's which say "draw this please." Everything is in a texture, and Allegro bitmaps are tied to textures with some additional helper information around them.
[This paragraph can be skipped:]
The new way also has the "Fixed/Classic Pipeline" (~1995-2005) vs "Modern Pipeline" (~2005 onward). Classic pipeline used to be faster because it was set-in-stone. Shaders were for special things, and the fixed pipeline did everything else like vertex transformation. The modern pipeline let you (and forced you!) to use shaders for everything. Without a shader, you don't get anything on the screen. These days, the fixed pipeline forces the card into compatibility mode. It's slower, but still 1000's of times faster than your traditional old videocards. IIRC, Allegro normally runs in fixed mode, and that's fine for 2-D games. But if you go on, you'll want to look into the details of this.
They already mentioned that A4 used timers, A5 uses event queues.
Allegro 5 uses event queues for everything. They're not too hard, but they're different, so read up on them. You're just running an event handler that checks if any events are on the event queue, and if so, it deals with them. That's it. But if you're careful, you can still structure a game like Allegro 4 without an event handler, so it should be relatively easy to port an A4 game to A5 without ripping out the core logic.
[edit]
My question : Is there a way to do this? If not how should I do it using a minimum of memory.
I don't recall the solution to your problem off-the-top of my head, but don't worry about using "minimum amounts of memory." Memory is cheap. Super cheap. Use whatever solution makes sense. It's unlikely you'll be wasting too much memory.
*Sorry for my English.
Don't worry about it. I definitely had far worse English when I started here.
For an event source of a timer, do I have to clear the event queue after a tick or is every tick a new event?
I just don't understand when to clear my event queue or not.
Also, I don't want the whole game to wait for that timer (I guess, still not sure about that). Is there a way to store the present event into ALLEGRO_EVENT ev; without stopping the program and wait for it?
For an event source of a timer, do I have to clear the event queue after a tick or is every tick a new event?
No, when you call al_wait_for_event or you call al_get_next_event and it returns true, then the event is taken off the queue. So every tick is a new event, and it ticks at the rate you set with al_create_timer.
Also, I don't want the whole game to wait for that timer (I guess, still not sure about that). Is there a way to store the present event into ALLEGRO_EVENT ev; without stopping the program and wait for it?
Yes, see al_get_next_event or al_wait_for_event_timed or al_wait_for_event_until.
Typically the input loop looks like this :
Ok so I think I understand.
In the example Edgar mentioned with the input loop, you have the if(redraw) loop that redraw the whole scene every time the while start. Does that make it the FPS of my program?
Because as I say earlier, that was code using Allegro 4.4 and I think all the structure of the program is now wrong because of it. So should I try to match the example or should I just keep it as it is?
This is my main and the action is in the Fight(); function.
At the moment I have an event queue for my graphic when I draw everything and I have another one where I use the timer and my keyboard input.
What does the Fight() function look like? I'm not sure how you want to do it without seeing that first. Isn't there a loop somewhere?
That's the whole Fight function. It's where everything happens except for initializing/de-initializing everything.
The main difference I see with your example is that I draw everything at the end of my loop inside Fight().
Allegro 5 is event based. You need to check for events inside a loop, because they will keep coming. You can't just check for an event once, and then expect it to change.
Also, you need to make sure the event type matches the data you are trying to get out of it.
Ie.
// This loop will check for all current events while (al_get_next_event(queue , &ev) { if (ev.type == ALLEGRO_EVENT_KEY_DOWN) { // Now it's okay to access the keyboard member, because we know it's a keyboard event if (ev.keyboard.keycode == ALLEGRO_KEY_R) { // do stuff } } }
That will also spin the loop needlessly.
I realize that. I'm just trying to explain the basics of using a loop to process all the events. If you look at my earlier example it uses al_wait_for_event. He didn't seem to fully grasp that model yet so I tried to use a simpler version to explain things. That's all.