Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » cpu fps etc...

This thread is locked; no one can reply to it. rss feed Print
 1   2 
cpu fps etc...
karistouf
Member #5,126
October 2004
avatar

hi again.
ok, this is surely once again THE CLASSICAL QUESTIOn about CPU weight and allegro and blablablabla.

I begin without the app:
{"name":"state0.jpg","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/0\/5076464c4a2ed765dbb2a2fdd59a9e3a.jpg","w":511,"h":500,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/0\/5076464c4a2ed765dbb2a2fdd59a9e3a"}state0.jpg

The old version, without any rest(1) nor timer function:
{"name":"schwz3_state.jpg","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/3\/83af845627c7ee305ada2bea96a85b09.jpg","w":992,"h":468,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/3\/83af845627c7ee305ada2bea96a85b09"}schwz3_state.jpg

I have put in my main loop a rest of 1 sec, and putted in volatile funct activated by the timer all my printing to screen.
Notice here that I have only a poor bmp of 32k and less for mouse cursor...

Modification to the program with a rest and timer function, FPS 100:
{"name":"fps100.jpg","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/4\/5\/45dac6f09ba88ffcdcb54dd614e4603a.jpg","w":962,"h":435,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/4\/5\/45dac6f09ba88ffcdcb54dd614e4603a"}fps100.jpg

FPS 50:
{"name":"fps50.jpg","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/d\/ad05f6a1c21056bbebca180a3c788b4b.jpg","w":955,"h":447,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/d\/ad05f6a1c21056bbebca180a3c788b4b"}fps50.jpg

Here is part of the code, I do not arrive to do less to not charge the CPU. Any idea ?

:-[

1////////////////////////////////////////////////////////////////////////////////
2 
3volatile long screen_unit=0;
4void screen_printing(void)
5{
6screen_unit++;
7
8//... mes functions d affichage
9 rectfill(buffer,0,0,440,400,makecol(255,255,255));
10 textprintf_ex(buffer,font, 105,20,makecol(255,0,0),-1,AppliName);//affichage nom appi
11 draw_sprite(buffer,fond1,(int)-5,0);
12
13 if (index_view_graph==1)
14 { rectfill(buffer, 320,350,330,360,makecol(255,0,0));
15 view_midi_visual();
16 }
17
18 if (index_view_midiapps==1)
19 { rectfill(buffer, 150,350,160,360,makecol(255,0,0));
20 listOfAppl();
21 }
22
23
24 if ( index_write_deb==1){
25 rectfill(buffer, 415, 370,425, 380,makecol(255,0,0));
26 }
27
28
29 show_connected_to_midishare();
30 textprintf_ex(buffer,font, 10,200,makecol(255,0,0),-1,"Midi INPUT: ");
31 textprintf_ex(buffer,font, 10,210,makecol(255,0,0),-1,"%s", my_midi_string);
32 
33 show_udp();
34 choices();
35 textprintf_ex(buffer,font, 10,180,makecol(255,0,0),-1,"FPS: %d ", FPS_defini);
36 draw_sprite(buffer,mouse,(int)mouse_x,mouse_y);
37 blit(buffer,screen,0,0,0,0,442,442);
38 
39}
40END_OF_FUNCTION(screen_printing)
41 
42 
43 
44////////////////////////////////////////////////////////////////////////////////
45int main()
46{
47 allegro_init();
48 install_keyboard();
49 install_mouse();
50 install_timer();
51 LOCK_FUNCTION(screen_printing);
52 LOCK_VARIABLE(screen_unit);
53
54 set_color_depth(16);
55 set_gfx_mode(GFX_AUTODETECT_WINDOWED,442,442,0,0);
56 if(set_gfx_mode(GFX_AUTODETECT_WINDOWED,440,400,0,0)!=0)
57 {
58 set_gfx_mode(GFX_TEXT,0,0,0,0);
59 allegro_message("%s\nSchwartz_Peter's Video Mode:\n 1024x768 and Higher\n16 or 32 bits better look\n\n", allegro_error);
60 quit_funct();return 1;
61 }
62 fond1=load_bitmap("chaton2.tga",NULL);
63 mouse=load_bitmap("curseur1.bmp",NULL);
64 
65 buffer=create_bitmap(SCREEN_W,SCREEN_H);
66 blit(buffer,screen,0,0,0,0,442,442);
67 
68 if(set_display_switch_mode(SWITCH_BACKGROUND))
69 {set_display_switch_mode(SWITCH_BACKAMNESIA);}
70
71
72 load_ip_conf();
73 SetUpMidi();
74 
75 initialisation_client();
76 
77 
78 while (index_quit==0)
79 {
80 rest(1);
81 
82 
83
84 install_int_ex(screen_printing,BPS_TO_TIMER(FPS_defini));
85 
86 
87 
88 }
89 
90
91quit_funct();
92 
93 
94
95return 0;
96}
97END_OF_MAIN();

GullRaDriel
Member #3,861
September 2003
avatar

umpf !!!

Chris, n'appelle install_int_ex qu'une seule fois ! et en dehors de la boucle while !

Apres quoi tu pourras boucler sur ton rest(1); tranquillement !

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

bamccaig
Member #7,536
July 2006
avatar

First of all you shouldn't be doing so much work in a timer function. Setting a flag or incrementing a counter and responding to it in the game loop is the preferred (and feasible) approach. I'm not sure why you repeatedly call install_int_ex, but that seems shifty as well...

gnolam
Member #2,030
March 2002
avatar

I'm surprised that doesn't outright crash, what with Allegro's notorious thread unsafety and all.

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

Audric
Member #907
January 2001

You can attempt to rest() for more than 1ms at once.
Try 5, 10, 15, 20.

edit
As for the drawing part, chances are the biggest job for the CPU is the

blit(buffer,screen,0,0,0,0,442,442);

Considering that less than 10% of the screen surface may have changed, you could just blit these parts individually, like a "dirty rectangles" system.

(Additionally, you can memorize if these screen parts HAVE changed at all. For example, the top text: No need to redraw the paragraph if it has the same content as when it was last redrawn.)

Goalie Ca
Member #2,579
July 2002
avatar

-------------
Bah weep granah weep nini bong!

Vanneto
Member #8,643
May 2007

Are there any advantages of using semaphores over normal high-res timers?

In capitalist America bank robs you.

karistouf
Member #5,126
October 2004
avatar

ooooups, i didn t know it was an error, I have an hudge programm wich is running with install_ex inside of the main loop since 4 years of dev... without any error i mean errors of timers (and its real time manipulation)...

but its still doing nothing o my troubles of CPU...
with:

     while (index_quit==0)
     {
     rest(1);
//nothing... but refreshment is done in the volatile as previous and first code

     }

CPU weight is still from 41 % and up to 70%

{"name":"outofloop.jpg","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/3\/032ede2c76a20c40b9e54221cb2392ea.jpg","w":983,"h":510,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/3\/032ede2c76a20c40b9e54221cb2392ea"}outofloop.jpg

so? I mean install_ex is there tomake use of timer in an easy manner, to avoid calculations of tclock ?

GullRaDriel
Member #3,861
September 2003
avatar

install_int* granularity can vary from 1 msec to 14-20 msec

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

Goalie Ca
Member #2,579
July 2002
avatar

Quote:

Are there any advantages of using semaphores over normal high-res timers?

Yay. Someone asked the RIGHT question.

Why did i use a locking semaphore? Because allegro timers spawn their own thread, wake it up, run user code (increment value), and then go back to sleep.

I used a semaphore because i wanted to put the mail loop to sleep and have the timer wake it up like it should happen. You only want your main loop to execute when the timer beeps! Allegro timer simplifies this possibility away but certain operating systems (not all) libraries can handle this without a problem.

Rest is basically a way to stop constant spin locking by taking shifts. It will tell the operating system to put the thread to sleep... but only for a really short time. It then checks again.. whenever the operating system feels like it. It may check almost right away (bad because more cpu wasted) but the general rule of thumb is that rest is only accurate to within 15ms.

To summarize: rest still wastes tons of cpu. It constantly wakes up and goes back to sleep.

With my locking mechanism i can get my own (graphically simple) allegrogl games to use < 1% cpu.

-------------
Bah weep granah weep nini bong!

bamccaig
Member #7,536
July 2006
avatar

That's really cool Goalie Ca, but how portable is it...? :-/ Will your example work on Windows and Linux? :-/ Do you need to install third party libraries or anything?

Goalie Ca
Member #2,579
July 2002
avatar

If your OS is posix then you have it. All linux, mac, and older winnt. For new windows you need to download pthread. http://sourceware.org/pthreads-win32/
If you really wanted to you could use windows locking mechanism. It is in winapi and does the same thing.

-------------
Bah weep granah weep nini bong!

bamccaig
Member #7,536
July 2006
avatar

I guess I will attempt to learn to use semaphores then. :D Until then, here is my revised raw timer template...

1/*
2 * Name: fps.h
3 * Author: bamccaig->members.allegro.cc
4 * Purpose: Example of using Allegro timer routines to limit frames-per-second
5 * in a game.
6 * Disclaimer: Use at own risk. :P
7 */
8#include <allegro.h>
9#include <stdio.h>
10#include <stdlib.h>
11 
12#define bool short int
13#define false 0
14#define true -1
15 
16#define SECS_PER_MIN 60
17#define MINS_PER_HOUR 60
18#define HOURS_PER_DAY 24
19#define TARGET_FPS 30
20#define WHITE makecol(255, 255, 255)
21 
22volatile bool gblnCloseButtonPressed = false; // Flag for window close (X) button status.
23volatile unsigned short int gushrFramesPerSecond = 0; // Count of frames last second (Set).
24volatile unsigned short int gushrFramesThisSecond = 0; // Count of frames this second (Increment).
25volatile unsigned int guintPendingFrames = 0; // Number of frames OK'd to be processed.
26volatile unsigned int guintTotalFrames = 0; // Total number of frames.
27 
28volatile unsigned short int gushrSeconds = 0;
29unsigned short int gushrMinutes = 0;
30unsigned short int gushrHours = 0;
31unsigned short int gushrDays = 0;
32 
33void add_frame(void); // Timer routine.
34void close_button_handler(void); // Window X button handler on supported platforms.
35void draw(BITMAP*); // Draws the scene.
36int initialize(void); // Initializes the application.
37void logic(void); // Processes gameplay.
38void tick(void); // Timer routine.
39void update_time(void); // Updates clock variables.

1/*
2 * Name: fps.c
3 * Author: bamccaig->members.allegro.cc
4 * Purpose: Example of using Allegro timer routines to limit frames-per-second
5 * in a game.
6 * Disclaimer: Use at own risk. :P
7 */
8#include "fps.h"
9 
10int main(int argc, char* argv[])
11{
12 BITMAP* bmpBuffer = NULL;
13 
14 // Try to initialize game.
15 if(initialize() != 0)
16 exit(-1);
17 
18 // Create and clear screen buffer.
19 bmpBuffer = create_bitmap(800, 600);
20 clear(bmpBuffer);
21 
22 // Main game loop.
23 while(!(key[KEY_ESC] || gblnCloseButtonPressed))
24 {
25 // Rest loop. Nothing to do until next frame so we "go to sleep" temporarily.
26 while(!guintPendingFrames)
27 rest(16);
28 
29 // Logic loop. Changes to the game happen here.
30 while(guintPendingFrames)
31 {
32 logic();
33 guintPendingFrames--;
34 }
35 
36 /*
37 * Draw. Here we draw the current frame first to a buffer in main memory and
38 * then to the video memory (screen).
39 */
40 draw(bmpBuffer);
41 }
42 
43 // Release buffer.
44 destroy_bitmap(bmpBuffer);
45 
46 return(0);
47}
48END_OF_MAIN()
49 
50 
51 
52void add_frame(void)
53/*
54 * This is a timer routine that signals the main game loop to execute the logic (and redraw).
55 * Every time it executes it increments a counter. When the counter is non-zero the main game
56 * loop will execute the logic and then decrement the counter. Logic only happens once
57 * for every execution of this timer routine. Drawing happens at most once, but perhaps less
58 * if the program starts to get behind and needs to catch up again by repeating logic.
59 */
60{
61 guintPendingFrames++;
62}
63END_OF_FUNCTION(add_frame)
64 
65 
66 
67void close_button_handler(void)
68/*
69 * Handles the X button of the window on supported platforms. Signals the main game loop
70 * to exit.
71 */
72{
73 gblnCloseButtonPressed = true;
74}
75END_OF_FUNCTION(close_button_callback)
76 
77 
78 
79void draw(BITMAP* bmpBuffer)
80/*
81 * Draws the current frame to a BITMAP buffer in main memory and then to the video memory (screen).
82 * In this example we're only drawing the total frame count and the frames-per-second count.
83 */
84{
85 // Draw to buffer.
86 textprintf_ex(bmpBuffer, font, 20, 20, WHITE, -1, "frame-count: %d", guintTotalFrames);
87 textprintf_ex(bmpBuffer, font, 20, 40, WHITE, -1, "time: %03d:%02d:%02d:%02d", gushrDays, gushrHours, gushrMinutes, gushrSeconds);
88 textprintf_ex(bmpBuffer, font, 20, 60, WHITE, -1, "fps: %d", gushrFramesPerSecond);
89 
90 // Draw to screen.
91 blit(bmpBuffer, screen, 0, 0, 0, 0, 800, 600);
92 clear(bmpBuffer);
93}
94END_OF_FUNCTION(draw)
95 
96 
97 
98int initialize(void)
99// Initializes the program.
100{
101 char* chrGLaDOS_msg = "If at first you don't succeed,...you fail";
102 
103 // Try to initialize allegro.
104 if(allegro_init() != 0)
105 {
106 printf("%s [to initialize Allegro].\n", chrGLaDOS_msg);
107 return(-1);
108 }
109 
110 // Try to install keyboard.
111 if(install_keyboard() != 0)
112 {
113 printf("%s [to install the keyboard routines].\n", chrGLaDOS_msg);
114 return(-1);
115 }
116 
117 // Try to install timer.
118 if(install_timer() != 0)
119 {
120 printf("%s [to install the timer routines].", chrGLaDOS_msg);
121 return(-1);
122 }
123 
124 // Set color depth.
125 set_color_depth(32);
126 
127 // Try to set graphic mode.
128 if(set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0) != 0)
129 {
130 printf("%s [to set the graphics mode]. %s.\n", chrGLaDOS_msg, allegro_error);
131 return(-1);
132 }
133 
134 /*
135 * Set display switch mode so the game will continue processing even if the
136 * user switches to another window.
137 */
138 if(set_display_switch_mode(SWITCH_BACKGROUND) != 0)
139 {
140 printf("%s [to set display switch mode].\n", chrGLaDOS_msg, allegro_error);
141 return(-1);
142 }
143 
144 // Lock timer variables.
145 LOCK_VARIABLE(gblnCloseButtonPressed);
146 LOCK_VARIABLE(guintPendingFrames);
147 LOCK_VARIABLE(gushrFramesPerSecond);
148 LOCK_VARIABLE(gushrFramesThisSecond);
149 LOCK_VARIABLE(gushrSeconds);
150 LOCK_VARIABLE(gushrMinutes);
151 LOCK_VARIABLE(gushrHours);
152 LOCK_VARIABLE(gushrDays);
153 
154 // Lock timer routines.
155 LOCK_FUNCTION(add_frame);
156 LOCK_FUNCTION(close_button_handler);
157 LOCK_FUNCTION(tick);
158 
159 // Install timer callbacks.
160 install_int_ex(add_frame, BPS_TO_TIMER(TARGET_FPS));
161 install_int_ex(tick, BPS_TO_TIMER(1));
162 
163 // Install close-button callback.
164 set_close_button_callback(close_button_handler);
165 
166 return(0);
167}
168END_OF_FUNCTION(initialize)
169 
170 
171 
172void logic(void)
173/*
174 * Logic. In this example we're only incrementing a total frame counter, a
175 * frames-per-second counter, and updating time variables.
176 */
177{
178 update_time();
179 
180 guintTotalFrames++;
181 gushrFramesThisSecond++;
182}
183END_OF_FUNCTION(logic)
184 
185 
186 
187void tick(void)
188/*
189 * This is another timer routine that executes [approximately] once per second.
190 * It's role is to set the frames-per-second count and reset the
191 * frames-this-second counter.
192 */
193{
194 // Update game time.
195 gushrSeconds++;
196 
197 // Update frames per second.
198 gushrFramesPerSecond = gushrFramesThisSecond;
199 gushrFramesThisSecond = 0;
200}
201END_OF_FUNCTION(tick)
202 
203 
204 
205void update_time(void)
206// Updates time variables.
207{
208 if(gushrSeconds == SECS_PER_MIN)
209 {
210 gushrMinutes++;
211 gushrSeconds = 0;
212 }
213 
214 if(gushrMinutes == MINS_PER_HOUR)
215 {
216 gushrHours++;
217 gushrMinutes = 0;
218 }
219 
220 if(gushrHours == HOURS_PER_DAY)
221 {
222 gushrDays++;
223 gushrHours = 0;
224 }
225}

To compile it the following commands should work (you must have Allegro installed).

Windows/MinGW: gcc -O2 fps.c -o fps.exe -lalleg

*nix/GCC: gcc -O2 fps.c -o fps $(allegro-config --libs)

Goalie Ca
Member #2,579
July 2002
avatar

Quote:

I guess I will attempt to learn to use semaphores then.

Simple. A semaphore is like a locking counter. I've pasted the code i wrote to the wiki and have added a few useful comments. Basically main goes to sleep, ticker wakes it up. No wasted cycles, no extra context switches, no spinlocks.

1#include <allegro.h>
2#include <semaphore.h>
3sem_t ticks; //our new "counter" variable.
4 
5 
6void ticker(){
7 sem_post(&ticks); //increases count. wakes up first waiting thread (sem_wait) if count > 0
8}END_OF_FUNCTION(ticker)
9 
10void main(){
11 setup_stuff();
12 
13 sem_init(&ticks, 0, 1); //sets a good default value to count. (count = 1)
14 LOCK_FUNCTION(ticker);
15 install_int_ex(ticker,BPS_TO_TIMER(60));
16 
17 while(game_on){
18 sem_wait(&ticks); //decreases count, goes to sleep if count < 0, wakes back up when count >= 0 (through sem_post)
19 update_stuff();
20 draw_stuff();
21 }
22}END_OF_MAIN()

-------------
Bah weep granah weep nini bong!

karistouf
Member #5,126
October 2004
avatar

OK finally I founded why it was taking so many weight in memory:
im using

   if(set_display_switch_mode(SWITCH_BACKGROUND))
  {set_display_switch_mode(SWITCH_BACKAMNESIA);}

to enable the visual refreshing of information if I m not on its window.
... oups !

Kitty Cat
Member #2,815
October 2002
avatar

Quote:

while(game_on){
    sem_wait(&ticks); //decreases count, goes to sleep if count < 0, wakes back up when count >= 0 (through sem_post)
    update_stuff();
    draw_stuff();
}

If you want to do frameskipping, this should work:

while(game_on){
    sem_wait(&ticks);
    do {
        update_stuff();
    } while(sem_trywait(&ticks) == 0);
    draw_stuff();
}

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

karistouf
Member #5,126
October 2004
avatar

MAOUW its nice, but it need to run , while its not on nor selected.
So in fact putting in an install_ex routines enable not to freeze the tasks, just the screen refreshment is not done ( wich take a HUDGE place in mem)

Thomas Fjellstrom
Member #476
June 2000
avatar

Quote:

I'm surprised that doesn't outright crash, what with Allegro's notorious thread unsafety and all.

A lot of the crashieness was "fixed" in the last release or two. But it means theres a ton of locking and unlocking going on, slowing things down and potentially using lots of cpu. That doesn't mean you should use the same allegro resources from multiple thread (in fact you probably shouldn't), unless you're absolutely sure you know what you're doing.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

bamccaig
Member #7,536
July 2006
avatar

1/*
2 * Name: fps2.h
3 * Author: bamccaig->members.allegro.cc
4 * Purpose: Example of using Allegro timer routines and semaphores to limit frames-per-second
5 * in a game and reduce wasted cycles.
6 * Disclaimer: Use at own risk. :P
7 */
8#include <allegro.h>
9#include <semaphore.h>
10#include <stdio.h>
11#include <stdlib.h>
12 
13#define bool short int
14#define false 0
15#define true -1
16 
17#define SECS_PER_MIN 60
18#define MINS_PER_HOUR 60
19#define HOURS_PER_DAY 24
20#define TARGET_FPS 30
21#define WHITE makecol(255, 255, 255)
22 
23sem_t gSemaphore;
24 
25volatile bool gblnCloseButtonPressed = false; // Flag for window close (X) button status.
26volatile unsigned short int gushrFramesPerSecond = 0; // Count of frames last second (Set).
27volatile unsigned short int gushrFramesThisSecond = 0; // Count of frames this second (Increment).
28volatile unsigned int guintTotalFrames = 0; // Total number of frames.
29 
30volatile unsigned short int gushrSeconds = 0;
31unsigned short int gushrMinutes = 0;
32unsigned short int gushrHours = 0;
33unsigned short int gushrDays = 0;
34 
35void add_frame(void); // Timer routine.
36void close_button_handler(void); // Window X button handler on supported platforms.
37void draw(BITMAP*); // Draws the scene.
38int initialize(void); // Initializes the application.
39void logic(void); // Processes gameplay.
40void tick(void); // Timer routine.
41void update_time(void); // Updates clock variables.

1/*
2 * Name: fps2.c
3 * Author: bamccaig->members.allegro.cc
4 * Purpose: Example of using Allegro timer routines and semaphores to limit frames-per-second
5 * in a game and reduce wasted cycles.
6 * Disclaimer: Use at own risk. :P
7 */
8#include "fps2.h"
9 
10int main(int argc, char* argv[])
11{
12 BITMAP* bmpBuffer = NULL;
13 
14 // Try to initialize game.
15 if(initialize() != 0)
16 exit(-1);
17 
18 // Initalize semaphore.
19 sem_init(&gSemaphore, 0, 1);
20 
21 // Create and clear screen buffer.
22 bmpBuffer = create_bitmap(800, 600);
23 clear(bmpBuffer);
24 
25 // Main game loop.
26 while(!(key[KEY_ESC] || gblnCloseButtonPressed))
27 {
28 // Sleep until next frame.
29 sem_wait(&gSemaphore);
30 
31 // Logic loop. Changes to the game happen here.
32 logic();
33 
34 /*
35 * Draw. Here we draw the current frame first to a buffer in main memory and
36 * then to the video memory (screen).
37 */
38 draw(bmpBuffer);
39 }
40 
41 // Release buffer.
42 destroy_bitmap(bmpBuffer);
43 
44 return(0);
45}
46END_OF_MAIN()
47 
48 
49 
50void add_frame(void)
51/*
52 * This is a timer routine that signals the main game loop to execute the logic (and redraw).
53 */
54{
55 // Wake up game.
56 sem_post(&gSemaphore);
57}
58END_OF_FUNCTION(add_frame)
59 
60 
61 
62void close_button_handler(void)
63/*
64 * Handles the X button of the window on supported platforms. Signals the main game loop
65 * to exit.
66 */
67{
68 gblnCloseButtonPressed = true;
69}
70END_OF_FUNCTION(close_button_callback)
71 
72 
73 
74void draw(BITMAP* bmpBuffer)
75/*
76 * Draws the current frame to a BITMAP buffer in main memory and then to the video memory (screen).
77 * In this example we're only drawing the total frame count and the frames-per-second count.
78 */
79{
80 // To buffer.
81 textprintf_ex(bmpBuffer, font, 20, 20, WHITE, -1, "frame-count: %d", guintTotalFrames);
82 textprintf_ex(bmpBuffer, font, 20, 40, WHITE, -1, "time: %03d:%02d:%02d:%02d", gushrDays, gushrHours, gushrMinutes, gushrSeconds);
83 textprintf_ex(bmpBuffer, font, 20, 60, WHITE, -1, "fps: %d", gushrFramesPerSecond);
84 
85 // To screen.
86 blit(bmpBuffer, screen, 0, 0, 0, 0, 800, 600);
87 clear(bmpBuffer);
88}
89END_OF_FUNCTION(draw)
90 
91 
92 
93int initialize(void)
94// Initializes the program.
95{
96 char* chrGLaDOS_msg = "If at first you don't succeed,...you fail";
97 
98 // Try to initialize allegro.
99 if(allegro_init() != 0)
100 {
101 printf("%s [to initialize Allegro]. %s.\n", chrGLaDOS_msg, allegro_error);
102 return(-1);
103 }
104 
105 // Try to install keyboard.
106 if(install_keyboard() != 0)
107 {
108 printf("%s [to install the keyboard routines].\n", chrGLaDOS_msg);
109 return(-1);
110 }
111 
112 // Try to install timer.
113 if(install_timer() != 0)
114 {
115 printf("%s [to install the timer routines].", chrGLaDOS_msg);
116 return(-1);
117 }
118 
119 // Set color depth.
120 set_color_depth(32);
121 
122 // Try to set graphic mode.
123 if(set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0) != 0)
124 {
125 printf("%s [to set the graphics mode]. %s.\n", chrGLaDOS_msg, allegro_error);
126 return(-1);
127 }
128 
129 /*
130 * Set display switch mode so the game will continue processing even if the
131 * user switches to another window.
132 */
133 if(set_display_switch_mode(SWITCH_BACKGROUND) != 0)
134 {
135 printf("%s [to set display switch mode].\n", chrGLaDOS_msg, allegro_error);
136 return(-1);
137 }
138 
139 // Lock timer variables.
140 LOCK_VARIABLE(gblnCloseButtonPressed);
141 LOCK_VARIABLE(guintPendingFrames);
142 LOCK_VARIABLE(gushrFramesPerSecond);
143 LOCK_VARIABLE(gushrFramesThisSecond);
144 LOCK_VARIABLE(gushrSeconds);
145 LOCK_VARIABLE(gushrMinutes);
146 LOCK_VARIABLE(gushrHours);
147 LOCK_VARIABLE(gushrDays);
148 
149 // Lock timer routines.
150 LOCK_FUNCTION(add_frame);
151 LOCK_FUNCTION(close_button_handler);
152 LOCK_FUNCTION(tick);
153 
154 // Install timer callbacks.
155 install_int_ex(add_frame, BPS_TO_TIMER(TARGET_FPS));
156 install_int_ex(tick, BPS_TO_TIMER(1));
157 
158 // Install close-button callback.
159 set_close_button_callback(close_button_handler);
160 
161 return(0);
162}
163END_OF_FUNCTION(initialize)
164 
165 
166 
167void logic(void)
168/*
169 * Logic. In this example we're only incrementing a total frame counter, a
170 * frames-per-second counter, and updating time variables.
171 */
172{
173 update_time();
174 
175 guintTotalFrames++;
176 gushrFramesThisSecond++;
177}
178END_OF_FUNCTION(logic)
179 
180 
181 
182void tick(void)
183/*
184 * This is another timer routine that executes [approximately] once per second.
185 * It's role is to set the frames-per-second count and reset the
186 * frames-this-second counter.
187 */
188{
189 // Update game time.
190 gushrSeconds++;
191 
192 // Update frames per second.
193 gushrFramesPerSecond = gushrFramesThisSecond;
194 gushrFramesThisSecond = 0;
195}
196END_OF_FUNCTION(tick)
197 
198 
199 
200void update_time(void)
201// Updates time variables.
202{
203 if(gushrSeconds == SECS_PER_MIN)
204 {
205 gushrMinutes++;
206 gushrSeconds = 0;
207 }
208 
209 if(gushrMinutes == MINS_PER_HOUR)
210 {
211 gushrHours++;
212 gushrMinutes = 0;
213 }
214 
215 if(gushrHours == HOURS_PER_DAY)
216 {
217 gushrDays++;
218 gushrHours = 0;
219 }
220}

To compile it the following commands should work (you must have Allegro [and pthreads installed - Windows users, this probably means you]).

Windows/MinGW: gcc -O2 fps2.c -o fps2.exe -lalleg -lpthreadGC2

*nix/GCC: gcc -O2 fps2.c -o fps2.exe $(allegro-config --libs) -lpthread

karistouf
Member #5,126
October 2004
avatar

Quote:

I'm surprised that doesn't outright crash, what with Allegro's notorious thread unsafety and all.

never crashed... 4 years this damn calling inside main loop... hundred of performances and theatre play without crash... ;D;D;D;D

Quote:

unless you're absolutely sure you know what you're doing.

well, or people have made studies, and better than say'until you know what you are doing' they can explain WHY and HOW ( more constructiv), or they didn t ... no ?

;D

Thomas Fjellstrom
Member #476
June 2000
avatar

Quote:

well, or people have made studies, and better than say'until you know what you are doing' they can explain WHY and HOW ( more constructiv), or they didn t ... no ?

I don't understand a thing you just said.

However, what i meant was, if you know the issues inherent with threading, and know what to work around them, do as you please.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

bamccaig
Member #7,536
July 2006
avatar

Thomas Fjellstrom
Member #476
June 2000
avatar

No. Just ignore that keyword. It doesn't do what most people think it does.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Goalie Ca
Member #2,579
July 2002
avatar

Quote:

On a side note, should a semaphore (sem_t) be volatile?

Actually it relies on a special CPU instruction called (roughly) "test and set lock". It is an entirely atomic operation. sem_t itself is a struct.

-------------
Bah weep granah weep nini bong!

bamccaig
Member #7,536
July 2006
avatar

Thomas Fjellstrom said:

No. Just ignore that keyword. It doesn't do what most people think it does.

Is this not what it does? :-/

 1   2 


Go to: