Page 1 of 2

Windows Events

Posted: Wed Jan 11, 2006 2:16 pm
by Steve Elliott
What event-like commands do PureBASIC users recommend for fullscreen games programming in a multi-tasking operating system like Windows?

What seems ideal is something like this DirectX code which doesn't halt the program completely to let Windows back-in (which is inefficient). It takes care of Windows calls and gives the program the time that is left (to render in the example).

WPARAM StartMessageLoop()
{
MSG msg;
while(1)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;

TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
// use idle time here
Render();
}
}

return msg.wParam;
}

Posted: Wed Jan 11, 2006 2:25 pm
by Fred
in fullscreen the messageloop is automatically processed by flipbuffer(). in windowed mode, you have to do it, preferably with WindowEvent():

Code: Select all

Repeat
  Event = WindowEvent()
  ; handle your events here
Until Event = 0 ; until all events have been processed.

Posted: Wed Jan 11, 2006 2:31 pm
by Steve Elliott
So Fred are you saying that fullscreen programs will only take the necessary time from Windows and no more?

In other words (using fullscreen) Windows will not try to take cycles back from the PureBASIC program because the PureBASIC game is using all resources and not allowing Windows events to function correctly (causing judder in a game). Is that correct?

Posted: Wed Jan 11, 2006 4:20 pm
by Joakim Christiansen
Just put a Delay(2) or something like that in your loop and other programs will run fine. :wink:

Posted: Wed Jan 11, 2006 5:12 pm
by Steve Elliott
Like I said Joakim that's inefficient - Windows might not require any processing so you've just halted your program for no reason. PureBASIC seems so Windows friendly so surely there's a better way?

Anyway Fred seems to be saying that it's taken care of - but I'd like clarification on this. Fred, do we need to put a delay statement in all of our full screen games?

Posted: Wed Jan 11, 2006 5:37 pm
by Joakim Christiansen
I don't think there is any bether way.
PB games use 100% cpu if you have no delay.
The FlipBuffers() command use cpu while it waits, so even if you set your frame rate to 10 it will still eat you cpu.

Posted: Wed Jan 11, 2006 5:47 pm
by Kale
Steve Elliott wrote:Like I said Joakim that's inefficient - Windows might not require any processing so you've just halted your program for no reason. PureBASIC seems so Windows friendly so surely there's a better way?

Anyway Fred seems to be saying that it's taken care of - but I'd like clarification on this. Fred, do we need to put a delay statement in all of our full screen games?
I sometimes put Delay(1) in my full screen apps to limit cpu usage, which is more than enough.

Posted: Wed Jan 11, 2006 7:55 pm
by Fred
v4 will brings an alternative (to reduce fullscreen game cpu usage), but it not sure anymore than the visual display will be 100% perfect. You could try it tough.

Posted: Wed Jan 11, 2006 8:13 pm
by Rescator
If you want the game to get all the cpu available but not lock up the system,
try Delay(0)
Some people hate it when a game or app use all available cpu though, so maybe make it user selectable.

Silly example:

Code: Select all

ms=0 ;High performance (uses all available cpu without locking up system)
ms=1 ;Multitask friendly (only uses as much cpu as needed, other apps should run very well)

Delay(ms)
Myself for misc. apps I use a delay of 1.
For a game I might use a delay of 0,
or allow the user to choose between the two.
And for really simple apps I do not use any delay,
but just use WaitWindowEvent() instead of WindowEvent()

So... The 3 recommended ways to handle loops:

1.
WaitWindowEvent()
Very system friendly, bad program performance for timecritical stuff obviously.
Possibility of using a system timer for loop triggering.

2.
WindowEvent() + Delay(1)
Very common, good performance, very system friendly.
This is the most popular choice!
Uses less power, generates less heat.
(cpu fan will go between low and max depending on your game/app)

3.
WindowEvent() + Delay(0)
Still system friendly, a few other apps might suffer some performance, maximum performance for your app, uses all free cpu power.
Uses more power, generates more heat.
(cpu fan will be going full speed all the time)

I do not recommend any other types of loops myself,
like no Delay() at all. As that tends to suck up not all free cpu but
steal (or rather deny) cpu from other apps as well. (cpu hogging)
You might even end up with graphics and sound stutters in your own program.

System drivers need cpu as well, altough they should have much higher priority than your program, they still share cpu with your program.

My advice is try with Delay(1) if that seems to give bad performance,
try using Delay(0) instead.
Delay(0) is not the same as Delay(1) or Delay(2) etc.
Delay(0) cause no delay at all, but simply let the system do a task switch,
and if nothing else is going on your program get back the cpu at once,
without delays at all.
Delay(1) on the other hand always waits at least 1ms,
regardless if something is using the cpu next or not in the cpu queue.

Lookup the Sleep function in the PSDK documentation for info on the use of 0 microsecond for the delay.
I'm not sure if Linux or Mac behave the same when Delay(0) is used though.

Posted: Wed Jan 11, 2006 8:24 pm
by PB
> Windows might not require any processing so you've just halted your
> program for no reason

You should do "Delay(1)" ONLY if WindowEvent=0, so that you won't halt
your app while it's busy.

Posted: Wed Jan 11, 2006 8:27 pm
by Rescator
PB wrote:> Windows might not require any processing so you've just halted your
> program for no reason

You should do "Delay(1)" ONLY if WindowEvent=0, so that you won't halt
your app while it's busy.
Yeah! That's a easy mistake to do, both ways actually.
And especially when using nested select or if else code.
It is so easy to forget to add a delay or accidentaly add a extra delay when not needed when nesting code.

Posted: Wed Jan 11, 2006 10:40 pm
by Steve Elliott
Thanks for all your feedback.

Using a delay(1) only when a WindowEvent() = 0 sounds like the best solution - at least until v4.

:D

Posted: Wed Jan 11, 2006 11:19 pm
by Joakim Christiansen
Steve Elliott wrote:Thanks for all your feedback.

Using a delay(1) only when a WindowEvent() = 0 sounds like the best solution - at least until v4.

:D
Yeah, just have the delay on default.

Code: Select all

Select WindowEvent()
  Case #PB_Event_CloseWindow: End
  Default: Delay(1)
EndSelect

Posted: Thu Jan 12, 2006 4:58 am
by netmaestro
Try this code:

Code: Select all

Repeat
  Ev=WaitWindowEvent()
until Ev=#PB_Event_V4_Release

Posted: Thu Jan 12, 2006 5:44 am
by Rescator
:lol: