A common game requirement is to synchronize numerous elements with a time line. For example a ball moving by 200 pixels in 2 seconds.

We have several possible approaches, this article will examine two especially :

• a simple and classic imprecise approach.
• a second approach with a more precise timeline.

# The simple method

The simple, commonly used. method is to calculate the time to wait for each one pixel move. In our case, 2 seconds equals 2000 milliseconds and so we move to one pixel every 10 ms (2000 ms / 200 pixels). In a loop we move the ball to one pixel and we wait 10 ms, repeatedly 200 times, we will move our ball to 200 pixels in 2 seconds:

`' Move delay in ms`
`delay ````= ````2000`
`' Move width in pixel`
`move ````= ````200`
` `
`' Create the ball`
`GraphicsWindow``.``Show``(``)`
`ball ````= ````Shapes``.``AddEllipse``(``20``,``20``)`
`ballPos ` `= ``0`
`Shapes``.``Move``(``ball````, ````10 ``+ ` `ballPos``,``10``)`
` `
`' Reference the time`
`start ````= ````Clock``.``ElapsedMilliseconds`
`' Loop`
```For ````i ``= ` `1 ````To ````move`
`  ``' Move the ball to one pixel`
`  ````ballPos ````= ``ballPos ` `+ ``1`
`  ``Shapes``.``Move``(``ball````, ````10 ``+ ` `ballPos``,``10``)`
`  ``' We wait delay/move milliseconds`
`  ``Program``.``Delay``(``delay``/``move``)`
`EndFor`
`' Calculate the real time used`
`GraphicsWindow``.````Title ````= ``Clock``.````ElapsedMilliseconds ````- ``start`
` `

If we run the program, our ball apparently moves to 200 pixels in 2 seconds, but if we look at the windows title where we display the final time elapsed, we can see that it show a longer time spent.

Why the difference?
Simply because our program does not only wait, it moves the ball, and makes some calculations.  All this takes time, and the sum of these is greater than our 2 seconds. Someone with a more powerful computer ill see a lower gap, On the other hand someone using a slower computer will see a larger difference. In a real game, there user will also interact and use the mouse or keyboard which will require processing that could also "slow down" our program even more.

Our ball will therefore not really be where it should be because of that time difference.

This lack of precision is not always a problem in a game, but if we want to make a quiz with a stopwatch, and we want that all players have the same opportunities, we cannot be satisfied with this, or players who will have a less powerful computer will have more time to respond :)

This method also has a second issue, let us imagine the case where we have several elements that move differently (not at the same speed for example), how to manage the time for each of the items? This method is likely to introduce strange interactions in such a scenario.

# A more precise time line

To solve our problem of precision regardless of the computer or the time consumed by the program for these calculations, we have another available approach: the timeline concept.

A time line represents the time that "runs" for our game. At any time in the game it is able to tell us where we are compared with the beginning of the timeline, and so we can determine which state we are supposed be in our game.

If we take my example with the ball, when I'll be at 500 ms in the timeline, I known my ball will be at 50 pixels from the origin, and at 1500 ms it's 150 pixels.

In Small Basic this is simple to simulate a timeline. We use "Clock.ElapsedMilliseconds" which returns the milliseconds from the 1st January 1900. If we save the value when we start the timeline :

`startTimeline``=``Clock``.``ElapsedMilliseconds`
` `

then if we want to known where we are in the timeline, we just do a subtract :

`timeline``=``Clock``.``ElapsedMilliseconds``-``startTimeline`
` `

Take our moving ball and this time move it based on the timeline for more precision.

`' Move delay in ms`
`delay ````= ````2000`
`' Move width in pixel`
`move ````= ````200`
` `
`' Create the ball`
`GraphicsWindow``.``Show``(``)`
`ball ````= ````Shapes``.``AddEllipse``(``20``,``20``)`
`ballPos ` `= ``0`
`Shapes``.``Move``(``ball````, ````10 ``+ ` `ballPos``,``10``)`
` `
`' Start the timeline`
`startTimeline ` `= ``Clock``.``ElapsedMilliseconds`
`' Loop`
```While ````ballPos ``< ` `move`
`  ``' Where we are in the timeline ?`
`  ````timeline ````= ``Clock``.````ElapsedMilliseconds ````- ``startTimeline`
`  ``' Calculate the ball position based on the timeline`
`  ````ballPos ````= ``(````timeline ````* ``move````) ````/ ``delay`
`  ``' Move the ball`
`  ``Shapes``.``Move``(``ball````, ````10 ``+ ` `ballPos``,``10``)`
`  ``' Simulate a long calculation to disrupts our program`
`  ````If ````ballPos ``< ` `move``/````2 ````Then`
`    ``Program``.``Delay``(``Math``.``GetRandomNumber``(``150``)``)`
`  ``EndIf`
`EndWhile`
`' Calculate the real time used`
`GraphicsWindow``.````Title ````= ``Clock``.````ElapsedMilliseconds ````- ``startTimeline`
` `

If we run this program we find that the gap disappear.

Yet in the first part of the distance I do random breaks, it is found as the ball "stutters", but it always comes back to the place that is hers from the timeline.

To calculate the position of the ball just make a cross multiplication :

```    2000 ms (delay) => 200 pixels (move)
timeline => ballPos
```

so

`ballPos``=``(``move``*``timeline``)``/``ballPos`
` `

# Elapsed time

So our ball is sync with our timeline.This example is so simple, in a real game, having to recalculate a situation since the beginning of the timeline is not always the best option.

Sometimes it's better to calculate the time elapsed between two consultations of the timeline. With our ball, rather than calculate the position according to the timeline on each iteration of the loop, we will calculate the time that has elapsed since the last loop, then we will calculate the number of pixels that our ball would having traveled in that time.

`' Move delay in ms`
`delay ````= ````2000`
`' Move width in pixel`
`move ````= ````200`
` `
`' Create the ball`
`GraphicsWindow``.``Show``(``)`
`ball ````= ````Shapes``.``AddEllipse``(``20``,``20``)`
`ballPos ` `= ``0`
`Shapes``.``Move``(``ball````, ````10 ``+ ` `ballPos``,``10``)`
` `
`' Start the timeline`
`startTimeline ` `= ``Clock``.``ElapsedMilliseconds`
`lastTimeline ` `= ``0`
`' Loop`
```While ````ballPos ``< ` `move`
`  ``' Where we are in the timeline ?`
`  ````timeline ````= ``Clock``.````ElapsedMilliseconds ````- ``startTimeline`
`  ``' Calculate the elapsed time`
`  ````elapsed ````= ``timeline ` `- ``lastTimeline`
`  ``' Calculate the ball movement in the elapsed time`
`  ````ballMovement ````= ``(````elapsed ````* ``move````) ````/ ``delay`
`  ``' Add the movement at the ball position`
`  ````ballPos ````= ``ballPos ` `+ ``ballMovement`
`  ``' Move the ball`
`  ``Shapes``.``Move``(``ball````, ````10 ``+ ` `ballPos``,``10``)`
`  ``' Simulate a long calculation to disrupts our program`
`  ````If ````ballPos ``< ` `move``/````2 ````Then`
`    ``Program``.``Delay``(``Math``.``GetRandomNumber``(``150``)``)`
`  ``EndIf`
`  ``' Save the timeline for next loop`
`  ````lastTimeline ````= ``timeline`
`EndWhile`
`' Calculate the real time used`
`GraphicsWindow``.````Title ````= ``Clock``.````ElapsedMilliseconds ````- ``startTimeline`
` `

This method is required in some cases. Imagine that our ball moves according to the keyboard keys pressed by the player, it is impossible to calculate the position of the ball since the beginning of the timeline. On the other hand make this calculation based on the elapsed time can work.

`' Move delay in ms`
`delay ````= ````2000`
`' Move width in pixel`
`move ````= ````200`
` `
`' Create the ball`
`GraphicsWindow``.``Show``(``)`
`ball ````= ````Shapes``.``AddEllipse``(``20``,``20``)`
`ballPos ` `= ``0`
`ballPosX ` `= ``0`
`ballPosY ` `= ``0`
`offX ````= ````1`
`offY ````= ````0`
`Shapes``.``Move``(``ball````, ````10 ``+ ` `ballPosX``,````10 ````+ ``ballPosY``)`
` `
`' Handle the key press`
`GraphicsWindow``.````KeyDown ````= ``OnKeyDown`
` `
`' Start the timeline`
`startTimeline ` `= ``Clock``.``ElapsedMilliseconds`
`lastTimeline ` `= ``0`
`' Loop`
```While ````ballPos ``< ` `move`
`  ``' Where we are in the timeline ?`
`  ````timeline ````= ``Clock``.````ElapsedMilliseconds ````- ``startTimeline`
`  ``' Calculate the elapsed time`
`  ````elapsed ````= ``timeline ` `- ``lastTimeline`
`  ``' Calculate the ball movement in the elapsed time`
`  ````ballMovement ````= ``(````elapsed ````* ``move````) ````/ ``delay`
`  ``' Add the movement at the ball position`
`  ````ballPos ````= ``ballPos ` `+ ``ballMovement`
`  ````ballPosX ````= ``ballPosX ` `+ ``(````ballMovement ````* ``offX``)`
`  ````ballPosY ````= ``ballPosY ` `+ ``(````ballMovement ````* ``offY``)`
`  ``' Move the ball`
`  ``Shapes``.``Move``(``ball````, ````10 ``+ ` `ballPosX``,````10 ````+ ``ballPosY``)`
`  ``' Simulate a long calculation to disrupts our program`
`  ````If ````ballPos ``< ` `move``/````2 ````Then`
`    ``Program``.``Delay``(``Math``.``GetRandomNumber``(``150``)``)`
`  ``EndIf`
`  ``' Save the timeline for next loop`
`  ````lastTimeline ````= ``timeline`
`EndWhile`
`' Calculate the real time used`
`GraphicsWindow``.````Title ````= ``Clock``.````ElapsedMilliseconds ````- ``startTimeline`
` `
```Sub ````OnKeyDown`
`  ````If ````GraphicsWindow``.````LastKey ````= ``"Up" ` `Then`
`    ````offX ````= ``0`
`    ````offY ````= ``-``1`
`  ````ElseIf ````GraphicsWindow``.````LastKey ````= ``"Down" ` `Then`
`    ````offX ````= ``0`
`    ````offY ````= ``1`
`  ````ElseIf ````GraphicsWindow``.````LastKey ````= ``"Left" ` `Then`
`    ````offX ````= ``-``1`
`    ````offY ````= ``0`
`  ````ElseIf ````GraphicsWindow``.````LastKey ````= ``"Right" ` `Then`
`    ````offX ````= ``1`
`    ````offY ````= ``0`
`  ``EndIf`
`EndSub`
` `

Our ball move always to 200 pixels in 2 seconds, but if we pressed the arrow keyboard keys our ball changes direction.

# A timeline for each

In a game based all on once timeline is not necessarily the most practical thing.

The first reason is we often need to restart a timeline, for example when we press a key that move acharacter to 100 pixels, we will start a new timeline for the movement calculation to known where is it based on the timeline.

Each element in a game will have its own timelines according to these needs. For example a timeline to calculate its current movement, and a timeline for calculating an animation. The game itself often have a timeline, for the game time for example.

`' Build the game board`
`GraphicsWindow``.``Show``(``)`
`GraphicsWindow``.````KeyDown ````= ``OnKeyDown`
`gameTitle ` `= ``Shapes``.``AddText``(``""``)`
` `
`' First element : a ball`
`elm``[``0``]``[``"shape"````] ````= ``Shapes``.``AddEllipse``(``20``,``20``)`
`elm``[``0``]``[``"x"````] ````= ``40`
`elm``[``0``]``[``"y"````] ````= ``40`
`elm``[``0``]``[``"startTimeline"````] ````= ``-``1`
`elm``[``0``]``[``"timeline"````] ````= ``-``1`
`Shapes``.``Move``(``elm``[``0``]``[``"shape"``]````, ````elm``[``0``]``[``"x"``]````, ````elm``[``0``]``[``"y"``]``)`
` `
`' Second element : a box`
`GraphicsWindow``.````BrushColor ````= ``"Yellow"`
`elm``[``1``]``[``"shape"````] ````= ``Shapes``.``AddRectangle``(``20``,``20``)`
`elm``[``1``]``[``"x"````] ````= ``40`
`elm``[``1``]``[``"y"````] ````= ``140`
`elm``[``1``]``[``"startTimeline"````] ````= ``Clock``.``ElapsedMilliseconds`
`elm``[``1``]``[``"timeline"````] ````= ``-``1`
`Shapes``.``Move``(``elm``[``1``]``[``"shape"``]````, ````elm``[``1``]``[``"x"``]````, ````elm``[``1``]``[``"y"``]``)`
` `
`' Init the game`
`gameStartTime ` `= ``Clock``.``ElapsedMilliseconds`
`gameTime ` `= ``0`
` `
`' Game loop`
```While ````"True"`
`  ``' Game timeline calculation`
`  ````gameTime ````= ``Clock``.````ElapsedMilliseconds ````-  ``gameStartTime`
` `
`  ``' Display the title`
`  ````title ````= ````"Game Time : " ````+ ``Math``.``Floor``(````gameTime ````/ ``1000````) ````+ ``" seconds"`
`  ````title ````= ``title ` `+ ``" | Ball : " ` `+ ``elm``[``0``]``[``"timeline"``]`
`  ````title ````= ``title ` `+ ``" | Box : " ` `+ ``elm``[``1``]``[``"timeline"``]`
`  ``Shapes``.``SetText``(``gameTitle````, ````title``)`
` `
`  ``' Calculate the timeline for each element`
`  ````For ````i ``= ` `0 ````To ````1`
`    ````stl ````= ``elm``[``i``]``[``"startTimeline"``]`
`    ````If ````stl ``> ` `0 ``Then`
`      ``elm``[``i``]``[``"timeline"````] ````= ``Clock``.````ElapsedMilliseconds ````- ``stl`
`    ``EndIf`
`  ``EndFor`
` `
`  ``' Calculate the pulse of the ball`
`  ````If ````elm``[``0``]``[``"timeline"````] ````> ``0 ` `Then`
`    ````zoom ````=``1``+``(``0.5``*``Math``.``Sin``(``elm``[``0``]``[``"timeline"``]``/``100``)``)`
`    ``Shapes``.``Zoom``(``elm``[``0``]``[``"shape"``]````, ````zoom``, ` `zoom``)`
`  ``EndIf`
` `
`  ``' Calculate the rotation of the box : One turn in two seconds`
`  ``Shapes``.``Rotate``(``elm``[``1``]``[``"shape"``]````, ````Math``.``Remainder``(``(``elm``[``1``]``[``"timeline"``]``/``(````1000 ````* ``2``)````) ````* ``360````, ````360``) ` `)`
` `
`  ``' We pause the computer`
`  ``Program``.``Delay``(``50``)`
`EndWhile`
` `
`' Handle the keyboard`
```Sub ````OnKeyDown`
`  ``' If press Escape quit the game`
`  ````If ````GraphicsWindow``.````LastKey ````= ``"Escape" ` `Then`
`    ``Program``.``End``(``)`
`  ``EndIf`
`  ``' If pressed space bar, enable/disable the pulse of the ball`
`  ````If ````GraphicsWindow``.````LastKey ````= ``"Space" ` `Then`
`    ````If ````elm``[``0``]``[``"startTimeline"````] ````> ``0 ` `Then`
`      ``elm``[``0``]``[``"startTimeline"````] ````= ``-``1`
`      ``elm``[``0``]``[``"timeline"````] ````= ``-``1`
`    ``Else`
`      ``elm``[``0``]``[``"startTimeline"````] ````= ``Clock``.``ElapsedMilliseconds`
`      ``elm``[``0``]``[``"timeline"````] ````= ``0`
`    ``EndIf`
`  ``EndIf`
`EndSub`
` `

In this example, we have three timelines, one for the game which display the time elapsed from the start of the game. A second timeline for the "Ball" object which start when we press the space bar. The last timeline is for the "Box" for the rotation calculation.

# Conclusion

The timelines are used to managed movement, animations, visual effects, etc.

So according to your need, feel free to use one or more of these techniques.

You can retrieve all the sample in the GitHub repos https://github.com/Small-Basic-French/Exemples/tree/master/Timeline.