Windows API: How do I call it?

General FreeBASIC programming questions.
MythGuyDK
Posts: 22
Joined: Sep 21, 2006 20:01

Windows API: How do I call it?

Postby MythGuyDK » Feb 21, 2007 18:19

I'm trying to figure out how to call the Windows API so can make a useful delay function. I'd use:

Code: Select all

t = timer: Do: Loop while t > timer
but it's very... glitchy.

Any help is appreciated.
Skyler
Posts: 242
Joined: Sep 26, 2006 16:30

Postby Skyler » Feb 21, 2007 18:26

Use:

Code: Select all

sleep n

where n is the number of milliseconds you want it to delay.
MythGuyDK
Posts: 22
Joined: Sep 21, 2006 20:01

Postby MythGuyDK » Feb 21, 2007 18:33

But that lets the user bypass the delay by hitting any key. I need something that delays and doesn't let the user bypass.

Plus knowing how to call the API would be good knowledge for the future...
Skyler
Posts: 242
Joined: Sep 26, 2006 16:30

Postby Skyler » Feb 21, 2007 18:40

Code: Select all

for x = 1 to num_of_ms
     sleep 1
next x

At most, they can skip one or two; I doubt they can hit the space bar one thousand times per second. Even if they could, It wouldn't do much good.
MythGuyDK
Posts: 22
Joined: Sep 21, 2006 20:01

Postby MythGuyDK » Feb 21, 2007 18:41

They can hold down the space button... >_>
LukeL
Posts: 118
Joined: Mar 14, 2006 17:26

Postby LukeL » Feb 21, 2007 18:54

Sleep 10000, 1
adding the 1 makes it a 'deep sleep' and cannot be skipped by keypress iirc
MythGuyDK
Posts: 22
Joined: Sep 21, 2006 20:01

Postby MythGuyDK » Feb 21, 2007 19:00

Really? *tests* OK... so it works.
Skyler
Posts: 242
Joined: Sep 26, 2006 16:30

Postby Skyler » Feb 21, 2007 21:52

Did you test my method? I did... the only problem is, you have to set the FOR...NEXT loop for half the required ms, eg:
You want a delay of 1 second. That is 1000 milliseconds. So, you would put 500 ms:
FOR i = 1 to 500
sleep 1
next i

It worked for me. You see, the OS's keyboard settings set the repeat rate- typically well above one millisecond.
tunginobi
Posts: 655
Joined: Jan 10, 2006 0:44
Contact:

Postby tunginobi » Feb 21, 2007 21:59

@Skyler: Timer resolution isn't 1 millisecond. It can vary anywhere between 5-50ms. Multiple sleeps would only multiply this resolution problem. LukeL's code works, is simpler to read and remember, and the timer resolution issue only applies once.
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Postby MichaelW » Feb 22, 2007 1:20

Timer resolution isn't 1 millisecond. It can vary anywhere between 5-50ms.

This is at least approximately correct for the timer used by the FB Sleep function, which AFAIK uses the “system timer” under Windows, but not for the high-resolution performance counter that is used by the FB Timer function under Windows on most recent systems. Per Microsoft, the system timer has a period of approximately 55ms under Windows 95/98/Me, and approximately 10ms under the later versions. Assuming the high-resolution performance counter is available, this code should return the resolution of the Sleep function, essentially 10ms on my Windows 2000 system.

Code: Select all

dim as integer i
dim as double t,tot
for i = 1 to 1000
  t = timer
  sleep 1
  tot += timer - t
next
print using "sleep resolution = ##.###ms";tot
sleep
anonymous1337
Posts: 5494
Joined: Sep 12, 2005 20:06
Location: California

Postby anonymous1337 » Feb 22, 2007 2:15

Since no one is answering the API question I assume no one cares. Now, about your FPS limiter. This loop is just about as close as you can possibly get to your desired frames per second using sleep:

Code: Select all

  '' How many Frames Per Second we want
Dim as integer FPS = 60

  '' Holds how long a frame is
Dim as Double SingleFrame = ( 1 / FPS )

  '' Holds the time of the last frame
Dim as Double LastTime = Timer

  '' Main Loop
Do
 
    '' Loop until one frame has passed by
  Do
      '' Save CPU while waiting for the frame to pass
    Sleep 1, 1 
  Loop until ( Timer - LastTime ) >= SingleFrame
 
    '' Print our estimated fps ( 1 / Amountoftimeframetook )
  locate 1, 1
  Print "Estimated FPS: " & ( 1 / ( Timer - LastTime ) )
 
    '' Save the new time in our variable for comparison
  LastTime = Timer
 
Loop until Multikey(&h01)
It's commented, so have fun. Basically, it goes into a loop of sleeping. Change the amount to whatever you like, but 1ms will do just fine. It continues this loop only while one "frame" hasn't passed by yet.

For 60 fps 8, 1 should be fine if you're lucky :D Otherwise on slower CPU's you can probably only get away with a 6 or 5 ms sleep. It's best to just use 1 and be speed compatable across platforms. If you need that so bad, use a pixels per second method rather than FPS. . .
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Postby MichaelW » Feb 22, 2007 8:11

Since no one is answering the API question I assume no one cares.

I could argue that the FB Sleep function is calling the API, but instead…

Code: Select all

#include "windows.bi"
'' In winbase.bi the Windows Sleep function has been
'' renamed to to Sleep_, I assume to avoid a name
'' conflict with the FB Sleep function.
dim as integer i
dim as double t,tot
for i = 1 to 1000
  t = timer
  Sleep_ 1
  tot += timer - t
next
print using "Sleep_ resolution = ##.###ms";tot
sleep

The resolution should be the same, but unlike the FB Sleep function, the user cannot bypass the delay by pressing a key.

MSDN2: Sleep function
cha0s
Site Admin
Posts: 5317
Joined: May 27, 2005 6:42
Location: Illinois
Contact:

Postby cha0s » Feb 22, 2007 8:59

might i just add that i've never had a problem just using a loop with timer.

Code: Select all

t = Timer + 2: Do: Loop While t > Timer


this is a reliable 2 second delay on all the computers i've ever tried it on.
counting_pine
Site Admin
Posts: 6241
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Postby counting_pine » Feb 22, 2007 16:41

It's reliable, and would give you the best accuracy, but it will hog the CPU by repeatedly looping and calling Timer, as frequently as the system will allow. Which is a waste of CPU time, unless you really need the precision.
If you don't, it would be a very good idea to put a "sleep 1" in the middle of the loop, to cut the CPU drain to almost 0%.

Code: Select all

t = Timer + 2: Do: Sleep 1: Loop While t > Timer

Return to “General”

Who is online

Users browsing this forum: No registered users and 15 guests