Strobing screen.
Blitz3D Forums/Blitz3D Beginners Area/Strobing screen.
| ||
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? |
| ||
Do you means how many times the screen strobes per second? |
| ||
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. |
| ||
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) |
| ||
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? |
| ||
TryFlip 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. |
| ||
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. =) |
| ||
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.. =( |
| ||
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 |
| ||
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. |
| ||
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. |
| ||
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 |
| ||
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! =) |
| ||
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. |
| ||
Thank you for your code also mindstorms. =) If it didn't help now, it might do in the future, or even help someone else! |