Different type of loop

Blitz3D Forums/Blitz3D Programming/Different type of loop

GIB3D(Posted 2009) [#1]
I understand you can use
While
Wend

Repeat
Forever

Repeat
Until

For
Next


But... would it be any worse/better if we used...........
Graphics 800,600,0,2
SetBuffer BackBuffer()
AppTitle "Function loop ;)"

omg_loop()

Function omg_loop()
	If KeyHit(1) End
	
	Cls
	
	For k = 2 To 255
		If KeyDown(k)
			Color 255,255,255
			Rect 0,0,GraphicsWidth(),GraphicsHeight()
			Color 0,0,0
			Text GraphicsWidth()/2,GraphicsHeight()/2,":D OM NOm NomNNMOm TEH LEWP!!!11!!",1,1
		EndIf
	Next
	
	Flip
	omg_loop()
End Function


.....a function for a loop?


Charrua(Posted 2009) [#2]
hi
try:
Graphics 800,600,0,2
Global Entradas
Global Salidas
SetBuffer BackBuffer()
AppTitle "Function loop ;)" 
omg_loop()
Function omg_loop() 
	Entradas = Entradas + 1
	If KeyHit(1) End
	Cls
	For k = 2 To 255
		If KeyDown(k)
			Color 255,255,255
			Rect 0,0,GraphicsWidth(),GraphicsHeight()
			Color 0,0,0
			Text GraphicsWidth()/2,GraphicsHeight()/2,":D OM NOm NomNNMOm TEH LEWP!!!11!!",1,1
		EndIf 
	Next
	Text 20,20,"Entradas/Salidas: "+Entradas+" / "+Salidas
	Flip
	omg_loop()
	Salidas = Salidas + 1
End Function 

as you can see, you are entering but never exiting the function, that should end with a stack overflow. If you call a function recursivelly you have to had a way out.

Juan


GIB3D(Posted 2009) [#3]
Um, the way I have works just fine, I'm just wondering if it's any better or worse than using the proper loops.

Edit:
Oh I see what you mean..... it's calling the function a million times... and... ohhhhhh stack.. stacking overflow... I get it ;) So therefore this way is BBAAADDDDDD!

Edit2:
OH, that's why you have that last variable, I see that both the variables would be the same if this were a proper loop but once the function is called again, it skips that last variable.


...no idea what Entradas and Salidas mean, or even what language that's in... but I understand what you were trying to show.


Charrua(Posted 2009) [#4]
sorry, Entradas is Ins (or entrances) and Salidas are outs or Exits
the idea where not to cofuse you.
My intention was that you see that you never return from the funtion, so the variable Salidas (incremented on exit) never get incremented.
Hope you get the point

best regards

Juan
(by the way, is spanish)


_PJ_(Posted 2009) [#5]
I have done some testing on this, an it seems that although ForNext, Repeat Until are around the same kinda speed, While/Wend is significantly faster


Charrua(Posted 2009) [#6]
wow

At first I think that a For/Next in wich the ammount of loops probably were known in advance should be compiled more eficiently than a While/Wend that should end more or less unexpecly!

I supose that the conditions you used where simple and the task's inside the loops were the same or considerably the same.

Any idea for that behavior, or knowledge about innerworkings.

Juan


GIB3D(Posted 2009) [#7]
Yes I understand the point :)

"While/Wend is significantly faster "

:D Yay! I use While/Wend for my main program loop, always, so I'm glad to hear it's faster than the others. When I first started learning about loops in blitz, it kind of scared me that there was more than one way, but I've learned that they pretty much do the same thing.


_PJ_(Posted 2009) [#8]
Ive no idea why it's so. It MIGHT be possible that different CPU's (or manufacturers of CPU's could give different results, for the sake of informaiton, I am running an AMD X2 64 5600+ chip

My test was done with the following:
ClearWorld
SetBuffer FrontBuffer()

Global FN1#=0
Global FN2#=0
Global FN3#=0

Global WW1#=0
Global WW2#=0
Global WW3#=0

Global RU1#=0
Global RU2#=0
Global RU3#=0

x=0

ClsColor 0,0,0
Cls

ClsColor 255,255,255
Global timer%

Delay 1000
Cls

timer%=MilliSecs()
For x=0 To 33554432
Next
stoptime=MilliSecs()
FN1=stoptime-timer

ClsColor 0,0,0
Cls

ClsColor 255,255,255
x=0
Delay 1000
Cls

timer%=MilliSecs()
While x<=33554432
	x=x+1
Wend
stoptime=MilliSecs()

WW1=stoptime-timer

ClsColor 0,0,0
Cls

ClsColor 255,255,255
x=0
Delay 1000
Cls

timer%=MilliSecs()
Repeat 
	x=x+1
Until x>33554432
stoptime=MilliSecs()

RU1=stoptime-timer

ClsColor 0,0,0
Cls

ClsColor 255,255,255
x=0
Delay 1000
Cls


timer%=MilliSecs()
For x=0 To 33554432
Next
stoptime=MilliSecs()
FN2=stoptime-timer

ClsColor 0,0,0
Cls

ClsColor 255,255,255
x=0
Delay 1000
Cls

timer%=MilliSecs()
While x<=33554432
	x=x+1
Wend
stoptime=MilliSecs()

WW2=stoptime-timer

ClsColor 0,0,0
Cls

ClsColor 255,255,255
x=0
Delay 1000
Cls

timer%=MilliSecs()
Repeat 
	x=x+1
Until x>33554432
stoptime=MilliSecs()

RU2=stoptime-timer

ClsColor 0,0,0
Cls

ClsColor 255,255,255
x=0
Delay 1000
Cls


timer%=MilliSecs()
For x=0 To 33554432
Next
stoptime=MilliSecs()
FN3=stoptime-timer

ClsColor 0,0,0
Cls

ClsColor 255,255,255
x=0
Delay 1000
Cls

timer%=MilliSecs()
While x<=33554432
	x=x+1
Wend
stoptime=MilliSecs()

WW3=stoptime-timer

ClsColor 0,0,0
Cls

ClsColor 255,255,255
x=0
Delay 1000
Cls

timer%=MilliSecs()
Repeat 
	x=x+1
Until x>33554432
stoptime=MilliSecs()

RU3=stoptime-timer



ClsColor 0,0,0
Color 255,255,255
Cls

Print "Mean For/Next     : "+Int((FN1#+FN2#+FN3#)/3.0)+"ms"
Print "Mean While/Wend: "+Int((WW1#+WW2#+WW3#)/3.0)+"ms"
Print "Mean Repeat/Until: "+Int((RU1#+RU2#+RU3#)/3.0)+"ms"



Strangely, though.. I have just run the program again a few times, and NOW it seems to indicate ForNext is quicker :S

oops!


GfK(Posted 2009) [#9]
but I've learned that they pretty much do the same thing
They don't. They're hugely different.

While... Wend tests the condition at the start of the loop. The loop repeats until the condition is false.

Repeat... Until, tests the condition at the end of the loop - code in the loop will always run at least once.

Repeat... Forever, will.... repeat a loop forever, obviously. To get out of it you must manually call an Exit.

For... Next, executes a loop a specific number of times.

Two things about your original code:

1. It *will* fail with a stack overflow eventually. Your function is calling itself repeatedly and it is not possible for the function to exit and remove the pointer from the stack.

2. There is no point in checking that many values with KeyDown. KeyDown uses scancodes, not ASCII codes. Much better to just check the ones you want.

[edit] what on God's earth is that code above meant to prove? Your For/Next loop will obviously be quicker as you aren't doing anything in it like you are with the others.


GIB3D(Posted 2009) [#10]
I did understand that tiny little difference between the loops, just didn't feel like explaining it heh.

But the reason I did that with the For k = 2 to 255 was because I saw someone else use something like it, and I knew that GetKey() wouldn't respond to every key. I had it with just If KeyDown(57) or MouseDown(1) but wanted you all to be able to press any key to test it.


Adam Novagen(Posted 2009) [#11]
Yeah, GetKey() pretty much only works with ASCII keys, that is, keys that have letters, number or symbols. GetKey() is actually extremely handy for text input; try this little snippet:

SetBuffer BackBuffer()


While Not KeyHit(1)


Cls


GK = GetKey()
If GK <> 0
    TextLine$ = TextLine + Chr(GK)
EndIf
Text 0,0,TextLine + "_"


Flip


Wend


Do some typing & see what happens. Also notice that when using GetKey(), the use of the Shift key is automatically compensated for. Try typing "AaBb."


GIB3D(Posted 2009) [#12]
LOL... try THAT little snippet you say? I've already created my own little fancy pancy um... texty thingy... heh.

Graphics3D 800,600,0,2
SetBuffer BackBuffer()

PositionEntity CreateCamera(),0,0,-5
CreateLight()
CreateCube()

Locate 0,20
a$=FUNC_OutputMessage(0,8,"Text + render first: ",1)
b$=FUNC_OutputMessage(0,8,"Text - render first: ",0)

Print a
Print b

WaitKey
End

Function FUNC_OutputMessage$(x%,y%,parameter$="",render_first%=1)
	Local TempLabel$
	Local Parameter_Offset% = Len(parameter)*FontWidth()
	
	Local S_TextMessage_Message$
	Local I_TextMessage_Column%
	Local I_TextMessage_Time_Delete%,I_TextMessage_Time_Arrow%,I_TextMessage_Time_Blink%
	
	FUNC_FlushInput()
	
	Repeat
		Cls
		
		If render_first = 1
			RenderWorld
		EndIf
		
		;BackSpace Start
			If KeyHit(14) Or KeyHit(211) Then
				FUNC_FlushInput()
				
				If S_TextMessage_Message <> "" Then
					If I_TextMessage_Column > 0 Then
						TempLabel$ = Right(S_TextMessage_Message,Len(S_TextMessage_Message)-I_TextMessage_Column)
						S_TextMessage_Message = Left(S_TextMessage_Message, I_TextMessage_Column-1 )+TempLabel
						I_TextMessage_Column = I_TextMessage_Column - 1
					EndIf
				EndIf
			EndIf
			
			If KeyDown(14) Or KeyDown(211) Then
				FUNC_FlushInput()
				I_TextMessage_Time_Blink = 0
				
				I_TextMessage_Time_Blink = I_TextMessage_Time_Blink + 1
				
				If I_TextMessage_Time_Blink > 25 Then
					I_TextMessage_Time_Blink = 25
					
					If S_TextMessage_Message <> "" Then
						If I_TextMessage_Column > 0 Then
							TempLabel$ = Right(S_TextMessage_Message,Len(S_TextMessage_Message)-I_TextMessage_Column)
							S_TextMessage_Message = Left(S_TextMessage_Message, I_TextMessage_Column-1 )+TempLabel
							I_TextMessage_Column = I_TextMessage_Column - 1
						EndIf
					EndIf
				EndIf
					
					Else
						I_TextMessage_Time_Blink = 0
			EndIf
		;BackSpace End
			
			
		;Enter Start
			If KeyHit(28) Then
				FUNC_FlushInput()
				
				DebugLog "S_TextMessage_Message = " + S_TextMessage_Message
				
				If Trim(S_TextMessage_Message) <> ""
					Return S_TextMessage_Message
						Else
							Return ""
				EndIf
			EndIf
		;Enter End
			
			
		;Arrow Keys Start
			If KeyHit(203) Then
				FUNC_FlushInput()
				I_TextMessage_Column = I_TextMessage_Column - 1
			EndIf
			
			If KeyHit(205) Then
				FUNC_FlushInput()
				I_TextMessage_Column = I_TextMessage_Column + 1
			EndIf
			
			If KeyDown(203) Then
				FUNC_FlushInput()
				I_TextMessage_Time_Blink = 0
				
				I_TextMessage_Time_Arrow = I_TextMessage_Time_Arrow + 1
				
				If I_TextMessage_Time_Arrow > 25 Then
					I_TextMessage_Time_Arrow = 25
					I_TextMessage_Column = I_TextMessage_Column - 1
				EndIf
				
					ElseIf KeyDown(205) Then
						FUNC_FlushInput()
						I_TextMessage_Time_Blink = 0
						
						I_TextMessage_Time_Arrow = I_TextMessage_Time_Arrow + 1
						
						If I_TextMessage_Time_Arrow > 25 Then
							I_TextMessage_Time_Arrow = 25
							I_TextMessage_Column = I_TextMessage_Column + 1
						EndIf
							
							Else
								I_TextMessage_Time_Arrow = 0
			EndIf
		;Arrow Keys End
		
		
		;Home End Keys Start
			If KeyHit(199) Then
				FUNC_FlushInput()
				I_TextMessage_Time_Blink = 0
				I_TextMessage_Column = 0
			EndIf
			
			If KeyHit(207) Then
				FUNC_FlushInput()
				I_TextMessage_Time_Blink = 0
				I_TextMessage_Column = Len(S_TextMessage_Message)
			EndIf
		;Home End Keys End
		
		;MouseHit 1 Start
			If MouseDown(1) Then
				If MouseY() => y Then
					If MouseY() <= y+FontHeight() Then
						I_TextMessage_Time_Blink = 0
						
						I_TextMessage_Column = (MouseX()/Float(FontWidth()))
					EndIf
				EndIf
			EndIf
		;MouseHit 1 Start
			
			Local TempKey% = GetKey()
			
			If TempKey <> 0
				DebugLog "TempKey = " + TempKey
				Select TempKey
					
					;ASCII
					;Delete			127
					
					;Left			31
					;Right			30
					;Up				28
					;Down			29
					
					;Escape/Esc		27
					;Enter/Return	13
					;Backspace		8
					
					;Home			1
					;End			2
					
					Case  127, 31,30,29,28, 13,8 ,1,2
						FUNC_FlushInput()
						;Does nothing if those keys are pressed
						
					Case 27
						FUNC_FlushInput()
						Return ""
						
					Default
						FUNC_FlushInput()
						
						I_TextMessage_Time_Blink = 0
						
						TempLabel$ = Right(S_TextMessage_Message,Len(S_TextMessage_Message)-I_TextMessage_Column)
						S_TextMessage_Message=Left(S_TextMessage_Message,I_TextMessage_Column)+Chr(TempKey)+TempLabel
						I_TextMessage_Column = I_TextMessage_Column + 1
						
				End Select
			EndIf
			
		If I_TextMessage_Column > Len(S_TextMessage_Message) Then
			I_TextMessage_Column = Len(S_TextMessage_Message)
				ElseIf I_TextMessage_Column < 0
					I_TextMessage_Column = 0
		EndIf
		
		I_TextMessage_Time_Blink = I_TextMessage_Time_Blink + 1
		
		If I_TextMessage_Time_Blink < 25
			Rect Parameter_Offset+x+Float(I_TextMessage_Column*FontWidth())-(FontWidth()*.5)+3,y-(FontWidth()*.5), 3,FontHeight()
		EndIf
		
		If I_TextMessage_Time_Blink > 50
			I_TextMessage_Time_Blink = 0
		EndIf
		
		Text x,y,parameter+S_TextMessage_Message,0,1
		
		Flip
	Forever
End Function

Function FUNC_FlushInput()
	FlushJoy()
	FlushKeys()
	FlushMouse()
End Function