Throwing ball on PowerApps


In many games, it is very important to naturally realise physical phenomena such as jumps, collisions, reflections, and bounds.
My previous post, it has been shown that the motion of projectile with air resistance and gravity can be realized on PowerApps.

In this post, I would explain how we can treat bounce and reflection events on PowerApps.
In addition to the implementation on PowerApps, will refer to a basic approach for these events with some mathematical expressions.

Physics

Throwing ball

First, the motion of throwing ball is described by Equation of motion for Projectile with gravity and air resistance.

It is very important to estimate velocity u(t) and v(t) in order to realise bounce and reflection.
Next, we consider the event of bounce and reflection, it is not much difficult.

Bounce

Both before & after the bounce, the motion of ball is given by EoM of projectile.
The only difference is its velocity.

As you can find from following figure, vertical component of velocity is flipped after the bounce, and (may) bit decreased which is expressed by ε*.
* ε : coefficient of restitution.
Value of ε is determined by material of floor/wall. If floor is made by metal, ε is almost 1 (no velocity loss), but if floor is dirt, ε becomes much smaller than 1.


So, the motion of ball after bounce is projectile motion with initial velocity ua and va

Reflection

As is the case in bounce, the effect of reflection is simply realised by following relation. In contrast to the case of bounce, horizontal component of velocity becomes opposite to one before reflection.

PowerApps

Now, you can implement these motion and effects into PowerApps!
Fine things aside, my app is constructed by 3 objects (ball, wall, and floor)+ 1 timer control.

X and Y Properties of ball object are as;

Ball.X
X0+ (vx0/AirResist.Text)* (1-Exp(-1*AirResist.Text * T))
Ball.Y
Y0-(vy0/AirResist.Text)*(1+GravityConst.Text/(AirResist.Text*vy0)) * (1-Exp(-1*AirResist.Text * T)) + GravityConst.Text * T/AirResist.Text

where X0, Y0 are initial position of ball, and vx0 , vy0 are initial velocity.

In order to move ball object, context variable T (time) is updated on every timer end;

Timer.OnTimerEnd
T: T + Timer.Duration/1000

Typically Timer.Duration is 50~100 millisecond. The ball now moves, but not sufficient.
We have to implement the effect of bounce and reflection. The whole block of code for OnTimerEnd is given by;

Timer.OnTimerEnd
If(
    //[Reflection] 
    //1. Flip sign of velocity X and set as initial velocity vx0
    //2. Initialize time T (Recast @next OnTimerEnd)
    Xnow > MainScreen.Width-Wall.Width-Ball.Width,
    UpdateContext(
        {
            T:0,
            vx0: -1.0*vxnow* (100-VelocityLoss.Text)/100,
            vy0: vynow,
            X0: Ball.X,
            Y0: Ball.Y,
            Xnow: Ball.X
        }
    ),
    If(
        //[Bounce] 
        //1. Flip sign of velocity Y and set as initial velocity vy0
        //2. Initialize time T (Recast @next OnTimerEnd)
        Ynow > MainScreen.Height-Floor.Height-Ball.Height,
        UpdateContext(
            {
                T: 0,
                X0: Ball.X,
                Y0: Ball.Y,
                vx0: vxnow,
                vy0: -1.0*vynow * (100-VelocityLoss.Text)/100,
                Ynow: Ball.Y
            }
        ),
        UpdateContext(
            {
                vxnow: vx0 * Exp(-1 * AirResist.Text * (T+Timer.Duration/1000)),
                vynow: vy0 * (1 + GravityConst.Text/(AirResist.Text * vy0)) * (Exp(-1 * AirResist.Text * (T + Timer.Duration/1000))) - GravityConst.Text/AirResist.Text,
                //Xnow,Ynow show the position of Ball at the next step
                Xnow: X0 + (vx0/AirResist.Text) * (1-Exp(-1 * AirResist.Text * (T + 2*Timer.Duration/1000))),
                Ynow: Y0-(vy0/AirResist.Text) * (1 + GravityConst.Text/(AirResist.Text * vy0)) * (1-Exp(-1 * AirResist.Text * (T + 2*Timer.Duration/1000))) + GravityConst.Text * (T + 2*Timer.Duration/1000)/AirResist.Text,
                T: T + Timer.Duration/1000
            }
        )
    )
)

First part of above, Xnow > MainScreen.Width-Wall.Width-Ball.Width, determine whether the ball collides with wall or not. It true, set current velocity/position into initial velocity/position for next projectile.
Also, second part, Ynow > MainScreen.Height-Floor.Height-Ball.Height, determine the condition of bounce event. If true, as in the case of reflection, set current velocity/position into initial velocity/position for next projectile.

That's all physics and implementation of My App!
You can download this app from PowerApps Community Gallery !