So before I started writing my game, I prototyped a lot of the stuff I was going to be doing in small test programs, and one of the obvious ones was smooth movement based on timing. Using a routine written by MrAToad and I believe Ampos, I created the following test program which draws two rectangles just to see which routine is smoother/better/etc. And I sure at time, which was probably a couple of months ago now, the movement was perfectly smooth without any jumping or "jerkiness". However, I try the same routine now and it seems jumpy and non-smooth.
Is anyone else having similar issues?
GLOBAL movementRate
GLOBAL screenWidth
GLOBAL screenHeight
GETSCREENSIZE screenWidth, screenHeight
GLOBAL x = 0
GLOBAL y = ( screenHeight / 2 )
GLOBAL x2 = 0
GLOBAL y2 = ( screenHeight / 2 ) + 100
GLOBAL timer AS TAppTime
timer.Initialise(60)
WHILE (x2+50) < screenWidth
movementRate = ( screenHeight / 2) * 0.001 * GETTIMER()
DRAWRECT x, y, 50, 50, RGB(0, 0, 255)
INC x, (0.2 * movementRate)
DRAWRECT x2, y2 + 50, 50, 50, RGB(255, 0, 0)
INC x2, (0.8 * timer.Update())
SHOWSCREEN
WEND
MOUSEWAIT
END
// --------------------------------- //
// Project: AppTimer
// Start: Thursday, September 11, 2008
// IDE Version: 5.360
TYPE TAppTime
AppTime_UPS;AppTime_Iterator;AppTime_CurrentTime;AppTime_PauseStart;AppTime_Speed;AppTime_DesiredLoopTime;AppTime_LastUpdateTime
AppTime_LastUPSTime;AppTime_DesiredFrequency%
//! This function initialises the AppTimer system, and must be called first.
//\param frameRate% - This is the frame rate that you want all movement to be based on. It defaults to 60 FPS, which is the lowest rate that should be used.
//\return Nothing is returned
FUNCTION Initialise%:frameRate%=60
self.AppTime_UPS=0.0
self.AppTime_Iterator=0.0
self.AppTime_CurrentTime=0.0
self.AppTime_PauseStart=0.0
self.AppTime_Speed=1.0
self.AppTime_LastUpdateTime=0.0
self.AppTime_LastUPSTime=0.0
self.AppTime_DesiredLoopTime=1000.0/(frameRate*1.0)
RETURN TRUE
ENDFUNCTION
//! This function updates the timing system. It needs to be called once per loop.
//\param No parameters are passed
//\return A movement value is returned. This should be muliplied by the amount you want to move. If the routine is paused, then 0.0 is returned
FUNCTION Update:
LOCAL time
LOCAL elapsed
IF self.AppTime_PauseStart<>0
RETURN 0.0
ENDIF
time=GETTIMERALL()
IF self.AppTime_LastUpdateTime=0.0
self.AppTime_Speed=1.0
self.AppTime_LastUPSTime=time
ELSE
elapsed=time-self.AppTime_LastUpdateTime
IF elapsed=0.0
elapsed=1.0
SLEEP 1
INC time,1.0
ENDIF
self.AppTime_Speed=elapsed/self.AppTime_DesiredLoopTime
ENDIF
self.AppTime_LastUpdateTime=time
self.AppTime_CurrentTime=time
INC self.AppTime_Iterator,1.0 // Its a float as it can go very large...
IF self.AppTime_CurrentTime-self.AppTime_LastUPSTime>=1000.0
self.AppTime_UPS=self.AppTime_Iterator/((self.AppTime_CurrentTime-self.AppTime_LastUPSTime)/1000)
self.AppTime_LastUPSTime=self.AppTime_CurrentTime
self.AppTime_Iterator=0
ENDIF
RETURN self.AppTime_Speed
ENDFUNCTION
//! This function is used when your program is paused or not. If it is, then the step speed is still updated
//\param pause% - If this is TRUE, then your program is paused. If FALSE, then it isn't
//\return Nothing is returned
FUNCTION Pause%:DoPause%
LOCAL elapsed
IF DoPause%=TRUE
IF self.AppTime_PauseStart=0.0
self.AppTime_PauseStart=GETTIMERALL()
self.AppTime_UPS=0
self.AppTime_Speed=0
ENDIF
ELSE
IF self.AppTime_PauseStart<>0.0
IF self.AppTime_LastUpdateTime<>0.0
elapsed=GETTIMERALL()-self.AppTime_PauseStart
INC self.AppTime_LastUpdateTime,elapsed
ENDIF
self.AppTime_PauseStart=0.0
self.Update()
ENDIF
ENDIF
ENDFUNCTION
//! This function returns the updates per second, and is an approximation
//\param No parameters are passed
//\return Updates per second
FUNCTION UPS:
RETURN self.AppTime_UPS
ENDFUNCTION
ENDTYPE
No, can't say I have... They are very smooth here.
Do you have debug mode on ? Any intensive hard drive activity ?
Hmm seems to run ok on my PC. If you are talking about jerkiness every once in a while, then sometimes there looks like there is a tiny little bit. Really though mine pretty much mimics the movie Mr TA Toad has posted.
Seems to run quite well on my extremely low end Android tablet too, although one square finishes way ahead of the other. :)
For me it is very jerky in the code and in the video. I had the same problem, even with older versions. I used to never have slow movements :)
Now I solved it somehow. I changed 2 things and donĀ“t know which one changed it.
1. Instead of using GETTIMER() I use GETTIMERALL() to get the time since last showscreen (timer=GETTIMERALL()- lasttime)
2. I calculate time, positions and have all gamelogic in as many fps as it gets. Just drawing and SHOWCREEN is every 1000/60.
LIMITFPS 500
WHILE GAMESTATE = STATE_GAME
WHILE Usedtime <= FrameTime
//do everything
INC UsedTime,timer
WEND
//draw everything
SHOWSCREEN
WEND
Mmm, yeah, that video is showing the exact same behaviour as as the two PC's I've tested it on. Maybe I'm remembering how smooth it was with rose tinted glasses because I'm sure it was less "jumpy" than that.
In fact, I've justed tried it with my work PC, which has an older version of GLB, IDE 10.113, and while the first run wasn't very smooth and was similar to the video, subsequent runs were, so maybe my home PC is doing loads of rubbish in the background.
I'll have to try it on a phone or something that won't have anything running in the background.