smooth scroll

Blitz3D Forums/Blitz3D Programming/smooth scroll

ZT(Posted 2004) [#1]
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


Ross C(Posted 2004) [#2]
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.


CodeD(Posted 2004) [#3]
Remove Vwait
Change Flip False to just Flip


Ross C(Posted 2004) [#4]
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...


ZT(Posted 2004) [#5]
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?


Ross C(Posted 2004) [#6]
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)


ZT(Posted 2004) [#7]
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??


wedoe(Posted 2004) [#8]
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



ZT(Posted 2004) [#9]
thanks. Same problem, jerky and too fast.

is it not jerky on your machine?


wedoe(Posted 2004) [#10]
Nope..


wedoe(Posted 2004) [#11]
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



ZT(Posted 2004) [#12]
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.


Ross C(Posted 2004) [#13]
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.


IPete2(Posted 2004) [#14]
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.


Sledge(Posted 2004) [#15]

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.


ZT(Posted 2004) [#16]
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!!


ZT(Posted 2004) [#17]
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?


Sledge(Posted 2004) [#18]

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?


WolRon(Posted 2004) [#19]
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.