Main loop - does everyone do the same stuff ?

Blitz3D Forums/Blitz3D Beginners Area/Main loop - does everyone do the same stuff ?

Dax Trajero(Posted 2004) [#1]
I'm new to all this stuff so was wondering if I'm doing things correctly in my main loop

Function main_loop ()

While Not keyhit(1)

Update_Game_Timers()
Get_Player_input()
Check_Sprite_to_Screen_Collision()
Check_Sprite_to_Sprite_Collision()

WaitTimer(screentimer) ; timer runs at 60Hz
Draw_Screen()
Draw_Sprites()

Wend

End Function



As you can see from the above code I have a screentimer set at 60, so the screen is redrawn at 60Hz. Is this the best way to attain smooth graphics or am I using an incorrect method ?


jhocking(Posted 2004) [#2]
Well, everyone does it slightly differently, but that's essentially what I do. I find that having a function called main_loop is a bit redundant; I do a loop in the main program, outside of any functions, and that loop calls functions (much like you are doing.)

That said, I prefer to have even fewer functions called directly in the main loop, and the functions are abstracted further. So rather than calling functions to move the player and check collisions and such, my main loop calls just two functions, UpdateGame and DrawEverything. Those functions call collision detection routines and drawing functions.


CS_TBL(Posted 2004) [#3]
if your mainloop is kinda big, then a main-loop function has the advantage that you can fold that loop in visual blitz ..


Tibit(Posted 2004) [#4]
I would not recommend using WaitTimer() to halt your program so that is fits a certain FPS. Instead Use Delta Time:

DeltaT#=(MilliSecs()-TimeD#)/1000: TimeD#=MilliSecs()
Now at every place where you apply something over time, Multiply it with DeltaT. Like Speed=Speed + Acceleration*DeltaT. Or X=X+Speed*DeltaT. In this way the game will flow the same for someone with a fps of 20 and someone with a fps of 900. If you use DeltaTime, The speed, for example, will be set as pixels/second. Let's say you want to travel the screen in 3secs. Set Speed=ScreenWidth()/3, or if you have a resolution of 800x600 Speed=800/3M;Pixels/sec. Also Whenever you want something to happen at a given time USE Millisecs() and RealTimers. So that you depend on real-life time and not a in game counter Like Time=Time+1...

For the sake of the loop (I know it's messy), it's not a function, here it is. But that is preference only. I like to have the MAIN-loop after all variables/Types and then there is no real need for a function.

And a Forum Tip: Write <CODE> to start CODEBLOCK <CODE/> to end it BUT use [ instead of < and ] instead of >

; - - -  - M - A - I - N -  - L - O - O - P - - - 
While Not KeyDown(1)
Cls
	 
	 If KeyHit( SPACE )     TEST=TEST+1 :If TEST >=  8 TEST = 0
	 If KeyHit( BACKSPACE ) TEST=TEST-1 :If TEST <=  0 TEST = 7
		 
	 If KeyHit( T )   
		If TEXTON=1 TEXTON=0 Else TEXTON=1
	 EndIf
	
	 If KeyHit( F ) 
		If FLIPFALSE=1 FLIPFALSE=0 Else FLIPFALSE=1
	 EndIf
	
	 If KeyHit( R )	
			If RECORD=1 RECORD=0 Else RECORD=1	
	 EndIf 	
	
		;FPS_Counter      < Runs and displays the FPS
		;--------------------------------------------
			FPS_Counter=FPS_Counter+1
			
			If FPS_Counter_time+1000 =< MilliSecs()
				FPS=FPS_Counter;<- Frames/Sec
				FPS_Counter=0
				FPS_Counter_time=MilliSecs()
			EndIf
					
			Text 10,80,"Current FPS: "+FPS	
		;--------------------------------------------
		DeltaT#=(MilliSecs()-TimeD#)/1000;Delta Timer
		TimeD#=MilliSecs()
		
		If DeltaT < 1
	;			__Update___________
				UpdatePlayer()	    ; Sends data
				BP_UpdateNetwork()  ; Receives Data	
				DecodeGameNetData() ; Reads Received Data		
				
				UpdateShot()	
				UpdateTExplosion()	
				UpdateSpark()
				UpdateImageExplosion()
				UpdateExplosion()   ; Explosions over tanks
				UpdateFireLine()
				
				Draw_Tanks()
				Draw_Arena()
	;			_____________________
		EndIf 

	;Flip limits your FPS to your monitors update Frekv, Flips False does not!
	If FLIPFALSE Flip False Else Flip ;)

Wend

; - - -  - M - A - I - N -  - L - O - O - P - - -



Perturbatio(Posted 2004) [#5]
there's a delta time example in the code archives


jhocking(Posted 2004) [#6]
"if your mainloop is kinda big, then a main-loop function has the advantage that you can fold that loop in visual blitz"

Which is a non-issue for me since I limit my main loop to even smaller than what he wrote, plus I use the default IDE.


N(Posted 2004) [#7]
Delta timing, as far as I'm concerned, is worse than render tweening, actually. They're essentially the same concept, except delta timing (the way most people seem to be doing it) is more of an approximation than the real results of the updated frames.

Tweening runs through 0 to N amount of frames (N amount of frames is delta time rounded up [Ceil()]), and then when you call RenderWorld it interpolates between the N-1 frame and the N frame (essentially frame = (N-1)*(1-Tween) + N*Tween), resulting in the actual results where the delta is greater than 1.0. I assume the cases where the delta time is greater than 1.0 would be low, but even so it's worth considering I think.

That's how I think it works, at any rate. I prefer render tweening, obviously.


morduun(Posted 2004) [#8]
Delta time is hardly an approximation. It gives a precise speed factor based on the time between each frame and a target framerate that one then affects movement and rotation rates by regardless of whether delta is greater or less than one.

I strongly suggest research, rather than assumption, when deciding to make statements like the above.


N(Posted 2004) [#9]
I strongly suggest research, rather than assumption, when deciding to make statements like the above.


That's why at the beginning of my post I say "as far as I'm concerned" and at the end "That's how I think it works", mordy.

This is how I see the two methods, whether or not it's how you see them doesn't concern me.

Now if I started saying that what I said was set in stone and that it was the one and only truth, then you should be concerned.


morduun(Posted 2004) [#10]
Not meant as a personal attack Noel. Simply seems odd to me that a fellow who generally has a clue about things would make such a statement without learning the difference for himself first. As you've rightly earned a bit of respect for yourself with the things you =have= done, misinformation coming from your mouth can easily be seen as truth, especially by people who are looking to Blitz veterans for answers. That said, I felt a reply along those lines was appropriate.


MSW(Posted 2004) [#11]
Also, to keep from pulling out your hair later, put a check in your delta time routine so as to catch the potentialy dangerious event of the millisecs() return rolling over causeing you to operate for a single update with an absurdly huge negative timeslice...to be sure this is a rare occurance (like once every month or so if the players PC is left continuesly on) but it can, and does happen.


morduun(Posted 2004) [#12]
It's a good idea to slip a 'gate' value in no matter what, in fact -- a fairly standard modification to delta time checks current delta against an averaged delta over time, and if the current delta is, say, twice, three times or whatever larger (or smaller) than the average value, to limit that value to 2 or 3 times the average. Not only does that guard against MSW's case, but it also keeps you safe when Windows decides to grab a timeslice for itself and muck up the works.


Dax Trajero(Posted 2004) [#13]
mordum is there any complete example code for this "steady" delta time ?


Dax Trajero(Posted 2004) [#14]
Switched my code over to Delta Time (albeit without a steadying component), made the adjustment to my sprite position calcs and its looking great!

FPS is 2166, but everything is sync'ed nicely thanks to MORDUN's code example.

Thanks all.


morduun(Posted 2004) [#15]
Glad it helped Dax :) Sorry I didn't catch your other reply sooner but I take it you got the demo code from that article so I'm glad it's worked out for ya.


HappyCat(Posted 2004) [#16]
The only real advantage I can see of WaitTimer is that it frees up the CPU while it's waiting, which might be useful I guess. Otherwise delta timing is very smooth.


Dax Trajero(Posted 2004) [#17]
morduun - I'm running with your delta time code, but I AM experiencing the jump effect you mention when windows pinches a timeslice.

Ok, to implement this "gate value" you mention to steady the delta time, I would introduce a new global to store the average delta time, and compare that to the current delta time.

so, if the current deltatime was say, in excess of 200% of the average deltatime, then set the current deltatime to 200% of the average deltatime ?


Dax Trajero(Posted 2004) [#18]
put in my averaging component - here's the figures...

over a 1 minute period, my game reports the following

Min Delta: 0.00
Max Delta: 4.14
Ave Delta: 0.06

so going back to what Morduun was saying I'd add a line of code that, in the event of the currentdelta rising to say 5.0, I would set the currentdelta = average delta * 2


morduun(Posted 2004) [#19]
You can also calc it in realtime -- take an average of delta values over time as you have and if the current value is more than 5 times average value, gate it at 5x the value. That way your gateway is dynamic both to the gamestate and to the individual computer.

(the 5's an example btw -- tinker til you're happy with it)


Zethrax(Posted 2004) [#20]
A simpler method of putting a choke on the delta time is to simply limit the result from the calculation of the amount of time taken for the last loop.

eg.

If the_time_taken > 100 Then the_time_taken = 100