Tutorial: Incrementing score counter

Tutorial: Incrementing score counter

When you complete a level in a video game, it often shows your score in an animated fashion. Sometimes this involves the numbers “spinning” in such a way that they count up from the 1s column to the 10s column and so on, like an odometer of a car but much faster.


Achieving this effect in Corona begins with some simple math. Let’s jump directly into some code:

The first thing to understand is that Corona is a frame-based system. This means that the screen updates essentially at a fixed pace. By default, this pace is 30 times per second, usually referred to as 30 frames per second (“fps”). Corona can also run at 60 fps, which many developers choose for a smoother look.

At 60 fps, the screen can only update every 1/60th of a second (16.6667 milliseconds). At 30 fps, the screen can only update every 1/30th of a second (33.3333 milliseconds). Trying to force a faster update rate is an exercise in futility.

Controlling the rate

Obviously, game scores can vary greatly — one game may have a maximum score of 12 while another will have a maximum score in the millions. Thus, we don’t want our function to count up by a fixed amount like 1 on each frame update. If so, a score in the millions would take too long to update, while a score like 12 would finish far too quickly.

A better solution is to determine how long the animation should run and then calculate the amount that it should increment on each frame update. In this example, the score will have 2 seconds to spin up from 0 to the final value. For an app set to run at 30 fps, this means that there will be 60 total updates.

Determining the passes and increment

First we need to figure out how many “passes” are required. This value is simply the time in milliseconds (duration) divided by the frame rate of the app (fps).

Next, we need to determine the amount to increment the score by. This is done via a method called lerp which stands for linear interpolation. This method basically allows you to compute intermediate points between two values based on some criteria.

In our example, the lerp function is straightforward. We take the difference between the start and stop values (v1-v0) and multiply it by the fraction of the time we want to know the increment for — in this case, 1/passes since we know how many iterations we need over the span 2 seconds. Then we add that to the start value (v0).

The showScore() function

The actual showScore() function requires four arguments:

  1. The display.newText() text object that will be updated.
  2. The “final value” to show for that text object, for example, the score the player achieved.
  3. The duration of the count-up routine in milliseconds.
  4. The frame rate of the app.

Inside the function, we set a temporary value, newScore, so the score displays to zero. We also use the duration and frame rate to calculate the number of required passes. All of this is computed inside of a Runtime "enterFrame" listener that will fire every frame. Finally, we use a counter to track the number of passes.

When the loop is done incrementing, we need to adjust for any fractional remainder of the final score. This is done simply by setting the text object to the final value.


Hopefully this tutorial gets you started with a classic “spinning score counter” feature for your game. If so inclined, you could easily extend the showScore() function to accept both duration and fps values instead of using the static values for the timers.

Rob Miracle

Rob Miracle creates mobile apps for his own enjoyment and the amusement of others. He serves the Corona Community in the forums, on the blog, and at local events.

  • Lerg
    Posted at 03:59h, 30 July

    I’ve made a followup pro tip on how to use transition.to() and metatables to achieve such animation.


    • Munky
      Posted at 11:20h, 30 July

      Brilliant Sergey, thanks!

    • Rob Miracle
      Posted at 15:17h, 30 July

      I may like you’re version better than mine.

      • Lerg
        Posted at 07:58h, 31 July

        Thank you!

  • ouguolin
    Posted at 20:08h, 30 July

    Very good tutorial!

    but I believe it’s a bug in this line:

    local passes = duration / fps

    it works if fps is 30 but wont work if fps is other values 🙂 and here is my fixing:

    local passes = duration * fps
    duration is in seconds and fps is in frames per second.

    • Kenny Tee
      Posted at 21:37h, 29 November

      You’re right on that Ougoulin.

      Local passes = duration * fps

      Main important thing is that duration which is 2000ms here, has to made into seconds which is 2s, otherwise, it will take forever for the increment to finish


      local function lerp( v0, v1, t )
      return v0 + t * (v1 – v0)

      local passes = duration/1000 * fps = 2000/1000 * 30 = 60

      Cheers and keep coding

  • andrew
    Posted at 23:36h, 11 June

    is there anyway to make it stop counting when my restart scene comes on.

    • Rob Miracle
      Posted at 17:36h, 12 June

      You’re in control of when you increment the score. Its up to your code to decide how to handle that.