smooth scroll
Blitz3D Forums/Blitz3D Programming/smooth scroll
| ||
Trying to get smooth scrolling for a 2D game in Blitz 3D, but whatever I do, there is always a bit of jerkiness. The scrolling dowsn't appear smooth to me, and somtimes, it will give a noticeable jerk. I also want the screen to scroll slower than it is, but can't get this to work. Can anyone give any suggestions as to why it's not working? Thanks Code below... Global Debug = True Type FrameRate Field TargetFPS# Field SpeedFactor# Field TimeElapsed# Field FPS# Field FPS2# Field FPS3# Field FPS4# Field FPS5# Field CurrentTicks Field FrameDelay End Type Global no0# = 0.00000000001 ;avoids division by zero ;for example; any time you perform a division, add no0# to the divisor ;quotient# = dividend# / (divisor# + no0#) Global FL.FrameRate = New FrameRate ;initialize frame limiter FL\TargetFPS# = 60 ;set this to whatever FPS your code is based on FL\FrameDelay = MilliSecs() Graphics 800,600 quitgame=0 SetBuffer frontbuffer() backx=0 backy=0 background=createimage(800,600) SetBuffer ImageBuffer(background) Color 255,0,0 Rect 0,0,50,50,1 Color 0,255,0 Rect 20,20,50,50,1 SetBuffer BackBuffer() ;--------------------------------------------------------------------------------------- ; Main Game Loop ********************************************************************** ;--------------------------------------------------------------------------------------- While (Not quitgame) Cls ;Set Speed Factor FL\CurrentTicks = MilliSecs() FL\SpeedFactor# = (FL\CurrentTicks - FL\FrameDelay) / (1000.0 / FL\TargetFPS#) If FL\SpeedFactor# <= 0 Then FL\SpeedFactor# = no0# FL\TimeElapsed# = (FL\CurrentTicks - FL\FrameDelay) / 1000.0 If Debug FL\FPS# = (FL\FPS2# + FL\FPS3# + FL\FPS4# + FL\FPS5# + FL\TargetFPS# / FL\SpeedFactor#) / 5 FL\FPS5# = FL\FPS4# : FL\FPS4# = FL\FPS3# : FL\FPS3# = FL\FPS2# : FL\FPS2# = FL\FPS# EndIf FL\FrameDelay = FL\CurrentTicks ;SpeedFactor# contains a percentage of the last frame ;TimeElapsed# contains a percentage of the last second v# = v# + (FL\TimeElapsed# * a#) ;velocity (m/s) = velocity (m/s) + time (s) * acceleration (m/s^2) speedZ=(FL\SpeedFactor#) ;--- check for escape key If KeyDown( 1 )=True Then quitgame =1 End if ;--- draw background... For by=0 To 15 For bx=0 To 15 DrawImageRect background,backx+bx*50,backy+by*50,0,0,50,50 Next Next ;-- scroll background down... backy=backy+speedZ If backy>700 Then backy=-800 If Debug Text 10, 10, "FPS: " + Int(FL\FPS#) Text 10,50,"X:"+Str$(backx)+" Y:"+Str$(backy) EndIf VWait Flip False Wend End |
| ||
Doesn't use vwait. If you syncing the framerate your self, then using vwait as well, it will sync the FPS to the refresh rate of the monitor, therefore making your Frame Rate code kinda useless. Maybe that's whats causing your jerkyness. Try getting rid of v-wait all together. |
| ||
Remove Vwait Change Flip False to just Flip |
| ||
Hmm, very odd. There must be a problem with your frame syncing code. The image scrolling only updates if th blitz window is moving.... And in full screen mode, it moves once then doesn't move again... |
| ||
I'd already tried just flip, but that still seems jerky on mine. Ross, try changing the FL\TargetFPS# = 60 to a different amount. Even if I don't use the frame syncing and just increment the scroll by 1, it still looks jerky. Obviously I want the game to play at the same speed on different setups, hence the frame sync code. Has anybody got some demo code which scrolls slowly and smoothly, taking into account different setups? |
| ||
I changed 60 to 120, didn't really have much of a diference. What you can do, is time how long the render takes, start a timer at the beginning of the loop, do the game logic, moving player..etc, see long long you have left, take away the render time, then wait that long till you do your drawing of images and flip. That should keep you code running smooth on different set ups :o) |
| ||
very odd how it doesn't work on yours. What if you ignore the FPS code and just update backy+1 ? I've just tried it on another machine, and it works fine, allbeit too jerky. Surely, if I just update the scroll by +1, and wait for vertical sync, the scroll should be smooth? But its not! What am I missing?? |
| ||
I don't know if this is any help to you but this scroller is very small and should be easy to covert to your need:Graphics 640,480,16,2:Dim scroll$(100):Color 255,255,255 Type scr Field x,y,txt$ End Type:Global a .scrollread:a=a+1:Read scroll$(a) If Not scroll$(a)="EOF" Goto scrollread a=a-1:SetBuffer BackBuffer():Repeat For b=1 To a:ln.scr=New scr:Ln\x=200:Ln\y=490:ln\txt$=scroll$(b) For c=1 To 20:For ln.scr=Each scr:ln\y=ln\y-1:Text ln\x,ln\y,ln\txt$:If ln\y<-10 Then Delete ln.scr Next:Flip:Cls:Next:Next:Until KeyDown(1) Data "Hello world":Data"Line two":Data"Line three":Data "EOF":End |
| ||
thanks. Same problem, jerky and too fast. is it not jerky on your machine? |
| ||
Nope.. |
| ||
Same scroller, cleaned up and half speed:Graphics 640,480,16,2 Dim scroll$(100):Color 255,255,255 Type scr Field x#,y#,txt$ End Type Global a .scrollread:a=a+1: Read scroll$(a) If Not scroll$(a)="EOF" Goto scrollread a=a-1 SetBuffer BackBuffer() Repeat For b=1 To a ln.scr=New scr:ln\x=200 ln\y=490:ln\txt$=scroll$(b) For c=1 To 30 For ln.scr=Each scr ln\y=ln\y-.5 Text ln\x,ln\y,ln\txt$ If ln\y<-10 Then Delete ln.scr Next Flip Cls Next Next Until KeyDown(1) Data "Hello world":Data"Line two":Data"Line three":Data "EOF":End |
| ||
hmmm, I give up. tried yours on both my machines and it looks jerky. Athlon 2100+ Geforce 4 & P4 1.7 with geforce mx2. I seem to be getting better results with using a 3D sprite and setting the camera a long way away. But I'm sure this must be more resource hungry, and won't work on slower computers. |
| ||
Well, 2d probably looks jerky, because it doesn't interpolate between pixel. 3D does this, so you will get smoother scrolling with that. Also, try upping your refresh rate on your monitor. Maybe that is causing problems. Maybe also, you GFX drivers are being forced to wait for v-sync before continuing. Try and do what i suggest. Time how long it takes to draw everything, then in the next loop time the rest of the code execution and wait the correct amount of millisecs before you render. |
| ||
ZT Just for the record. I have an Athlon 1900+ 512 MB Geforce 3 (64MB), when I run the original code with the vWait and false parts removed it looks absolutely fine. Really smooth if a little quick. IPete2. |
| ||
Well, 2d probably looks jerky, because it doesn't interpolate between pixel. That's not really true, as evidenced by the thousands upon thousands of games that exhibit smooth scrolling using 2D alone. Interpolating just makes things look distorted - a good 3d-as-2D system will move objects in pixel sized steps anyway. ZT, whether or not your original code looks jerky or not depends on two lines... FL\TargetFPS# = 60 and Graphics 640,480 For example, my GFX card runs at the optimal refresh rate for whatever resolution it is set to. At 640*480 that is 120hz, into which 60 frames a second fits quite precisely - the image being updated once every two refreshes exactly. At this resolution your original code looks PERFECT on my monitor therefore. However if I set the resolution to 1024*768 then it's a different story... at that resolution my monitor's optimal refresh rate is 85hz and, obviously, the speed at which the code updates the display no longer syncronises exactly with what the monitor is doing. Set like this, it looks jerky. Chances are, your monitor's refresh rate is not set to a multiple of 60 and this is why your code looks jerky. This is a continual problem with PC development - either you can use the monitor's refresh to limit speed and have a program that always looks smooth (CPU speed permitting) but may execute at different rates on various machines OR you can frame limit and have a program that is BOUND to update in a jerky manner on some set-ups. |
| ||
thanks for the feedback. Yes, 3D does give a smoother look. I have changed my refresh etc, and tested it on several machines, but the important factor is that the game runs on other peoples machines (without them adjusting their refresh), so this would not help in the long run. How do you check if the gfx drivers are forcing a vsync wait? I've looked at the driver, geforce Ti4600, and the closest thing I can see, says "Verticle Sync - Application Controlled" which suggests to me that its not waiting. Again this won't help, as I can't force prospective customers to change their gfx card settings, but I'm curious. I'll stick with what I've got without the vwait. At least it seems to be consistent over 3 machines (which is the important factor to me), allbeit with the odd jerkiness. I think I'm just being fussy. I'm sure it used to scroll smoother on the C64!! |
| ||
Sledge - that's interesting. I have tried various settings on the refresh, but it's optimum is 72Mhz at 1280 by 1024. It's an LCD. I've also tried various combinations of FL\TargetFPS# = 60 which I've currently got set to 72. So the end result is, it's going to look different on everybody else's machine (in terms of smoothness), even if I manage to keep the game/scroll speed the same? or are you suggesting I set the game to 60Mhz and 640x480? |
| ||
or are you suggesting I set the game to 60Mhz and 640x480? That would not guarantee you anything - my old monitor maxed out at 85Hz at 640*480 and many of your customers will have such hardware. On my old monitor, the code that looks fine for me now would look jerky again. Similarly, if I run your code at 1024*768 AND set TargetFPS# to 85 rather than 60 it looks fine (the FPS counter suggests an update of 42.5 frames a second... fitting exactly with the monitor's optimal speed at that res'). You basically have a couple of questions to address: Are you going to allow your code to run at multiple speeds in order to appear smooth on a range of monitors (remembering that you can still retain some control over the range)? And, if so, how are you going to let your program know what speed it should adopt? |
| ||
I think the reason you are experiencing jerkiness is because backx, backy, and speedZ are integers. Change all three to floating point and the problem may go away. |