Techniques for cash register score

A place for people with an interest in developing new shmups.
Post Reply
User avatar
DyingIsFun
Posts: 35
Joined: Mon May 31, 2021 7:14 am
Contact:

Techniques for cash register score

Post by DyingIsFun »

Hey all,

Cash register score is a staple of arcade games. This is the technique of incrementing a score upwards in the UI whenever a player achieves some score amount, rather than doing a one-time addition of the score amount to the total score.

One of the simplest ways to implement this is to simply add any new score amount to a variable called score_queue and whenever score_queue is non-zero to subtract 1 from score_queue and add 1 to total_score every few milliseconds (for example, every 0.017s).

This naive approach is obviously problematic when dealing with big scores. For example, if I kill an enemy worth 250,000 score and add 1 to my total_score every frame, it would take 250,000 * 0.017 = ~71 seconds for my score counter to tick to the final value! Yuck.

One way I thought to combat this is with logic like the following (simplified for illustration):

Code: Select all

        // cash register score
        if (score_queue > 0)
        {
            if (Time.time > time_of_last_score_update + score_frequency)
            {
                time_of_last_score_update = Time.time;
                if (score_queue >= 1000 && score_queue % 1000 == 0)
                {
                    score_queue -= 1000;
                    score += 1000;
                }
                else
                {
                    score_queue -= 10;
                    score += 10;
                }
            }
        }
This works to prevent big scores from taking a long time to tick up, but is ugly in that once the sub-1000 multiples of 10 are removed from the score_queue, the thousands increment up one at a time, very fast, making the cash registering look unnatural.

So, what are some techniques that you use to implement nice cash register score?
User avatar
trap15
Posts: 7835
Joined: Mon Aug 31, 2009 4:13 am
Location: 東京都杉並区
Contact:

Re: Techniques for cash register score

Post by trap15 »

Actually, cash register score ticking is extremely uncommon in arcade games, at least as far as the main score display goes. There's very few actually with it, but some games try to give the feeling of it without having it, with various methods like tick damage points.

As far as implementing this sort of thing (I've done so for uses outside of in-game score display), I like to either do it digit by digit (ticking up end-stage bonuses works nicely with this), or drain a fraction each tick (works well for most cases, I use it for displaying experience points at the end of the game). For the latter, I would do something like:

Code: Select all

int score_queue; // whatever it may be

// Adjust numbers to taste.
const int queue_divisor = 69; // Lower divisor makes the drain faster for higher values.
const int queue_addend = 420; // Higher addend makes the drain faster for lower values.

int score_to_add = (score_queue / queue_divisor) + queue_addend;
if(score_to_add > score_queue) score_to_add = score_queue;
score_queue -= score_to_add;
score += score_to_add;
@trap0xf | daifukkat.su/blog | scores | FIRE LANCER
<S.Yagawa> I like the challenge of "doing the impossible" with older hardware, and pushing it as far as it can go.
User avatar
DyingIsFun
Posts: 35
Joined: Mon May 31, 2021 7:14 am
Contact:

Re: Techniques for cash register score

Post by DyingIsFun »

Thanks for the intel, trap15!
Ixmucane2
Posts: 760
Joined: Mon Jan 19, 2009 3:26 pm
Location: stuck at the continue prompt

Re: Techniques for cash register score

Post by Ixmucane2 »

For a particularly "cash register" look, you can emulate a split flap display, as actually used in old cash registers and similar devices like clocks. They have the restriction that symbols change sequentially, not arbitrarily; in exchange for being slow, they can look really good because they are printed panels, not restricted to constrained shapes like 7-segment displays or the like.

You need animations, probably automatically generated and all the same length, for the transition between consecutive symbols (e.g. 0 -> 1,...,8 -> 9, 9 -> empty, empty -> 0; you can also have multi-digit panels).

With a separate state for each panel (current animation frame and desired symbol to display) you can
  • update the target symbol every frame (e.g. when score is 1457 the tens panel wants to roll to 5; next frame score is 1524 and it wants to roll to 2)
  • decide, every time panel animations end (they probably look better synchronized), whether the panel should animate to the next symbol (if the current displayed symbol, at the end of the just finished animation, is different from the current target symbol) or remain fixed (if the current displayed symbol matches the target).
User avatar
heli
Posts: 585
Joined: Fri Sep 13, 2019 3:58 pm

Re: Techniques for cash register score

Post by heli »

If you shoot 100 enemys in 1 second is also a problem.
User avatar
BryanM
Posts: 6116
Joined: Thu Feb 07, 2008 3:46 am

Re: Techniques for cash register score

Post by BryanM »

I think a roll-over display like Ixmucane mentioned would be ideal to communicate what the numbers are doing to the player and that the numbers aren't drunk.

With a direct display like you were talking about, I think having a flexible update frequency would be ideal. When there's a huge amount of number to churn through, have it add a % of the acquired score to the display quickly, then slow and scale down the % until single +1's are coming in a few times a second. This can be designed such that there isn't a firm upper bound to how long the display takes to settle, but that there's at least a logarithmic increase to its duration. And as it slows down a viewer can anticipate it stopping, like a wheel on a gameshow coming to a stop, that kind of feeling.
oab
Posts: 61
Joined: Tue Mar 19, 2019 4:14 am

Re: Techniques for cash register score

Post by oab »

This is what I use in my game. It increases score 20% every frame.

Code: Select all

if current_score < target_score
{

     increase_score = ((target_score - current_score) * 0.2).ceil() 

     current_score += increase_score
}

I am making a vertical shmup game: USG

Released Flesh and miniStrike
Ixmucane2
Posts: 760
Joined: Mon Jan 19, 2009 3:26 pm
Location: stuck at the continue prompt

Re: Techniques for cash register score

Post by Ixmucane2 »

If the purpose is simply to keep the displayed score changing every frame throughout "chains" of scoring events, any roughly exponential mechanism should do.
OAB's example is very simple (and it can be made even simpler by omitting the redundant preliminary test), robust (don't forget the ceiling function, to increase the displayed score by at least 1 whenever it's behind) and exactly exponential.

For readability (it would give a hint of the rate of score increase, and it would enable special effects) incrementing only one digit at a time, of course the most significant one, might look better. It can be done by rounding the increase to the next smaller power of ten. Example in C:

Code: Select all

double gross_increase= ceil((double)(target_score-displayed_score)*k);
	if(gross_increase>0.0){
	  double log_increase=log10(gross_increase);
	  double one_digit_log_increase=floor(log_increase);
	  double one_digit_increase=pow(10.0,one_digit_log_increase);
	  displayed_score += (int)one_digit_increase;	 
	}
Note that k might be 1.0; the rate of score convergence is better controlled through update delays.
Post Reply