Let's create an MPAGD game - Part 20: SCOREs, LIVES and DISPLAYing stuff.
Our game is starting to take shape, now is probably a good time to sort out the mess that is currently the score bar at the top of the screen. Before this, let's take a look at how MPAGD stores the player's score, how we can add to it and how we display it on the screen.
First, the score is not a normal 8bit variable. As you recall 8bit variables can hold a number from 0-255. The score in an MPAGD game can hold a value from 0 to 999,999 after which point it will reset to 0. You don't need to understand how it does this, just that it does!
Remember back in Part 11 we added a score every time Stinky Dog collected a bone. We did this by adding the command
into the COLLECTBLOCK event. The SCORE command will accept a 16 bit number, i.e. any number from 0 to 65,535 (2 to the power 16). The number you put after the SCORE command is then added to the players current score.
Note that SCORE is not a variable, so you can't do any coding that interrogates it, like IF SCORE >50000 ADD 1 TO LIVES.
We also updated the score on screen by including the command:
AT 0 6 SHOWSCORE
The AT command is a shorthand way of positioning the cursor on the screen, so the code above is the same as:
LET LINE = 0 LET COLUMN = 6 SHOWSCORE
But what if we also wanted to have the word 'SCORE:' before the score, so it displays: SCORE: 000000... that might look neater.
Let's open up our GAME INITIALISATION script:
EVENT GAMEINIT LET LIVES = 3 AT 0 27 DISPLAY LIVES AT 0 6 SHOWSCORE
...and let's tidy it up a bit:
EVENT GAMEINIT AT 0 0 PRINT "SCORE:" SHOWSCORE LET LIVES = 3 AT 0 21 PRINT "LIVES:" DISPLAY LIVES
Now our score bar is looking a little neater:
So we can see that AT 0 0 positions the cursor in the top left character cell of the screen, we then PRINT the word 'SCORE': display the actual score next to it (note that the cursor automatically moves to the next column available, which is why in our game initialisation event we can save a few bytes by removing the AT 0 6 before SHOWSCORE...since after printing 'SCORE:' the cursor is already there!.
Then we shift the cursor to 0 21 to display the LIVES remaining.
Another score related bonus in MPAGD is...BONUS. This works in a similar way to SCORE, in that you can add to the players bonus with a command like:
That you trigger when the player does something. Lets give Stinky Dog a BONUS if one of his noxious farts stuns Sideways Clive...
Open up your SPRITETYPE 1 event and find the part that deals with the fart colliding with Sideways Clive...
IF COLLISION 2 ; if Clive touches a Type 2 sprite (the fart) IF DIRECTION = LEFT ; if Clive is going left LET SETTINGB = 0 ; remember the direction he was going, 0 = Left ELSE ; if he wasn't going left LET SETTINGB = 1 ; he was going RIGHT, 1 = RIGHT ENDIF LET DIRECTION = 5 ; set the direction to STUNNED LET SETTINGA = 0 ; start the stunned timer OTHER ; switch to the Fart REMOVE ; remove the fart ENDSPRITE ; switch back to this event LET F = 0 ; reset the Fart in play to no fart in play BONUS 50 ; add 50 to the bonus ENDIF
Now when a fart hits Clive we'll increase the bonus.
Note that the BONUS won't automatically be added to the score, it will tot up as we play, we're going to add it later, when Stinky Dog completes a level of the game.
Like SCORE, you are limited to incrementing the BONUS by numbers up to 65535 and it will max out at 999999.
At the moment, in our game, a level is completed when Stinky Dog collects all the Bones on screen, we test if they have all been collected in our COLLECTBLOCK event which currently looks like this:
EVENT COLLECTBLOCK SCORE 100 ; score 100 points when we collect a Bone AT 0 6 SHOWSCORE ; display the score SUBTRACT 1 FROM B ; decrement the number of bones left on screen IF B = 0 ; have all Bones been collected? NEXTLEVEL ; if so move to the next screen ENDIF
Let's make it a bit more interesting, we will clear the screen, display the bonus, add it to the score and then start the next level.
When it comes to clearing the screen, we have two commands we can choose from:
CLS - will clear the entire screen
CLW - will clear only the play window and not the score bar that we have at the top (or wherever you positioned yours!)
Let's just clear the screen, display the score, the bonus, add the bonus to the score and display the new total score, then we'll wait for the player to press a key to start the next level.
EVENT COLLECTBLOCK SCORE 100 ; score 100 points when we collect a Bone AT 0 6 SHOWSCORE ; display the score SUBTRACT 1 FROM B ; decrement the number of bones left on screen IF B = 0 ; have all Bones been collected? CLS ; clear the screen AT 10 2 ; at line 10, column 2... SHOWSCORE ; display the score DELAY 25 ; wait 1 second PRINT " + " ; display + DELAY 25 ; wait another second SHOWBONUS ; display the bonus DELAY 25 ; wait another second PRINT " = " ; display = DELAY 25 ; wait another second ADDBONUS ; add the bonus to the score ZEROBONUS ; reset the bonus to 0 now we've added it SHOWSCORE ; display the new score AT 15 8 ; at line 15 column 8 PRINT "PRESS KEY TO START" WAITKEY ; wait for a key press NEXTLEVEL ; if so move to the next screen ENDIF
Let's give it a go...
That seemed to work...but did you spot the problem?
Right at the end, when the next level started, the screen bar at the top has completely disappeared. But then the score value and lives value return...
Why is that?
Well, first we used the CLS command when Stinky Dog collects the final bone. CLS wipes the entire screen clean, so the score bar goes too.
So, why isn't it reinstated when the next level starts.
Simply put, the answer is that our code doesn't tell it to. At the moment we put the PRINT "SCORE:" and PRINT "LIVES" code in our GAME INITIALISATION event. This event is only run when the Game first starts. The score then appears when we first collect a bone, and the lives appear when we are killed, that's because we have SHOWSCORE and SHOWLIVES commands in the COLLECTBLOCK and KILL PLAYER events respectively.
To remedy this, we'll move the PRINT commands to the RESTARTSCREEN event. This event is run every time we restart a screen (including after a death and when we start a new level).
So, open up your GAME INITIALISATION script and cut everything beneath EVENT GAMEINIT except the LET LIVES = 3, so it should now look like this:
EVENT GAMEINIT LET LIVES = 3
then open up you RESTART SCREEN Event and paste it in above the DATA statement...it should now look like this:
EVENT RESTARTSCREEN RESTORE READ B ; read the first value of the DATA and put it in B IF SCREEN >= 1 ; if it is screen 1 or above REPEAT SCREEN ; then repeat SCREEN-many times READ B ; read the next value ENDREPEAT ; so we've found the right B value for the Screen ENDIF AT 0 0 PRINT "SCORE:" AT 0 6 SHOWSCORE AT 0 21 PRINT "LIVES:" DISPLAY DOUBLEDIGITS LIVES ;-------------------number of Bones per screen------------------------- DATA 5 7 3 4 6 9 5 8 5 6 4 8 6 9 3 8 9 DATA 4 7 8 10
We leave the LET LIVES = 3 statement in Game initialisation, since we only want this to run once, when the game first starts, otherwise the number of lives will reset every time the screen is restarted if we put it in the RESTARTSCREEN event.
The lives variable in MPAGD can contain an 8bit number (0-255) and unlike SCORE and BONUS we can write code around it, for example, we could 'ADD 1 TO LIVES' if the player collected a particular object.
It does behave a bit differently to normal variables, in that if it reaches 0 (no lives remaining) MPAGD will run the 'LOST GAME' event.
As LIVES is an 8 bit variable we also need to use the DISPLAY command to display it.
The DISPLAY command also has additional parameters we can use to control how it displays on screen, these are: DISPLAY SINGLEDIGIT - will only display 0 - 9,
DISPLAY DOUBLEDIGITS - will only display 0-99 with a leading 0 for 0-9 (00,01,02 etc)
DISPLAY TRIPLEDIGITS - will display 0-255 with a leading 00 for 0-9 , and 0 for 10-99
In our game I'm going to restrict the number of lives that can ever be gained to a maximum of 10, so I've added in the DOUBLEDIGITS parameter in the command in the code above (highlighted). As for the way we can restrict lives to a maximum of 10...we'll come back to that later.
As we've used DOUBLEDIGITS to display the lives in the RESTARTSCREEN event, we're going to need to do the same wherever our code tells the game to display the lives. At the moment, there should be only one other reference to LIVES, which is in our KILL PLAYER event, which is triggered whenever we KILL the player, open up your KILL PLAYER event and add the DOUBLEDIGITS...
EVENT KILLPLAYER SUBTRACT 1 FROM LIVES AT 0 27 DISPLAY DOUBLEDIGITS LIVES ZEROBONUS
I also want to tweak the game a little, so I've also added a ZEROBONUS into the KILLPLAYER event too, that way, if Stinky Dog is killed, he will lose any fart bonuses he has accumulated.
Let's test the game...
OK, that seems to be working as expected, but I'm not too keen on the font or colours surrounding the play area, I think it's about time we looked at that next...