Suppose in your game you want to give the player a set amount of time to complete each screen. And then, perhaps, give them a bonus dependent on the amount of time left when they successfully complete the levels objectives.
How would we go about that?
First, MPAGDD runs at 25 frames per second, so it should be pretty simple to create a timing mechanism that can count second.
Second, we'll need some variables to store (and display) the current amount of minutes/seconds remaining.
Third, we might want to change the amount of time allowed on a per screen basis, or maybe use difficulty levels to alter the amount of time allowed.
METHOD 1 - Simple: Same amount of time per screen
We'll start off with a simple version, where for each screen there is a fixed amount of seconds and minutes allowed to complete the screen, if the timer reaches 0 the player dies.
Now, MPAGD runs at 25 frames per second. So if we have a variable that increments once every frame, when it reaches 25 we'll have timed a second.
We'll use variable G as our general time, counting the 1/25th of seconds.
We'll also need variables that store the number of minutes and seconds allowed per screen:
M = Minutes
S = Seconds.
We'll initialise the values for these three variables in our RESTART SCREEN event, that way, they will reset each time we start a screen, including after a death. In your restart screen event you will add:
LET G = 0 ; reset the 1/25s timer
LET M = 1 ; countdown minutes allowed
LET S = 0 ; countdown seconds allowed
Next, we'll add some code that will perform and display the countdown, to ensure this runs consistently throughout the game we will put this into the MAINLOOP 1 event so that it will run at the start of each frame:
; COUNTDOWN TIMER
;================
ADD 1 TO G ; increment the general timer
IF G = 25 ; when it reaches 25
LET G = 0 ; reset it
SUBTRACT 1 FROM S ; decrement seconds remaining
ENDIF
IF S = 0 ; if 0 seconds
IF M = 0 ; and 0 minutes left
KILL ; kill the player
EXIT ; exit processing this event
ENDIF
SUBTRACT 1 FROM M ; decrement the minutes
LET S = 59 ; reset the seconds
ENDIF
COLOUR 71 ; white text on black (zx spectrum)
AT 22 26
DISPLAY DOUBLEDIGITS M ; display minutes remaining
CHR 58 ; ':'
DISPLAY DOUBLEDIGITS S ; display seconds remaining
So, we increment G, when it hits 25 we reset it to 0 and decrement the number of seconds (S) when S reaches 0 we reset it to 59 and decrement the number of minutes, unless there are no minutes left in which case we have run out of time and we kill the player, here's what it should look like...
METHOD 2 - Advanced: Different amount of time per screen
If we want to alter the amount of time available we just need to change the variable initialisation code in our RESTART SCREEN event to use a DATA table and READ the values for Minutes (M) and Seconds (S)
We can use this for the variable initialisation in the RESTART SCREEN
LET G = 0 ; reset the 1/25s timer
RESTORE ; restore the data table so we read from the start
READ M ; read the 1st data and put it in M
READ S ; read 2nd value put it in S
IF SCREEN >= 1 ; if it is screen 1 or above
REPEAT SCREEN ; then repeat SCREEN-many times
READ M ; read the next value for M
READ S ; and the next value for S
ENDREPEAT ; so we've found the right M & S values for the Screen
ENDIF
Then we will add this as our DATA table, the values alternate from minutes to seconds, so the SCREEN 0 allowable time is 0 minute 30 seconds (the first 2 values), for SCREEN 1 its 1 minute 0 Seconds (values 3 & 4), for Screen 2 it's 1 minute 15 seconds (values 5 & 6) and so on.
DATA 0 30 1 0 1 15 2 0 1 45 1 30 1 0 1 30
Adding a Bonus for completing the screen
Everything we've done so far is fine for killing the player if they run out of time, but what if they complete the screens objectives, we could add a bonus based on the amount of time remaining. Dependent on what triggers the completion of the screen (in Stinky Dog it's collecting all the bones) you will need to add your bonus routine in the correct event. It might be something like this:
IF M > 0 ; if there are minutes left
REPEAT M ; repeat for each minute remaining
REPEAT 60 ; repeat 60 times (60 sec)
BONUS 10 ; increase bonus by 10
ENDREPEAT
ENDREPEAT
ENDIF
IF S > 0 ; if there are seconds left
REPEAT S ; repeat for each second
BONUS 10 ; increase the bonus by 10
ENDREPEAT
ENDIF
ADDBONUS ; add the bonus to the score
ZEROBONUS ; reset bonus to zero
Applying this to our Stinky Dog game
In our Stinky Dog game though, there's a couple of changes I want to make.
First we already have a DATA table in RESTART SCREEN 0, it holds the number of bones that need to be collected per screen. No problem, MPAGD doesn't care what the data it holds in the DATA table - so we just need to include the bones values and READ three times per cycle to get the correct number of bones, minutes and seconds.
LET G = 0 ; reset the 1/25s timer
RESTORE ; restore the data table so we read from the start
READ M ; read the 1st data and put it in M
READ S ; read 2nd value put it in S
READ B ; read third value and put it in B for Bones
IF SCREEN >= 1 ; if it is screen 1 or above
REPEAT SCREEN ; then repeat SCREEN-many times
READ M ; read the next value for M
READ S ; and the next value for S
READ B ; and the next values for B
ENDREPEAT ; we've found the right M, S & B values for the Screen
ENDIF
And the DATA table at the bottom of RESTART SCREEN:
DATA 0 30 6 1 0 7 1 15 3 2 0 4 1 45 6 1
DATA 30 4 1 0 8 1 30 6
Next, as we've already created a nice reusable death routine which we call by setting Stinky Dog's SETTINGA value to 99, I'm going to move the Countdown Timer code from MAINLOOP 1 to the player event, remove the KILL command and change it to LET SETTINGA = 99
NOTE: Place the code AFTER your IF SETTINGA = 99 ....ENDIF routine
; COUNTDOWN TIMER
;================
ADD 1 TO G ; increment the general timer
IF G = 25 ; when it reaches 25
LET G = 0 ; reset it
SUBTRACT 1 FROM S ; decrement seconds remaining
ENDIF
IF S = 0 ; if 0 seconds
IF M = 0 ; and 0 minutes left
LET SETTINGA = 99 ; kill the player
EXIT ; exit processing this event
ENDIF
SUBTRACT 1 FROM M ; decrement the minutes
LET S = 59 ; reset the seconds
ENDIF
COLOUR 71 ; white text on black (zx spectrum)
AT 22 26
DISPLAY DOUBLEDIGITS M ; display minutes remaining
CHR 58 ; ':'
DISPLAY DOUBLEDIGITS S ; display seconds remaining
Here it is in action when we run out of time
To add a new time bonus on completing the screen we'll need to update our COLLECT BLOCK event:
EVENT COLLECTBLOCK
SCORE 100 ; score 100 points when we collect a Bone
AT 0 6
COLOUR 71
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 4 6
MESSAGE 1 ; "well done"
CHR 32
MESSAGE 0 ; "stinky dog"
CHR 33
DELAY 25 ; wait another second
COLOUR 65 ; bright blue on balck
AT 7 7
MESSAGE 2 ; "score"
CHR 32 ; <space>
DELAY 25 ; wait another second
SHOWSCORE
DELAY 25 ; wait another second
AT 9 2
COLOUR 70 ; bright yellow on black
MESSAGE 3 ; "fart"
CHR 32 ; <space>
MESSAGE 4 ; "bonus"
CHR 32 ; <space>
DELAY 25 ; wait another second
SHOWBONUS ; display the bonus
ADDBONUS ; add the bonus to the score
ZEROBONUS ; reset the bonus to 0 now we've added it
DELAY 25 ; wait another second
COLOUR 67 ; bright magenta on black
AT 11 2
MESSAGE 7 ; "time"
CHR 32 ; <space>
MESSAGE 4 ; "bonus"
CHR 32 ; <space>
DELAY 25 ; wait another second
IF M > 0 ; if there are minutes left
REPEAT M ; repeat for each minute remaining
REPEAT 60 ; repeat 60 times (60 sec)
BONUS 10 ; increase bonus by 10
ENDREPEAT
ENDREPEAT
ENDIF
IF S > 0 ; if there are seconds left
REPEAT S ; repeat for each second
BONUS 10 ; increase the bonus by 10
ENDREPEAT
ENDIF
SHOWBONUS
ADDBONUS ; add the bonus to the score
ZEROBONUS ; reset bonus to zero
AT 13 5
COLOUR 71
MESSAGE 8 ; "total"
CHR 32
CHR 61
CHR 32
SHOWSCORE ; display the score
DELAY 25 ; wait 1 second
AT 17 8 ; at line 15 column 8
COLOUR 215
MESSAGE 5 ; "press key to start"
WAITKEY ; wait for a key press
NEXTLEVEL ; if so move to the next screen
ENDIF
Note that I've added two new messages to the TEXT MESSAGES:
DEFINEMESSAGES
"STINKY DOG" ;0
"WELL DONE" ;1
"SCORE" ;2
"FART" ;3
"BONUS" ;4
"PRESS KEY TO START" ;5
"LIVES" ;6
"TIME" ;7
"TOTAL" ;8
Here it is all working nicely!
留言