![]() |
|
Porting from Allegro 4.4 to 5.0 |
Francis Langlais
Member #15,985
June 2015
|
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: 1volatile int calcCounter = 0;
2volatile int calcsCompleted = 0, cps = 0;
3volatile int frameCounter = 0, fps = 0;
4
5void FPSTimer(void) {
6 fps = frameCounter;
7 frameCounter = 0;
8 cps = calcsCompleted;
9 calcsCompleted = 0;
10}
11
12void AddCalc(void) {
13 calcCounter++;
14}
15 LOCK_VARIABLE(calcCounter);
16 LOCK_VARIABLE(calcsCompleted);
17 LOCK_VARIABLE(cps);
18 LOCK_VARIABLE(frameCounter);
19 LOCK_FUNCTION(fps);
20 LOCK_FUNCTION(AddCalc);
21
22 if (install_int_ex(AddCalc, BPS_TO_TIMER(CALCS_PER_SEC)) != 0)
23 AbortOnError(
24 "Fight() failed to create calcs timer.\nProgram will exit.");
25
26 if (install_int_ex(FPSTimer, SECS_TO_TIMER(1)) != 0)
27 AbortOnError("Fight() failed to create FPS timer.\nProgram will exit.");
Second : floodfill Floodfill was a function in Allegro 4.4 that did the same thing the fill bucket do in MSpaint. 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. 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. |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
Francis Langlais said: 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; }
Quote: 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. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Francis Langlais
Member #15,985
June 2015
|
Thank you! That help a lot for the timer. |
Chris Katko
Member #1,881
January 2002
![]() |
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:] 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] Francis Langlais said: 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. Quote: *Sorry for my English. Don't worry about it. I definitely had far worse English when I started here. -----sig: |
Francis Langlais
Member #15,985
June 2015
|
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? |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
Francis Langlais said: 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. Quote: 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 : 1ALLEGRO_EVENT_QUEUE* queue = al_create_event_queue();
2if (!queue) {return 1;}
3al_register_event_source(queue , al_get_keyboard_event_source());
4al_register_event_source(queue , al_get_mouse_event_source());
5al_register_event_source(queue , al_get_display_event_source(display));
6al_register_event_source(queue , al_get_timer_event_source(timer));
7
8// Input loop
9while (!quit) {
10 if (redraw) {
11 // redraw
12 al_flip_display();
13 redraw = false;
14 }
15
16 do {
17 ALLEGRO_EVENT ev;
18 al_wait_for_event(queue , &ev);
19 if (ev.type == ALLEGRO_EVENT_TIMER) {
20 // do some timed action
21 redraw = true;
22 }
23 if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
24 quit = true;
25 break;
26 }
27 } while (!al_is_event_queue_empty(queue));
28}
My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Francis Langlais
Member #15,985
June 2015
|
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? 1int main(int argc, char *argv[]) {
2 ROBOTCOLORS colours[4] = { ROBOT_RED, ROBOT_GREEN, ROBOT_YELLOW,
3 ROBOT_PURPLE };
4 int cnt;
5
6 ProcessCommandLine(argc, argv);
7 InitCompetition();
8
9 for (cnt = 0; cnt < numInCompetition; cnt++) {
10 (*fpREG[registeredRobots[cnt]])(colours[cnt]);
11 }
12
13 Fight();
14 EndCompetition();
15
16 return EXIT_SUCCESS;
17}
This is my main and the action is in the Fight(); function. |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
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? My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Francis Langlais
Member #15,985
June 2015
|
1void Fight() {
2 int calcsUntilOrders = 0;
3 char systemMessage[255] = "";
4 ROBOT *robot;
5
6 ALLEGRO_EVENT_QUEUE *event_queue = NULL;
7 ALLEGRO_EVENT event;
8 ALLEGRO_TIMER *FramePerSecondTimer;
9 ALLEGRO_TIMER *AddCalcTimer;
10
11 AddCalcTimer = al_create_timer(1 / 60);
12 FramePerSecondTimer = al_create_timer(1);
13 event_queue = al_create_event_queue();
14 al_register_event_source(event_queue, al_get_keyboard_event_source());
15 al_register_event_source(event_queue,
16 al_get_timer_event_source(FramePerSecondTimer));
17 al_register_event_source(event_queue,
18 al_get_timer_event_source(AddCalcTimer));
19
20 al_get_next_event(event_queue, &event);
21 if (event.timer.source == AddCalcTimer) {
22 AddCalc();
23 }
24
25 if (event.timer.source == FramePerSecondTimer) {
26 FPSTimer();
27 }
28
29 while (event.keyboard.keycode != ALLEGRO_KEY_SPACE)
30 ; //Wait for screen to initialize before starting.
31
32 theGame.state = GS_FIGHTING;
33
34 while (event.keyboard.keycode != ALLEGRO_KEY_ESCAPE) {
35
36 if (event.type == ALLEGRO_EVENT_KEY_DOWN) //Check for relevant keys.
37 {
38 if (event.keyboard.keycode == 'r' || event.keyboard.keycode == 'R') //User wants re-randomized loc's.
39 ForeachLL_M(robotList, robot)
40 {
41 ChooseRandomLocation(robot);
42 robot->heading = GetRandomNumber(360);
43 }
44 }
45
46 while (calcCounter) {
47 calcCounter--;
48 calcsUntilOrders++;
49
50 UpdateEnergySystems(robotList); //Do first so we know what
51 //systems are powered.
52 MoveRobots(robotList);
53 DrawRobotBitmaps(robotList);
54 CheckRobotCollisions(&theGame, robotList);
55
56 MoveWeapons(weaponList);
57 CheckWeaponCollisions(&theGame, robotList, weaponList);
58
59 //Now that collisions are
60 ApplyDamage(&theGame, robotList, deadRobotList); //done and weapons have
61 //hit, we apply damage.
62
63 DrawSensorBitmaps(robotList); //Need to draw BEFORE data is
64 //updated because bimaps are
65 //used in collision detection.
66 UpdateSensorData(robotList);
67
68 UpdateParticles();
69
70 calcsCompleted++;
71
72 if (calcsUntilOrders == ORDER_FREQ) {
73 calcsUntilOrders = 0;
74 ForeachLL_M(robotList, curRobot)
75 curRobot->ActionsFunction(TURN_TIME);
76 }
77
78 if (theGame.useSounds)
79 PlaySounds(&theGame);
80
81 }
82
83 sprintf(systemMessage, "FPS: %d CPS: %d", fps, cps);
84 RenderScene(robotList, deadRobotList, weaponList, systemMessage);
85 frameCounter++;
86 }
87}
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(). |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
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 } } }
My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Thomas Fjellstrom
Member #476
June 2000
![]() |
That will also spin the loop needlessly. -- |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
I realize that. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|