Vertical Shmup - Part 7 - A Gameplay Decision
I started this series as a bit of nostalgic homage to Imagine's Arcadia, a game as a 12 year Old back in 1982 I loved. If you recall, the original Arcadia didn't require to kill all of the enemies in each wave, rather you had to survive the timer.
I could implement the same gameplay for this game by implementing a timer, but I'm not trying to recreate Arcadia exactly so I think we'll do something else.
As an alternative, we could make it so that you have to kill all the enemies in each wave before the next wave appears.
Or, it might be good to have a set amount of each wave of enemies that are spawned after which the next wave will begin. So to get a top score you need to kill as many as possible, perhaps if you kill all enemies in a wave there's some kind of bonus or power up that you can be rewarded with.
I think this last approach is my favourite and is the one I'm going to attempt to start with.
To do this, we're going to need a variable that can count the enemies in each wave that we've killed, let's head back to our Spawner event code (Sprite Type 7)
and add in the highlighted lines of code below.
EVENT SPRITETYPE7 ; SPAWNER ; ============ IF SETTINGA = 0 ; first time we run this LET JUMPSPEED = 0 ; reset the enemies spawned counter LET SETTINGB = 0 ; reset the timer RESTORE ; start from the beginning of the data table REPEAT L ; get the data for this level READ AIRBORNE ; get the spawner movement READ X ; get starting x position READ Y ; get starting y position READ J ; get the enemy sprite type READ K ; get the enemy image READ E ; how many enemies in this level? READ G ; delay between releasing each enemy READ P ; Number of points scored if enemy is killed ENDREPEAT LET D = E ; store the number of enemies to be killed in D LET F = E ; also store #enemies in F to count kills & exits ADD 1 TO SETTINGA ; prevent this running again ENDIF IF SETTINGB = G ; has timer reached the delay point? IF JUMPSPEED < E ; are there still enemies left to spawn? IF S <= 8 ; are there 10 or less enemies already on screen? SPAWN J K ; spawn an enemy ADD 1 TO JUMPSPEED ; increment the number spawned SPAWNED ; switch to the enemy sprite LET DIRECTION = 0 ; set its initial direction to 0 ENDSPRITE ; return to the spawner ENDIF ELSE ; all enemies in this level have been spawned IF F = 0 ; if all enemies killed or exited ADD 1 TO L ; get ready for next level IF L = 3 ; have we reached the end of the levels? LET L = 1 ; yes, start again ENDIF LET SETTINGA = 0 ; GET DATA FOR NEXT LEVEL ENDIF ENDIF LET SETTINGB = 0 ; reset the timer ENDIF ADD 1 TO SETTINGB ; increment the timer DATA 0 165 8 2 2 5 12 5 0 80 8 2 2 5 12 10
So, we read into E the total number of enemies in the wave, were not going to want to change this info during the wave so we'll copy it into another variable, D, which we will use as a Countdown each time we kill an enemy.
We will also store the number of enemies in the wave in F, we'll then decrement F every time an enemy is killed or exits the screen. We'll then only move to the next level/wave when all enemies have been removed from the screen,, otherwise we might run in to problems as new waves would otherwise appear before the last of the previous enemies had left the screen - which could mess up our counters.
We also need think about the scoring mechanism. In Arcadia, each enemy scored the same number or points as the level/wave. So in level 1 each kill scored 1 point, in Level 2 - 2pts and so on.
We could do the same here quite easily, but again, I'm not trying to recreate Arcadia exactly, and I want to retain some flexibility, so we'll use a new variable P which we will read from the DATA table, so you can see from the highlighted code above, killing an enemy in level 1 will score 5 points and killing an enemy in level 2 will score 10 points.
We also need to add the score to the Screen, first we'll drop it into our RESTART SCREEN event:
EVENT RESTARTSCREEN LET S = 0 ; initialise the sprite counter AT 0 1 ; position the cursor at Line 0 Column 1 SHOWSCORE ; display the score
That's OK to start with but we need it to update whenever points are scored, we could simply drop the same code into the MAIN LOOP, but in my experience if you want to keep your MPAGD game running efficiently its best not to refresh on screen scores and variables on every cycle, instead, we'll only update it when required.
One approach would be to repeat the above lines of code in every event where points are scored, but that could get quite repetitive codewise, instead my preference is to use a variable as a trigger, I'll use T.
Now in our Main Loop 1 we'll add some code:
EVENT MAINLOOP1 IF T = 1 ; Score bar update requested AT 0 1 ; at Line 0 column 1 SHOWSCORE ; update the score LET T = 0 ; reset the trigger ENDIF
So now, whenever we want to update the score bar we'll just need to add LET T = 1 in the relevant events.
Let's go back to our explosion sprite event (Type 6) and add the triggers, countdowns and score code in:
EVENT SPRITETYPE6 ANIMATE ; regular amination IF FRAME = 4 ; are we on the last frame? IF DIRECTION = 0 ; was enemy hit by a torpedo? REMOVE ; yes, remove this sprite SUBTRACT 1 FROM S ; decrement the sprite counter SUBTRACT 1 FROM D ; decrement the enemy kill countdown SUBTRACT 1 FROM F ; decrement the kill/exit countdown IF D = 0 ; have all enemies been killed? SCORE 500 ; yes, score extra 500 points ELSE ; no, still some more to kill SCORE P ; score P number of points ENDIF ELSE IF DIRECTION = 1 ; is this the player exploding? KILL ENDIF ENDIF LET T = 1 ; update the score bar ENDIF
Now we'll score P points for each kill, but if we kill all enemeies in a wave D will be 0 and we will score a bonus 500 points.
Let's give it a test...
Looks ok to me, the bonus is working as expected.
But these enemies are a bit toothless, so next we'll give them some weapons of their own.
NEXT: PART 8 : THE ALIENS FIGHT BACK!