Ballistic Motion

Ballistic motion is motion that is affected by gravity. Imagine a ball thrown up into the air that rises to its maximum height and then comes back down. For simplicity, we'll ignore winds and friction with the air.
To write a program that simulates ballistic motion, we'll start with the simple, vector motion of a ball model.
Notes Code and Results

Motion without gravity.

We have a ball moving upward (in the y-direction) at 5 m/s, so its velocity vector is: $$ \vec{v} = <0, 5, 0> $$
Notice that:
  • Line 1:
    
                      scene.range = 10
                    
    Sets a constant field of view so we don't automatically zoom in or out as the ball moves.
The core of the model are lines 24 and 25:

            ball.pos.x = ball.pos.x + ball.v.x * dt
          
These equations for the position comes from the fact that, as we all know, velocity is the change in distance over time. Considering only motion in the x direction (vx): $$ v_x = \dfrac{\Delta x}{\Delta t} $$ We can write the change in distance (Δx) as the difference in the old and new positions: $$ v_x = \dfrac{x_{new} - x_{old}}{\Delta t} $$ Therefore, if we know the velocity (v), the time step (Δt), and the starting position (xold), then we can solve this equation to find the new position (xnew). $$ x_{new} = x_{old} + v_x \cdot \Delta t \tag{1}$$ This could be read as: the new position is equal to the old position plus the change in position.

There is no motion in the x direction, but the same general equation applies in y, so:


            ball.pos.y = ball.pos.y + ball.v.y * dt
          

              scene.range = 10

              ball = sphere(radius=0.5)

              ball.v = vector(0, 5, 0)

              ball.arrow = arrow(pos = ball.pos, axis = ball.v, shaftwidth=0.2)
              ball.vx_arrow = arrow(pos = ball.pos,
                                    axis = vec(ball.v.x, 0, 0),
                                    color=color.red,
                                    shaftwidth=0.2)
              ball.vy_arrow = arrow(pos = ball.pos + ball.vx_arrow.axis,
                                    axis = vec(0, ball.v.y, 0),
                                    color=color.yellow,
                                    shaftwidth=0.2)

              dt = 0.05

              while True:
                  sleep(dt)
                  sleep(1)

                  # update ball position based on velocity vector
                  ball.pos.x = ball.pos.x + ball.v.x * dt
                  ball.pos.y = ball.pos.y + ball.v.y * dt

                  #update positions of the arrows
                  ball.arrow.pos = ball.pos
                  ball.vx_arrow.pos = ball.pos
                  ball.vy_arrow.pos = ball.pos + ball.vx_arrow.axis
                  # update directions of arrows
                  ball.arrow.axis = ball.v
                  ball.vx_arrow.axis = vec(ball.v.x, 0, 0)
                  ball.vy_arrow.axis = vec(0, ball.v.y, 0)
            
The result should look like:
result

Adding gravity (acceleration)

Acceleration is the change in velocity (Δv) with time (Δt) so: $$ a = \dfrac{v_{new} - v_{old}}{\Delta t} $$ So for each timestep, we'll solve this equation for the new velocity (vnew ): $$ v_{new} = v_{old} + a \cdot \Delta t \tag{1}$$ The acceleration due to gravity (g) is: $$ a = g = -9.8 \, \text{m/s}^2 $$ So, for vertical, ballistic motion we can write the equation as: $$ v_{new} = v_{old} + g \cdot \Delta t \tag{2}$$ We can add this as a single line to the previous program, before we calculate the new position.
  • Line 23:
    
                      ball.v.y = ball.v.y - 9.8 * dt
                    

            scene.range = 10

            ball = sphere(radius=0.5)

            ball.v = vector(0, 10, 0)

            ball.arrow = arrow(pos = ball.pos, axis = ball.v, shaftwidth=0.2)
            ball.vx_arrow = arrow(pos = ball.pos,
                                  axis = vec(ball.v.x, 0, 0),
                                  color=color.red,
                                  shaftwidth=0.2)
            ball.vy_arrow = arrow(pos = ball.pos + ball.vx_arrow.axis,
                                  axis = vec(0, ball.v.y, 0),
                                  color=color.yellow,
                                  shaftwidth=0.2)

            dt = 0.05

            while True:
                sleep(dt)
                #sleep(1)

                # update velocity based on gravitational acceleration
                ball.v.y = ball.v.y - 9.8 * dt

                # update ball position based on velocity vector
                ball.pos.x = ball.pos.x + ball.v.x * dt
                ball.pos.y = ball.pos.y + ball.v.y * dt

                #update positions of the arrows
                ball.arrow.pos = ball.pos
                ball.vx_arrow.pos = ball.pos
                ball.vy_arrow.pos = ball.pos + ball.vx_arrow.axis
                # update directions of arrows
                ball.arrow.axis = ball.v
                ball.vx_arrow.axis = vec(ball.v.x, 0, 0)
                ball.vy_arrow.axis = vec(0, ball.v.y, 0)


          

Add a floor

Add a floor to your model so the ball bounces.
result