;--------------------------------------- ;Assemble IT - Game 3 - Missile Blasta ;The Remastered Edition ; ;Written by Richard Bayliss ;(C)2018 The New Dimension ;--------------------------------------- ;in this tutorial, we will show you how ;to code a 1 player blast 'em game. this ;will involve eight sprites. one will be ;the player ship, one will be a bullet ;and the remaining six will become ;missiles ;also in this tutorial, you'll be seeing ;how sprite animations work, and how we ;control the sprite priorities ;we'll also be adding levels, which will ;engage the speed of the missiles to ;make the game a tad on the difficult ;side. ;there'll also be a shield generator and ;a scoreboard. we'll also be adding some ;credits on the front of the screen as ;well as game over. anyway, enough of ;chitty chatty clag, let's move on to ;the hard stuff - the game coding of ;course :) ;Generate program file !to "missileblasta.prg",cbm ;Variables /pointers for the game spritepos = $0370 ;positions for the ;sprites collision = $03f0 ;collision dection firelockup = $0330 ;debugged firemode gameon = $0331 ;to check if game ;is on, or not levelct = $0332 ;our level counter pointer = $0340 ;pointer for multi ;purpose animation ;with sprites nomovebull = $0342 destroy = $0350 ;pointer to check ;explosion anim plrdestroy = $0351 gameover = $0352 MusicInit = $1000 ; Init music MusicPlay = $1003 ; Play music ;Some zeropages for you! xpos = $02 ;X-Position control of scrolling message firebutton = $03 ;Fire button control (Prevent button held) missilecounter = $04 ;Missile counter before flipping to next level ;Setup BASIC / SYS start address (Since nothing ;is overlapping memory $0801) *=$0801 !basic 2018,$3800 *=$0c00 attribs !bin "bin/attributes.bin" ;Insert the music (,,2 prg) *=$1000 !bin "bin/music.prg",,2 ;Insert the sprites *=$2000 !bin "bin/sprites.bin" ;Insert the status screen (pre-built from older build) *=$2700 !bin "bin/status.prg",,2 ;Insert the game binary charset *=$2800 !bin "bin/charset.bin" ;Insert the game screen binary (Made from Charpad) *=$3000 gamematrix ;Insert the title screen matrix (Made from Charpad) !bin "bin/screen.bin" *=$3400 titlematrix !bin "bin/titlescreen.bin" ;Insert the game screen colour attributes *= $3800 ;where we start our ;jmp address restart sei ;set irq flag lda #$00 ;Init xscroll sta xpos sta firebutton sta animdelay1 ;Reset animation timers sta animdelay2 sta missilecounter ;Reset number of missiles to destroy lda #$18 ;turn on screen sta $d016 ;multicolour lda #$1a sta $d018 ;Charset at $2800 lda #$0e ;Screen colour sta $d022 ; lda #$06 ;BLUE IS MY FAVOURITE COLOUR :) sta $d023 lda #$00 ;black the frame and sta $d021 ;background sta $d020 ; ;Draw the title screen from the exported binary ;from Charpad. ldx #$00 drawtitle lda titlematrix,x sta $400,x lda titlematrix+$100,x sta $0500,x lda titlematrix+$200,x sta $0600,x lda titlematrix+$2e8,x sta $06e8,x inx bne drawtitle ldx #$00 colourtitle ldy $0400,x lda attribs,y sta $d800,x ldy $0500,x lda attribs,y sta $d900,x ldy $0600,x lda attribs,y sta $da00,x ldy $06e8,x lda attribs,y sta $dae8,x inx bne colourtitle lda #$1a ;charset type sta $d018 ;read from $2800 lda #$00 ;no sprites on sta $d015 ;screen ;Reset title screen message lda #ScrollText sta MessRead+2 ;Call out interrupts for the title screen, to ;display the title screen scrolling message ;and also to play music. ldx #titleirq lda #$36 stx $0314 sty $0315 sta $d012 lda #$7f sta $dc0d lda #$1b sta $d011 lda #$01 sta $d01a lda #$00 jsr MusicInit cli jmp * waitfire lda $dc00 ;check for firebutton pressed lsr lsr lsr lsr lsr bit firebutton ror firebutton bmi waitfire2 bvc waitfire2 jmp exittitle waitfire2 rts ;Switch off IRQ interrupts from title screen exittitle sei ldx #$31 ldy #$ea lda #$00 sta $d01a sta $d019 stx $0314 sty $0315 lda #$81 sta $dc0d sta $dd0d lda #$00 sta firebutton jmp GameStart ;Title screen IRQ interrupt titleirq inc $d019 lda $dc0d sta $dd0d lda #$36 cmp $d012 bne *-3 lda #$18 sta $d016 jsr DoTitleScroll lda #$f1 cmp $d012 bne *-3 lda xpos sta $d016 jsr waitfire jsr PalNTSCCheck ;Check system for music player` jmp $ea7e ;Produce and perform the scroller for the title ;screen. DoTitleScroll lda xpos sec sbc #2 ;Speed set for example title and #7 sta xpos bcs EndScroll ldx #$00 shiftchr lda $07c1,x sta $07c0,x lda #$07 sta $dbc0,x inx cpx #$27 bne shiftchr MessRead lda ScrollText cmp #$00 bne StoreChar lda #ScrollText sta MessRead+2 jmp MessRead StoreChar sta $07e7 inc MessRead+1 bne EndScroll inc MessRead+2 EndScroll rts GameStart lda #$ff ;this is where we sta $d015 ;setup and init. sta $d01c ;all the sprites lda #$0b ;for our game sta $d025 ; lda #$01 ; sta $d026 ; lda #$80 ; sta $07f8 ; lda #$82 ; sta $07f9 ; lda #$8a ; sta $07fa ; sta $07fb ; sta $07fc ; sta $07fd ; sta $07fe ; sta $07ff ; ;reposition sprites according to ;postable. ldx #$00 possprts lda postable+$00,x sta spritepos+$00,x inx cpx #$10 bne possprts ;Set some colours for the game sprites, according ;to the colour table ldx #$00 spcols lda SpriteColourTable,x sta $d027,x inx cpx #$08 bne spcols ;draw the space background from reading ;the stored screen ($3000-$33e8) ldx #$00 drawgamescreen lda gamematrix,x sta $0400,x lda gamematrix+$100,x sta $0500,x lda gamematrix+$200,x sta $0600,x lda gamematrix+$2e8,x sta $06e8,x inx bne drawgamescreen ;Once again, draw the attributes on to ;the screen colours ldx #$00 drawattribs ldy $0400,x lda attribs,y sta $d800,x ldy $0500,x lda attribs,y sta $d900,x ldy $0600,x lda attribs,y sta $da00,x ldy $06e8,x lda attribs,y sta $dae8,x inx bne drawattribs lda #$18 ;turn on screen sta $d016 ;multicolour mode lda #$1a ;turn on charset sta $d018 ;fron $2800 lda #$06 ;use blue for sta $d023 ;multicolour 1 lda #$0e ;and lt blue for sta $d022 ;multicolour 2 ldx #$00 ;read 40 chars to status lda $2700,x ;paste the score sta $0400,x ;from $2700 to the lda #$07 ;screen ram ($400) sta $d800,x ; inx ; cpx #$28 ; bne status ; lda #$01 ; disable destroy sta destroy ; and set levelct sta levelct ; to level1 lda #$00 ; init the no of sta missilecounter ; missiles blasted lda #$00 ;disable the sta firelockup ;functions to sta plrdestroy ;lock controls sta pointer ;initialise the sta pointer+$01;pointers and sta nomovebull ;bullet status sta gameover ;disable ;game over lda #$08 jsr $ffd2 ;disable shift+cbm lda #int ;initialise and ldy #$00 ;we prepare to play sta $0314 ;the irq request stx $0315 ;flag, to run a sty $d012 ;continuous loop lda #$7f ;to perform more sta $dc0d ;tasks. sta $dd0d ; lda #$01 ; sta $d019 ; sta $d01a ; cli hold jmp hold int inc $d019 ;our main irq flag lda gameover ;is game over? if cmp #$01 ;so, end the game beq endgame jsr expand ;call expand jsr mvplayer ;call mvplayer jsr bulletmv ;call bulletmv jsr shipcol ;call shipcol jsr missile ;call missile jsr animate ;call animate jsr bullcol ;call bullcol jsr chkhit ;call chkhit jsr random ;call random jsr colroll ;call colroll jsr PalNTSCCheck jmp $ea7e ;irq loop endgame jsr explplr ;call explplr jsr colroll ; jsr PalNTSCCheck ;Check system for music player` jmp $ea7e ;expand sprite positions and put read ;data from spritepos into the main ;sprite position formats ($d000-$d00f) expand ldx #$00 xloop lda spritepos+$01,x sta $d001,x lda spritepos+$00,x asl a ;x position is more ror $d010 ;than 256 pixels sta $d000,x inx inx cpx #$10 bne xloop rts ;read the joystick in port 2 and move ;the player around the screen. pressing ;firebutton will make the player shoot ;a rocket. you should already know how ;the joystick control works. so no help ;is really reqired here. mvplayer lda $dc00 ;read joystick up lsr a ;check up bcs down ;not up ldy spritepos+$01; dey ;move player dey ;up, until it cpy #$48 ;reaches #$48 bcs setup ;then stop ldy #$48 ;moving player setup sty spritepos+$01 down lsr a ;check down bcs left ;not down ldy spritepos+$01; iny ;move player iny ;down until it cpy #$e2 ;reaches #$ec bcc setdown ;then stop ldy #$e2 ;moving player setdown sty spritepos+$01 left lsr a ;read left bcs right ;not left ldy spritepos+$00 dey ;as with up cpy #$0c ;and down, but bcs setleft ;moving left ldy #$0c ; setleft sty spritepos+$00 right lsr a ;read right bcs fire ;not right ldy spritepos+$00 iny ;as up and cpy #$9e ;down but bcc setright ;moving right ldy #$9e setright sty spritepos+$00 fire lsr a ;read fire bit firebutton ;Prevent firebutton hold down ror firebutton ;when firing. bmi nojoy ;not fire bvc nojoy lda #0 sta firebutton lda firelockup ; cmp #$01 ;check beq nojoy ;firelockup ;if not locked lda spritepos+$00;place bullet sta spritepos+$02;on ship and lda spritepos+$01;fire bullet sta spritepos+$03 lda #$01 ;lock fire sta firelockup ;until bullet ;finish its ;functional ;process nojoy rts ;the moving bullet ;this routine (as you already seen ;before) will check whether the bullet ;is at its home position, or is moving ;if the bullet is not moving then we ;call moveit, else we just jump on to ;nomovebl which ignores the bullet ;moving process. bulletmv lda nomovebull cmp #$01 beq nomovebl moveit lda spritepos+$03 sec sbc #$0c ;bullet fast enough? cmp #$36 ;Reached outside screen? bcs storebull ;No. store it to next position ;Reset bullet X/Yposition lda #$00 sta spritepos+$02 lda #$00 ;Bullet ready for firing again sta firelockup storebull sta spritepos+$03 lda #$82 sta $07f9 rts nomovebl ;check and perform the enemy to bullet ;collision detection. if bullet smacks ;the enemy, add points to the score. ;you already seen this sort of routine ;in our previous 2 player game tutorial ;you will also notice that this routine ;also works with control loops. where ;we kill the enemies. bullcol lda spritepos+$02 sec sbc #$06 sta collision+$00 clc adc #$0c sta collision+$01 lda spritepos+$03 sec sbc #$0c sta collision+$02 clc adc #$18 sta collision+$03 ;can you see what i mean. okay, this ;process is doing exactly the same as ;the player collision, but it works ;the bullet. when an enemy hits the ;player's bullet, it will die. else we ;just ignore the process. we add a score ;to any missile hit, and if 100 missiles ;is shot. we increase the speed for the ;next level - else ignore the process. ldx #$00 chkbcol lda spritepos+$04,x cmp collision+$00 bcc nohit cmp collision+$01 bcs nohit lda spritepos+$05,x cmp collision+$02 bcc nohit cmp collision+$03 bcs nohit lda #$00 sta spritepos+$05,x lda ranpos+$00 sta spritepos+$04,x lda #$00 ;turn on bullet sta destroy ;explosion ;this is how we add points to the score ;increment the character at screen ram ;$040b (the last zero digit on screen) ;by one, and then we call a loop, which ;will use the previous five zero digits ;to increment each number after reaching ;the nearest digit (after reaching '9' ;we increment each digit - and so on inc $0409 ;Give 100 points to the player ldx #$03 score lda $0406,x cmp #$3a bne setscore lda #$30 sta $0406,x inc $0405,x setscore dex bne score ;this is where we increment the amount ;of missiles that have been shot. if ;100 missiles have not been shot then ;ignore the rest of the process. else ;add 1 to levelct - which will increase ;the playing speed. also increment the ;character at $0427, which is the char ;at the end of the screen. inc missilecounter lda missilecounter cmp #100 bne stoploop lda #$00 sta missilecounter inc $0427 inc levelct lda levelct cmp #9 ;Past level 8? bne stoploop lda #1 ;Game won. Reset to level 1 sta levelct lda #$31 sta $0427 stoploop rts nohit inx inx cpx #$0c bne chkbcol rts ;since the bullet has hit the missile, ;we need to check if the destroy ;pointer is turned on, so that we can ;show the explosion animation for the ;enemy :) chkhit lda destroy cmp #$01 beq nodestroy lda #$01 sta nomovebull exploop1 lda animdelay2 cmp #2 beq doexplanim2 inc animdelay2 rts doexplanim2 lda #$00 sta animdelay2 ldx pointer+$01 lda expltbl+$00,x sta $07f9 inx cpx #7 ;Number of frames to read beq reset2 inc pointer+$01 rts ;reset the pointer and turn off the ;explosion generator for the bullet reset2 ldx #$00 stx pointer+$01 ldx #$01 stx destroy ldx #$00 stx firelockup stx nomovebull lda #$00 sta spritepos+$03 sta spritepos+$02 nodestroy rts ;missile to ship collision. if missile ;hits the player, make the player lose ;a shield from the ship and replace the ;enemy missile shipcol lda spritepos+$00 ;read player sec ;sprite and sbc #$06 ;calculate sta collision+$04 ;the position clc adc #$0c sta collision+$05 lda spritepos+$01 sec sbc #$0c sta collision+$06 clc adc #$18 sta collision+$07 ;this is where we read the collision ;detection for the player ship. if the ;player ship does not hit an enemy ;(collision+$04 - collision+$07) then ;this routine jumps to noshpcol, showing ;that there is no collision detected ;during the working process. however if ;collision+$04 to collision+$05 is read ;the missile is replaced at zero y-pos ;and we stop the player bullet and ;convert it into an explosion. ldx #$00 shipchk lda spritepos+$04,x cmp collision+$04 bcc noshpcol cmp collision+$05 bcs noshpcol lda spritepos+$05,x cmp collision+$06 bcc noshpcol cmp collision+$07 bcs noshpcol lda #$00 sta spritepos+$05,x lda ranpos+$00 sta spritepos+$04,x ;decrement the player's shield. if the ;player has lost all shields, switch on ;game over (where we destroy the player ;ship) to lock other functions. dec $0419 lda $0419 cmp #$30 bne stopscol lda #$01 sta gameover stopscol rts ;nothing has hit the player ship noshpcol inx ;where there is inx ;no collision cpx #$0c bne shipchk rts ;move those missiles. ;in this routine, we call a loop, which ;will move all the enemy missiles. we ;use levelct to control the speed of ;the missiles going down, and we use ;zero (adc #$00) to control the x-speed ;of the missiles. using #$00 does not ;move the x-position. missile ldx #$00 falloop lda spritepos+$04,x clc adc #$00 ;don't move x-pos sta spritepos+$04,x lda spritepos+$05,x clc adc levelct sta spritepos+$05,x inx inx cpx #$0c bne falloop rts ;multi-purpose animator routine animate lda animdelay1 cmp #2 beq doanimation1 inc animdelay1 rts doanimation1 lda #$00 sta animdelay1 ldx pointer animloop lda misstbl+$00,x sta $07fa sta $07fb sta $07fc sta $07fd sta $07fe sta $07ff lda plrtble+$00,x sta $07f8 inx cpx #7 beq reset inc pointer rts reset ldx #$00 stx pointer rts ;a control loop to read the random ;position table - to make the game more ;interesting :) random lda ranpos+$00 sta ranpos+$18 ldx #$00 ranloop lda ranpos+$01,x sta ranpos+$00,x inx cpx #$18 bne ranloop rts ;game is over and the player is dead so ;now we create our own explosion routine explplr lda animdelay2 cmp #$02 beq allowexplode inc animdelay2 rts allowexplode lda #$00 sta animdelay2 ldx pointer+$01 eloop lda expltbl+$00,x sta $07f8 inx cpx #7 ;Max no of frames beq reset3 inc pointer+$01 rts reset3 ldx #$00 stx pointer+$01 jmp restart ;Subroutine that does a colour washing effect over ;the status text at the top of the screen. colroll lda colours+$00 sta colours+$28 ldx #$00 col1 lda colours+$01,x sta colours+$00,x lda colours+$00,x sta $d800,x inx cpx #$28 bne col1 rts ;Pal/NTSC speed check to detect music speed PalNTSCCheck lda $02a6 cmp #$01 beq PAL inc ntscpointer lda ntscpointer cmp #6 beq ResetNTSC PAL jsr MusicPlay rts ResetNTSC lda #$00 sta ntscpointer rts animdelay1 !byte 0 animdelay2 !byte 0 ntscpointer !byte 0 ;Sprite colour table SpriteColourTable !byte $0e,$07,$03,$0a,$0d,$03,$0a,$0d ;Colour washing table. colours !byte $06,$06,$02,$02,$04,$04 !byte $05,$05,$03,$03,$07,$07 !byte $01,$01,$07,$07,$03,$03 !byte $05,$05,$04,$04,$02,$02 !byte $06,$06,$06,$06,$06,$06 !byte $06,$06,$06,$06,$06,$06 !byte $06,$06,$06,$06,$06,$06 !byte $06,$06,$06,$06,$06,$06 !byte $06 ;Starting position table for the sprites ;before the game commences. postable !byte $58,$e0,$00,$00,$0c,$30 !byte $32,$40,$5c,$50,$82,$60 !byte $45,$70,$75,$80 plrtble ;Animation table for the player ship !byte $80,$81,$80,$81,$80,$81,$80 ;Animation table for rotating missiles ;that are falling through space. misstbl !byte $8a,$8b,$8c,$8d,$8e,$8f,$90 ;Explosion animation frame table expltbl !byte $83,$84,$85,$86,$87,$88,$89 ;A small little random table, for ;randomly selecting the position of ;the next sprite X position ranpos !byte $58,$75,$0c,$45,$32,$82 !byte $5c,$7c,$15,$4c,$3c,$88 !byte $15,$4c,$85,$6c,$2c,$95 !byte $3c,$55,$7c,$45,$3c,$1c !byte $91 ;Some additional data (Title Screen Scroll text) !ct scr ScrollText !text "... welcome to - missile blasta " !text "- remastered edition - for assemble it ... prog" !text "ramming, graphics and music were " !text "all done by richard bayliss ... " !text " (c)2018 the new dimension / asse" !text "mble it ... this was a game i " !text "wrote back in 2003 in which was t" !text "he first version of the assemble " !text "it featured game, but i decided t" !text "o remaster the old version to mak" !text "e it look much nicer for the 2018" !text " assemble it update ... hopeful" !text "ly this game looks much nicer and" !text " more colourful compared to the 2" !text "003 version ... want some instr" !text "uctions on how to play this? ... " !text " okay, here goes ... using a" !text " joystick in port 2, move your sp" !text "ace ship, and keep tapping the fi" !text "re button to fire lasers at thos" !text "e missiles deep in the heart of o" !text "uter space - a place beyond the s" !text "tars ... for every 100 missiles " !text "shot, you will move on to the nex" !text "t level ... after each level pr" !text "ogresses, the missile will start " !text "to fall faster ... after the ei" !text "gth level, the game will start again ... okay, i think " !text "i have said enough now ... it i" !text "s time for you to press fire and " !text "be engrossed with this historical" !text " piece of code, remastered 15 yea" !text "rs later from it's past - into th" !text "e future ... goodbye for now! " !text " - press fire to play - " !text " " !byte 0