High Scores, soaring even higher

8-1-2018
First, I want to thank Allen Albright and Antonio Villena for helping me understand the logic for the high score list.

Every arcade game needs a high score display, you just want to see how high you can go and beat the other players that play your game. It’s been a standard in all arcade machines since Space Invaders. The idea is rather simple. You have a list of scores and initials, you keep track of your players current score when the game is over you see if your last games score is larger than the lowest score on the table. If it is, give the player the ability to enter in their initials, store the initials and score in the table and display the results.

In my implementation, each of those steps is dependent on a memory structure called a STRUCT.

A struct is like an array of arrays, in this case, we are storing 2 arrays.

The first array is a score array, we will be storing the 5 top scores, plus 1 additional score. The second array is a initials array, we will store a 3 letter combination and link that to the score itself, again there will be 6 entries. Finally, we are going to have a sort function, that will arrange the score by descending value.

Now, I do want to preference this with, you have to think more in terms of an older implementation of C as some of the newer versions of C, do some of this work for you and the examples one may find on the internet will not compile with Z88dk (at least I couldn’t get them to work).

A struct (structure) sets aside a chunk of memory that we will use to store our various bits. As much, it should be defined before your main program runs.

In our circumstance, this is in our variables.h.

struct HiScore scores[] = 
{
    {5000L, "DDD"},
    {250L, "AAA"},	
    {6000L, "EEE"},
    {4000L, "CCC"},
    {3000L, "BBB"},
    {250L, "AAA"}
}

You will notice, that the scores are not in numerical order, this for us to test our sort function later on. You may also notice that after every score, we have an L listed, this is to indicate that the number is a long variable. A long will store a number as large as 2,147,483,646, an obviously over the top large score. If you score 1 number above this, the whole structure would come apart, which is why we want such a large number. This is the largest number obtainable in most C compilers. Now, we have declared our struct and initialized it.

Next, we are going to create 2 more variables to define the structure a little further.

unsigned char initials[4]  = "\0";
long key;

The first is an array to hold the initials of the player and created with 1 more character than we need, we pre-populate it with a null character.

Next, we are creating our key, this is a score key that we will use for our sorting function later on.

Next, we are going to need to keep track of the player’s current score with the variable:

long yourScore;//2,147,483,647 max

Again, this is declared as a long variable with a maximum value of 2,147,483,646.

Next, we are going to move to our main.c. We have a section in the program, where we set up our variables before the game starts. We want to initialize our score with

yourScore = 0;

This resets our score to 0 when we start a game.

Scorekeeping, displaying the score on the game window and the endgame are out of scope for this document and will be covered in another. We are more interested in the game over function.

//game over check
//lives = 3 on start
if( yourLives == 0 ) //end game
{
    //Sound(STOP, 0);
    endgame();
    isLevelRead = FALSE;//reset flag to re read level
    EXIT;
    //Bitmap(0, 0);//	 
    goto start;// start all over
}

Here’s a simple explanation.

If our lives equal 0, then the game is over, and we need to trigger our endgame function. Once, the endgame function is complete, we will reset the read level flag to false where we will reread the level information again when we restart. The line…

EXIT;

Stops the FASE sprite engine.

We will eventually, reshow the main image, but it’s commented out for now. Finally, we goto Start.

I know it’s usually bad form to use the GOTO keyword, but we’ll make an exception here and in one other place.

I try to use goto as few times as possible, but it is fine to use it occasionally. The problem with using happens in BASIC is that you must provide a line number, which can easily be abused. Here, we will GOTO a label, which is much easier to keep track of. I am not going to be abusing goto.

Now that we know how our game is going to end, let’s take a look at our endgame function.

// Game Over
void endgame()
{
    clearScreen();
    PrintStr(gameOverTXT, 0x0B0C);
    printHighScores();
    //check to see if your current score is a new high score
    if (yourScore > scores[4].hiScoreList)
    {
        highScore();
    }
    else
    {
        PrintStr(gameOverTXT, 0x0B0C);
    }
    PrintStr(pressSpace, 0x0A0E);
    while (1)
    {
        i= inp(0x7ffe) & 0x1f;

        if( i==0x1e )
            break;
    }

    Pause (30);
    clearScreen();
}

The endgame function is more or less an overview function that just calls other functions in their proper order.

The big picture here is:

We clear the screen
We print on the screen that the game is over
We then print what the current high score list is.
We check if your current high score is larger than the lowest valid high score entry.
If it is, then we will go to the highscore routine.
If it is not, then we will just print the game is over.
Next, we will enter an endless loop and wait for the spacebar to be pressed, when it is pressed, we will break out of the loop.
We wait 30 milliseconds
Finally, we clear the screen again.

My last article covered clearing the screen, pretty simple and straight-forward.

The screen printing function – PrintStr – is part of the FASE sprite engine and comes in the form of

PrintStr ( char *string, unsigned int xy );

Whereas the string is a string pointer and xy comes in the form of a hex number combining both the x and y position in a single number. For example, 0x0B0C is the 11th character block in the X-axis and 12th character block in the Y-axis.

Our next command is to print the current high scores, with the command

printHighScores();

That simply points to a function written in gamedisplay.h. The code for that function is.

void printHighScores()
{
    screenCounter = 0;
    insertionSort();
    PrintStr(highScoreText, 0x0103);
    xx = 0x0405;
    for (screenCounter = 0; screenCounter < 5; ++ screenCounter )
    {
        strcpy (str," ");
        strcat (str,scores[screenCounter].hiInitals);    //Concatenate strings
        strcat (str,"....");
        
        ltoa(scores[screenCounter].hiScoreList, yourScoreTXT , 10);//use lota for long variables
        strcat (str,yourScoreTXT);

        PrintStr(str, xx);
        ++ xx;
    }
}

Our printHighScores() function is rather simple and straight-forward. We are going to be reusing a variable screenCounter to step through all of the high scores, so the first thing we do is reset the variable to 0.

We then perform a sorting of the scores. I will cover the actual sorting function in another article.

The next command is to print to the screen, the text “The Top Scores are:”. That variable highScoreText is defined in variables.h

The next thing we are doing is setting up our variable xx. This is going to be used to move the individual scores down the screen. We set up the variable with the value 0x0405 and will increment that value in our loop.

Now, we set up our loop to step through all of our scores, this is the screenCounter loop.

The loop starts off with srtcpy and copies to string – str a space character.

We then use strcat to concatenate the string str with the initials stored in the struct.

We follow-up by concatenating to the string str a series of periods to separate the initials from the score.

Next, we convert the long number used for the score and store that to the string yourScoreTxt, the 10 in that function is the number of characters used for such a long number.

We then concatenate the string str with the string used in the last command, so now we have one long string consisting of the initials, the periods and the score.

Next, we print that string to the screen with our PrintStr command.

Finally, we increment the xx value, so that the next score is printed on the next line.

Going back to the endgame() function. Our next series of commands are:

//check to see if your current score is a new high score
if (yourScore > scores[4].hiScoreList)
{
    highScore();
}
else
{
    PrintStr(gameOverTXT, 0x0B0C);
}

These are going to be used to check your high score. It basically says that if your high score is larger than the last score in the sorted list, then we will go to the highscore() routine. If you score does not surpass the lowest sorted score, we will print to the screen the gameOverTXT. Again this is a string that was created at the start of the game in variables.h that says “Game Over”.

I will cover the highScore() function in yet another article.

Our next command:

PrintStr(pressSpace, 0x0A0E);

Prints to the screen to press the spacebar. The instruct the player on how to break the endless loop we are about ready to create.

Our endless loop.

while (1)
{		
    i= inp(0x7ffe) & 0x1f;

    if( i==0x1e )
        break;
}

Is used to keep the scores on the screen until the spacebar is pressed. We covered keyboard usage in another article, so you should recognize the keyboard code.

Now, we will pause for a short while after the player presses the spacebar. This command is optional, I am just adding an additional pause. It will work fine without it as well.

Finally, we call up the clearScreen() function.

My two follow-up articles, one on sorting and one on high score entry should finish this topic. Believe it or not, we are getting closer to the game being assembled.

As always, happy coding.

Advertisements

Author: andydansby

I'm a hobbyist coder working with the ZX Spectrum. Living in New York state near the Syracuse area. I grew up in Virgina. The first computer my parents bought for me was a Timex Sinclair 2068.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s