Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

Dark GDK / Making it run as fast as possible

Author
Message
prasoc
16
Years of Service
User Offline
Joined: 8th Oct 2008
Location:
Posted: 16th Jul 2010 00:51 Edited at: 16th Jul 2010 01:01
What I'm doing is having a server window which caps at 60 (vsync on: if I dont have it on, the cpu usage goes to 50%...) but if the fps falls below a certain limit, timer based updating slows down. What I want is change the loop into one that goes as fast as possible (to update the timer) but run dbSync() when I want to (60 times a second). I tried changing the LoopGDK() into a "true" but it crashes on exit Could I use multithreading?

_Pauli_
AGK Developer
15
Years of Service
User Offline
Joined: 13th Aug 2009
Location: Germany
Posted: 16th Jul 2010 14:50
Don't know about multithreading but I think something like this could work:
- run your program with uncapped sync rate
- get the elapsed time each loop (with dbTimer())
- add elapsed time to a time value (dbTimer() returns milliseconds)
- if time value is bigger than 1000 / 60 (for your desired 60 times a second) do a sync and reset the time value to 0

Now the plot thickens, the fps decreases, and the awesomeness goes through the roof.
prasoc
16
Years of Service
User Offline
Joined: 8th Oct 2008
Location:
Posted: 16th Jul 2010 18:48 Edited at: 16th Jul 2010 18:50
With an uncapped framerate, my server eats one whole core With vsync on (capped at 60), it uses like 7% rather than 50% cpu usage (one core)

edit: but using the dbtimer() to 1000 / 20 (for 50ms each) is what I do, but if the frame rate falls below a certain rate, the code that checks the time doesn't get run as often as it should

Benjamin
21
Years of Service
User Offline
Joined: 24th Nov 2002
Location: France
Posted: 16th Jul 2010 19:12
If your timer based movement is "slowing down" then you're doing something wrong. Generally it's best to leave VSync enabled.
KISTech
16
Years of Service
User Offline
Joined: 8th Feb 2008
Location: Aloha, Oregon
Posted: 16th Jul 2010 19:34
I'm doing something like this in DBPro.

It's basically the same scenario that _Pauli_ mentions, but I also separate the Game Loop from the Display Loop. The Game loop runs the TBM function, and handles movement of all the objects, and collision, and networking. All those things that can't wait around long.

The Display Loop handles all GET IMAGE, PASTE IMAGE, and TEXT commands, because that only needs to happen when you're ready to show it on screen.

If you want to save some CPU cycles, I was using IanM's NICE WAIT command in DBPro, but I don't know what the equivalent commands would be to do that in C++. You would only have to have a nice wait for a few milliseconds each loop to gain back a fair amount of CPU usage.

The end result of all of this, I'm pushing DBPro to it's outer limits with all that my game is doing, and it's holding 50-55 FPS on my machine, and a Game loop rate of around 70-90.

I do the same thing on the server, except there are no 3D objects so it runs considerably faster. The Display loop is set at 5 FPS, and the game loop runs flat out at around 20,000 loops per second. Giving plenty of time for it to chew through network packets from hundreds of clients.

..and as Benjamin said, if your TBM is "slowing down" then there's something wrong with it. My guess is you have it tied to the framerate somehow. Post the code for your TBM and we can help straighten that out.

prasoc
16
Years of Service
User Offline
Joined: 8th Oct 2008
Location:
Posted: 16th Jul 2010 20:57 Edited at: 16th Jul 2010 21:00
Basically, the while loop is running at 60 fps usually. This means 60 times the loop is gone through. If I wanted my TBM to run at 30hz, I do it like this:



If it runs at less than 30 FPS, the code to increase "tickNum" doesn't get called as often as it should (because the loop isn't running atleast 30 times a second in order to update tickNum)

edit: KISTech, how do you do your second loop within dgdk's one?

JTK
14
Years of Service
User Offline
Joined: 10th Feb 2010
Location:
Posted: 16th Jul 2010 23:04
I use an elapsed time approach. Like so:



And simply pass the elapsed value to the tbm code. From there the tbm can decide what to do - update 1 frame and carry the excess over to the next update or two frames (maybe there's been a couple frames that exceeded the time lapse needed for the update...

it seems to work for me and shows consistant motion regardless of the actual frame rate...

if you like, I can post an example later for you...

JTK
KISTech
16
Years of Service
User Offline
Joined: 8th Feb 2008
Location: Aloha, Oregon
Posted: 17th Jul 2010 01:07 Edited at: 17th Jul 2010 01:17
Quote: "KISTech, how do you do your second loop within dgdk's one?"


The LoopGDK is your main loop.

Inside that you have the calculations to decide whether or not you'll call the Game loop or the Display loop.

dbSync() only happens at the end of the Display loop.

Like so,

I don't know what terminology you would use in C++ for gameLoop() or dispLoop(). They are basically just subroutines you call at the appropriate times.


On the TBM subject,

From your code I can't really tell how you're using it for movement. The idea is to have a value to multiply your movements by that is based solely on the amount of time that has passed, regardless of the framerate.



The code is only finding out how many milliseconds have elapsed since the last time through. There is no need to divide it by 30, or 60. The division by 1000 simply puts decimal point in the right place to calculate the proper distance to move.

At 60 FPS 16.667 milliseconds pass each frame, so you multiply the movement speed by 0.016667 seconds. Over 60 frames, you've moved the object 1 unit. ( 0.016667 * 60 = 1 )

This is true at any framerate. At 30 FPS, 33.333 milliseconds pass each frame. ( 0.033333 * 30 = 1 )

prasoc
16
Years of Service
User Offline
Joined: 8th Oct 2008
Location:
Posted: 17th Jul 2010 02:01
Well, it is more of a time-based counter than actual movement. Every 30th of a second (which is 1000/30) it increases the "tickNum" by one and further on in the code it sends the movement packets to all clients and I'll try out the 2 subroutines and report back

Mumbles
14
Years of Service
User Offline
Joined: 21st Jul 2010
Location:
Posted: 21st Jul 2010 21:42
Generally, I would just stick a Sleep(1) in there. CPU usage will drop down to 0% and it can still process up to 1000 loops per second.

I also used to use GetTickCount (kernel32.dll / windows.h) instead of dbTimer for my render delay counting (Although this was DBP times for me, so it would have been timer() rather than dbTimer()). GetTickCount (on 32-bit XP) increases every 16 ms, giving you a maximum of 64 fps. Not owning vista or 7, I wouldn't know if that old trick works or not...

Obviously, you will want your non-graphical processing to not be capped at 64 updates per seconds, so that would still use dbTimer, which I believe updates 1000 times per second.

Something to think about at least...

Login to post a reply

Server time is: 2024-11-19 20:49:30
Your offset time is: 2024-11-19 20:49:30