Flappy Bird

It’s everyone’s favourite reaction-based mobile game, rebuilt in Power Apps!

This makes use of parallax scrolling, as demonstrated in my side scrolling endless runner game, but works in some more animation control of the avatar/bird which wants to constantly fall to the bottom of the screen.


Watch the video below to see my setup. I am using four timers here:

  • tmrScroll, which controls the parallax animation
  • tmrCollision, which checks for intersections between the avatar and the pipe obstacles
  • tmrRise, which lasts a fixed 300ms and executes when the screen is tapped, and animates the upward movement of the avatar
  • tmrFall, which does the opposite, and lasts 1300ms, meaning the bird takes just over a second to hit the bottom from any position


The Rise and Fall timers are referenced in the Y property of the avatar. Tapping the screen resets and starts the rise timer and stops and resets the fall timer. Once the rise timer ends, it starts the fall timer. For ease, I also set variables according to these events.

With(
    {
        // number of pixels a single rise will add to bird Y-pos
        RiseAmt:varRise,
        // number of pixels to fall to bottom of screen
        // this changes based on bird position but will always take same amount of time - falling from a larger height means higher acceleration
        FallAmt:Parent.Height - currY
    },
    // are we rising or falling?
    Switch(
        true,

        // rising
        StartRise,
        currY - (RiseAmt * (tmrRise.Value / tmrRise.Duration) * (2 - (tmrRise.Value / tmrRise.Duration))),

        // falling
        StartFall,
        currY + (FallAmt * (tmrFall.Value / tmrFall.Duration)),
        //currY + (FallAmt * (tmrFall.Value / tmrFall.Duration) * (1 - (tmrFall.Value / tmrFall.Duration))),

        // neither timer in play, just use current Y-pos
        currY
    )
)


I use a multiplier in the animation code to apply acceleration to the rise. Let’s break it down:

currY - (RiseAmt * (tmrRise.Value / tmrRise.Duration) * (2 - (tmrRise.Value / tmrRise.Duration))


currY is a variable that is set when the screen is tapped. It saves the current Y position of the avatar so that we can use it as a base for the animations.

RiseAmt/varRise are placeholders for the height of a ‘jump’ when the screen is tapped. I set this as a variable so it can be easily tweaked when debugging.

Dividing the timer value by its duration gives me a number between 0 and 1 which I can multiply the rise amount by to get the distance of travel. This is then subtracted from the recorded Y position to make the avatar ‘rise’ up the screen (smaller Y values being further up).

By subtracting the ratio of timer value vs duration from 2, I get a number between 2 and 1 that tends towards 1. When I multiple this with the rise amount, we get an animation that starts off fast (when it’s being multiplied by ~2) and slows down towards the end (when the multiplier gets close to, or is, 1).

This gives us a simple and effective way of simulating acceleration/deceleration without complex mathematics. The same could be done using the trigonometry functions but in a far less readable way.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *