News:

Function Finder  Find all the functions within source code files

Main Menu

Timer Based Movement - Frame Rate Independent Motion Example

Started by kevin, September 26, 2024, 11:57:23 AM

Previous topic - Next topic

kevin

  Timer Based Movement - Frame Rate Independent Motion Example


  This PlayBASIC code snippet shows how to make moving objects (balls) in a game move independently of the frame rate, meaning the movement looks consistent regardless of how fast or slow the game runs. This is achieved by using timers to calculate the position of each ball based on elapsed time rather than relying on the game's frame rate.

How It Works:

1. Setting Frame Rate Goals:

  - The program sets a target frame rate of 50 frames per second (FPS) and calculates how many milliseconds each frame should last (`1000 / 50 = 20ms` per frame).

2. Ball Setup:

  - The balls are defined using a custom type (`tBALL`) which includes properties like position (`X`, `Y`), size, color, speed, direction, and the time when the ball was created.

3. Adding Balls:

  - Balls are randomly generated within the display area with random sizes, colors, speeds, and directions. New balls are added every 50 milliseconds, creating a dynamic scene.

4. Moving the Balls:
  - The balls' positions are updated based on how much time has passed since each ball was created. This is calculated using the elapsed time and the ball's speed. The movement calculations are independent of the frame rate, making the motion consistent.

5. Rendering and Removal:
  - Each ball is drawn on the screen at its updated position. If a ball moves outside the display area, it's removed from the scene.

6. Display Information:
  - The program shows the current number of balls and the actual frames per second (FPS) at the top of the screen.

This approach ensures that the motion of the balls remains smooth and consistent, even if the game's performance varies. It's a great demonstration of using time-based calculations for movement, which is a valuable technique in game development to maintain consistency across different devices and frame rates.



PlayBASIC Code: [Select]
    // Ste our ideal  Required frames per second rate
Frame_RATE# = 50

// Ticks per frame
Frame_RATE_MILLISECOND_PER_FRAME# = 1000.0/Frame_RATE#


Type tBALL
X#
Y#
Size
Colour
Speed#
Direction#
StartTime
EndType

Dim Ball as TBall List

CurrentTime = timer()

Do

Cls

CurrentTime= Timer()

// Randomly Add more balls to the scene
if Add_Balls < CurrentTime

for lp =1 to rndrange(100,500)
Ball = new tBall
Ball.x = rndrange(100,GetsurfaceWidth()-100)
Ball.y = rndrange(100,GetsurfaceHeight()-100)
Ball.size = rndrange(10,20)
Ball.Colour = rndrgb()
Ball.Speed = rndrange#(1, 5)
Ball.Direction = rnd#(360)
Ball.StartTime = CurrentTime
next
Add_Balls=CurrentTime+50
endif

// Draw Balls
lockbuffer
For each Ball()

// How long as this ball been alive and move in this direction?
ElapsedTime = CurrentTime-Ball.StartTime

// compute how far this ball have moved since creation
Dist#= (Ball.Speed /Frame_RATE_MILLISECOND_PER_FRAME#) * ElapsedTime

// Compute the moved position from it's origin point
x#=Ball.x+cos(ball.direction)*Dist#
y#=Ball.y+sin(ball.direction)*Dist#


// check if the ball is on screen or not ?
// if not; delete it from the list
if x#<(-ball.size) or x#>(getSurfaceWidth()+ball.size) or y#<(-ball.size) or y#>(getSurfaceHeight()+ball.size)
Ball=null
continue
endif

// draw the ball since it's still visible
circlec x#,Y#,ball.size,true,ball.colour

Next
unlockbuffer

text 10,10,"Balls #"+str$(GetListSize(Ball()))
text 10,20," Fps #" +str$(fps())

sync

Loop spacekey()






 


kevin

  I little effect for something fun to look at :)


Source Code Bellow: Just Some Circles




PlayBASIC Code: [Select]
    Screen=NewImage(getSurfaceWidth(),GetSurfaceHeight(),2)

// Ste our ideal Required frames per second rate
Frame_RATE# = 50

// Ticks per frame
Frame_RATE_MILLISECOND_PER_FRAME# = 1000.0/Frame_RATE#


Type tBALL
X#
Y#
Size
Colour
Speed#
Direction#
StartTime
Mode
EndType



Dim Ball as TBall List

Dim Modes(1)
Modes(0)= 1+64
Modes(1)= 1+128

CurrentTime = timer()

Do


CurrentTime= Timer()

// Randomly Add more balls to the scene
if Add_Balls < CurrentTime

for lp =1 to rndrange(50,250)
Ball = new tBall
Ball.x = (GetsurfaceWidth()/2)-rnd(30)
Ball.y = (GetsurfaceHeight()/2)-rnd(30)
Ball.size = rndrange(10,100)
Ball.Colour = rndrgb() and $0f0f0f
Ball.Speed = rndrange#(1, 5)
Ball.Direction = rnd#(360)
Ball.StartTime = CurrentTime
Ball.Mode = Modes(lp&1)
next
Add_Balls=CurrentTime+50
endif


rendertoimage screen
Cls
inkmode 1+64
// Draw Balls
lockbuffer
For each Ball()

// How long as this ball been alive and move in this direction?
ElapsedTime = CurrentTime-Ball.StartTime

// compute how far this ball have moved since creation
Dist#= (Ball.Speed /Frame_RATE_MILLISECOND_PER_FRAME#) * ElapsedTime

// Compute the moved position from it's origin point
x#=Ball.x+cos(ball.direction)*Dist#
y#=Ball.y+sin(ball.direction)*Dist#


// check if the ball is on screen or not ?
// if not; delete it from the list
if x#<(-ball.size) or x#>(getSurfaceWidth()+ball.size) or y#<(-ball.size) or y#>(getSurfaceHeight()+ball.size)
Ball=null
continue
endif

Inkmode Ball.Mode

// draw the ball since it's still visible
circlec x#,Y#,ball.size,true,ball.colour

Next
unlockbuffer


rendertoscreen
drawimage Screen,0,0,false

sync

Loop spacekey()