Strobing screen.

Blitz3D Forums/Blitz3D Beginners Area/Strobing screen.

SheepOnMintSauce(Posted 2006) [#1]
This isn't anything I NEED to know, I'm just about curious about it. I made a small program which strobes black and white when you press the space bar.

Graphics 800,600,0,0
SetBuffer BackBuffer()
a=True
fps=CreateTimer(10)
While Not KeyDown(1)
  WaitTimer(fps)
  Cls
  If KeyDown(57)
    For b=0 To 200
      If a=True
        ClsColor(255,255,255)
        a=False
      Elseif a=False
        ClsColor(0,0,0)
	a=True
      EndIf
    Next
  EndIf
  Flip
Wend


I was fiddling about with it, and got to thinking about how would I work out how many hertz it was strobing by? I have my monitor set to 85hz, and I set the frame timer to 10 frames per second. Would this be about 8.5hz, or am I missing something? If so, how would I figure out how many hertz it is strobing by?


Ross C(Posted 2006) [#2]
Do you means how many times the screen strobes per second?


SheepOnMintSauce(Posted 2006) [#3]
Yes, well at least I think so. Like a strobe light flashing on and off I suppose. I read on wikipedia that most strobe lights are limited to 10~12 flashes a second.. so I'm assuming that's 10-12hz, which is what I'd like to do on the screen. But, I'm not sure if it works the same way as I've done it.


Ross C(Posted 2006) [#4]
IGNORE, i was ignorant about the command you were using, sorry! The Waittimer uses Frames per second, which equates into hertz, so yeah :o)

I'm pretty sure the waittimer() things stops your program until the time has passed. You should maybe consider using a different approach if you intend to have other things happening in your program :o)

One way is to use Millisecs(). This is the system timer that starts when your computer gets powered on. To use this for a timer, you would do something like this:

Timer = millisecs()


Make your timer variable equal the current millisecs() value. Remember, the millisecs() command, returns the current millisecond the computer is counting, so it changes on it's own. Now, to get how many milliseconds have passed since then, do:

Time_passed = Millisecs() - Timer


Time_passed will now contain the difference between the two, giving you how many milliseconds have passed. The benefits of this, is your program keeps executing :o)


SheepOnMintSauce(Posted 2006) [#5]
Ah right. It seems really slow now.. like a dodgy light bulb or something. Wouldn't the refresh rate of the monitor have something to do with it too?


Ross C(Posted 2006) [#6]
Try
Flip 0

:o), that will disable vsync. I think it only works in full screen mode though.

Oh and remember, 10 frames per second, isn't fast. That's another reason why it's dodgy.


SheepOnMintSauce(Posted 2006) [#7]
Ah, sorry I must've missed that last but one post you did about the milliseconds. Actually using milliseconds probably makes more sense to me since there's a thousand milliseconds in a second so, I could devide the 1000 by the hertz, so I'd know when to make a flash after the resulting amount of milliseconds has passed. Thanks Ross, I'll give that a shot. =)


SheepOnMintSauce(Posted 2006) [#8]
I tried redoing it, the thing is the way I did it, I just got a blank screen.
timer=MilliSecs()
hertz=8
Graphics 800,600,0,0
SetBuffer BackBuffer()
waittime=1000/hertz
checktime=waittime
While Not KeyDown(1)
	timepassed=MilliSecs() - timer
	If timepassed=checktime
		ClsColor(255,255,255)
		Cls
		checktime=checktime+waittime
	ElseIf timepassed<>checktime
		ClsColor(0,0,0)
		Cls
	EndIf
	Flip
Wend


I realised it's probably because of the If timepassed=checktime part, where the timepassed just misses the checktime. I altered it again to..

timer=MilliSecs()
hertz=8
Graphics 800,600,0,0
SetBuffer BackBuffer()
waittime=1000/hertz
checktime=waittime
While Not KeyDown(1)
	timepassed=MilliSecs() - timer
	If timepassed>=checktime
		ClsColor(255,255,255)
		Cls
		checktime=checktime+waittime
	ElseIf timepassed<checktime
		ClsColor(0,0,0)
		Cls
	EndIf
	Flip
Wend


This seems to work, but I don't know how accurate it is now. and the lower the value of 'hertz' the more inaccurate it'll be, because it's not flashing on the checktime exactly. After trying something like 40 for the hertz value it's not too accurate there either.. =(


mindstorms(Posted 2006) [#9]
Millisecs() go too fast for each loop to be one millisecs. Usually 8 or 9 millisecs pass with each loop. Try this function that I picked up somewhere. Run the function each loop, and it will calculate an average of the last 20 loops, making it more acurate than simple millisecs(). gLoopTime is on average how much time it has taken per loop, so you can add this to another variable to determine how much time has past or will past.

;clock
Dim savedClockTime#(20)
Global savedClockCount
Global gLoopTime#

Function UpdateGameClock()
	savedClockCount = savedClockCount+1
	If savedClockCount = 20 Then savedClockCount = 0
	Local time# = MilliSecs()
	gLoopTime# = (time#-savedClockTime#(savedClockCount))/20000	
	savedClockTime#(savedClockCount) = time#
	If gLoopTime# > .1 Then gLoopTime# = .0167	
End Function




SheepOnMintSauce(Posted 2006) [#10]
How would I go about fitting this in exactly? I did just have a try, but it's a bit bewildering and I found myself getting a bit confused as to how it works.


Ross C(Posted 2006) [#11]
You have a slight problem with all of this, as far as i can see :o) You are flipping the screen buffer. Now, each time you flip and cls the screen, you are setting the buffer to a different colour, so, on each flip, you are getting the result of the other buffer. Solution is to use double buffering and draw a rect on the screen.


Ross C(Posted 2006) [#12]
First off, a loop doesn't take 8-9 millisecs() to perform. I get 1090 fps with my code below. It will drop if i add more 2d stuff, but it's veeeeeeery quick. So, the millisecs method is very accurate. Check out the sample at the bottom of this post for details.

The way you usually lay out 2d drawing operations, it's been a while since i did the 2d stuff, that's why i didn't pick up on it right away :o)

The way is usually to have

While Not Keyhit(1)

cls

;draw stuff

flip

wend


a cls at the beginning, and a flip at the end.

I have put in a strobe variable. if set to one, the color is white, if set to zero, the color is black. I alternate this, using a very handy piece of code :o)

strobe = 1 - strobe


Every time that's used, it will alternate between the values of 0 and 1.

I change the color by multiplying the value of strobe by 255. This changes the color appropriately. Then a rect that fills the screen appears. You could do this fast by using your clscolor method, but i think it's simplier using the rect. Remember, this isn't a timing problem, it's a problem with the way the code was laid out. I use a slightly different method to set the timers too.

So, this should work:

Global timer=MilliSecs()
hertz# = 8
Graphics 800,600
SetBuffer BackBuffer()

Global wait_time# = 1000.0/hertz

Global strobe = 0

While Not KeyDown(1)

	Cls
	If MilliSecs() > timer + wait_time
		strobe = 1 - strobe
		timer = MilliSecs()
	EndIf

	Color(strobe*255,strobe*255,strobe*255)
	Rect 0,0,800,600

	;ignore, for timing purposes only
	frames = frames + 1
	If MilliSecs() > time+1000 Then
		time = MilliSecs()
		fps = frames
		frames = 0
	End If

	Color 128,128,128
	Text 20,0,"fps = "+fps
	Text 20,10,"millisecs to complete frame = "+(1000/fps)
	; end of ignore

	Flip 0
Wend



SheepOnMintSauce(Posted 2006) [#13]
I get 1,980 odd as the frames per second with that code, but I also get the bar of the refresh of my monitor showing too. I do see now though, how that code is a lot better. I especially like that strobe = 1 - strobe line. Without the Flip 0, and just Flip instead, I don't get the refresh showing on the screen, but the frames per second drops to about 85. I realise this is because of it having to wait, but it still seems to be accurate too. Thanks! =)


mindstorms(Posted 2006) [#14]
I just supplied the code because I had the same problem (with a much bigger loop) and this fixed it. I thought it might help, but I was wrong. Thinking about it, I agree with Ross that your loop updates enough to use the raw millisecs() code.


SheepOnMintSauce(Posted 2006) [#15]
Thank you for your code also mindstorms. =) If it didn't help now, it might do in the future, or even help someone else!