;Assemble It - Game programming ;feature - Software Sprite/Background ;collision by Richard Bayliss. ;Game 6: Hyper Blitz ;IMPORTANT INFORMATION: ;---------------------- ;To get the collision working correctly ;your sprites must be pixelled from the ;very bottom area, to where you wish to ;draw it. Otherwise you will probably ;get an inaccurate collision and would ;need to constantly modify the sprite's ;width co-ordinates. !to "hyperblitz.prg",cbm ;Setup some variables bombreleased = $02 ;Bomb control pointer playerdead = $03 ;Death pointer screenlostore = $04;Low byte Char collision pointer screenhistore = $05 ;Hi byte Char collision pointer screenlostore2 = $06;Low byte Char collision pointer2 screenhistore2 = $07;Hi byte Char collision pointer 2 animdelay = $08 ;Delay for animation animpointer = $09 ;Actual anim pointer firebutton = $0a *=$0801 ;Basic SYS !basic 2018,$4000 ;Game music *=$1000 !bin "bin/gamemusic.prg",,2 ;Insert the game sprites ;into the source code ;Sprite data *=$2000 !bin "bin/gamesprites.prg",,2 ;Insert the charset into ;the source code ;charset *= $2800 !bin "bin/gamecharset.prg",,2 ;Insert your game screen *= $3000 !bin "bin/gamescreen.prg",,2 ;Main code. Setup the charset, screen ;and initialise the player sprite ;frame and position. *= $4000 sei ;Add my little info screen :) ldx #$00 putinfo lda $3400,x sta $0400,x lda $3500,x sta $0500,x lda $3600,x sta $0600,x lda $36e8,x sta $06e8,x lda #$03 sta $d800,x sta $d900,x sta $da00,x sta $dae8,x inx bne putinfo lda #$00 ;Look how this method ldx #$1a ;is used. Where we ldy #$18 ;store A,X,Y. Much sta $d020 ;tidier :) sta $d021 stx $d018 sty $d016 spacewt lda $dc01 ;Wait for spacebar cmp #$ef bne spacewt lda #$03 ;We only wish to use sta $d015 ;one sprite for this sta $d01c ;game. lda #$0b ldx #$05 sta $d023 stx $d022 lda #$80 ;Player ship default ldx #$83 ;Bomb default sta $07f8 stx $07f9 lda #$01 ldx #$0b ldy #$0e sta $d026 stx $d025 sty $d027 sty $d028 lda #irq sta $0315 lda #$32 sta $d012 lda #$7f sta $dc0d lda #$1b sta $d011 lda #$01 sta $d01a lda #$00 jsr $1000 ;Music init cli initall ;Draw the game screen (Fetching from the screen data ;address ($3000-$3400) and placing the screen data ;to the screen RAM. ldx #$00 drawscrn lda $3000,x sta $0400,x lda $3100,x sta $0500,x lda $3200,x sta $0600,x lda $32e8,x sta $06e8,x lda #$09 ;White multicolour sta $d800,x sta $d900,x sta $da00,x sta $dae8,x inx bne drawscrn ;Paint the last char row and make our ;default statusbar. ldx #$00 paint lda statusbar,x cmp #$40 bcc okay sec sbc #$40 okay sta $07c0,x ;Last row char lda #$07 sta $dbc0,x ;Last row cols inx cpx #$28 ;40 chars bne paint lda #$00 ldx #$3c sta playerx stx playery lda #$00 sta bombx sta bomby lda #$00 sta bombreleased ;bomb off sta playerdead ;dead off sta animdelay ;reset delay sta animpointer ;reset counter loop lda #$00 sta synctimer cmp synctimer beq *-3 jsr expandmsb ;Widen sprite MSB jsr animation ;Animate sprite jsr moveship ;Move player jsr readjoy ;Check for fire jsr movebomb ;Dropping bomb jsr bgrcoll ;Bomb/Background jsr bgrcoll2 ;Ship/Backgroumd jmp loop ;Expand the most significant bit of X ;for the sprites expandmsb ldx #$00 expandlp lda playery,x sta $d001,x lda playerx,x asl a ror $d010 sta $d000,x inx inx cpx #$10 ;We are only using bne expandlp ;2 sprites so rts ;Animate the player's sprite, depending ;on whether or not he's dead. If he's ;dead. Animate explosion routine, ;otherwise, animate the player ship's ;thrusters. animation lda playerdead cmp #$01 beq deathanim jmp animship rts ;Animate the player alive (Thrusters) animship lda animdelay cmp #$02 beq doshipanim inc animdelay rts doshipanim lda #$00 ;Reset delay per sta animdelay ;frame ldx animpointer lda playerframe,x sta $07f8 inx cpx #$04 beq resetplanim inc animpointer rts resetplanim ldx #$00 stx animpointer rts ;Animate the dead player deathanim lda animdelay cmp #$02 beq enddthdelay inc animdelay rts enddthdelay lda #$00 sta animdelay ldx animpointer lda explosionframe,x sta $07f8 inx cpx #$07 beq enddeath inc animpointer rts enddeath ldx #$00 stx animpointer lda #$00 sta $d000 ;Home actual sprite sta $d001 jmp gameover ;Move the player's ship until it is off ;screen. If the player is off screen, ;move playery down to 4 pixels and then ;reposition the player at zero x pos. moveship lda playerdead cmp #$01 beq nomove lda playerx clc adc #1 sta playerx cmp #$ac bcc keepmoving lda playery clc adc #4 sta playery lda #$00 sta playerx rts keepmoving sta playerx nomove rts ;Now we will try and read the fire ;button in joystick port 2. Pressing ;fire should release the bomb if ;the bomb has not already been dropped readjoy lda playerdead cmp #$01 beq nobomb lda $dc00 lsr a lsr a lsr a lsr a lsr a bcs nobomb ;Player pushes the fire button, but ;before we can release the bomb, we ;should check if the bomb is already ;released. If it is, then go straight ;to the 'nobomb' label to ignore ;the process. Otherwise position the ;bomb on to the player's x+y co-ords. ;Then switch on bombreleased prompt. lda playerx cmp #$0c bcc nobomb lda bombreleased cmp #$01 beq nobomb lda playerx sta bombx lda playery sta bomby lda #$01 sta bombreleased nobomb rts ;Ok, now let's move the bomb downwards ;until it has hit a certain position ;on screen. Then we offset it and then ;switch the 'bombreleased' pointer off ;so that the player can drop another ;bomb. movebomb lda playerdead cmp #$01 beq bomberase lda bombreleased cmp #$01 bne notready lda bomby clc adc #2 cmp #$e2 bcc notoff lda #$00 sta bomby sta bombx sta bombreleased rts notoff sta bomby notready rts bomberase lda #$00 sta bombx sta bomby rts ;Okay, now for the sprite/background ;character collision routine. To see ;how this works, please refer to the ;source underneath the tutorial ;heading SOFTWARE RELATED SPRITE TO ;BACKGROUND COLLISION. bgrcoll lda bomby;Bomb's Y position sec sbc #$32 ;Make sure collision lsr a ;does not go outside lsr a ;the upper border! lsr a tay lda screenlo,y ;Storing the sta screenlostore;low and hi lda screenhi,y ;bytes of the sta screenhistore;screen chars! lda bombx ;Bomb's X position sec sbc #$07 ;X-width of bomb lsr a lsr a tay ldx #$03 sty selfmod+1 ;For this part of the source, I used ;SHIFT + A and SHIFT + B for the chars ;that for the building. bgcloop lda (screenlostore),y cmp #$41 ;SHIFT+A hit? beq smashed cmp #$42 ;SHIFT+B hit? beq smashed;Building is smashed iny ;Increment Y to the selfmod ;loop jmp selfmod ;Self modifying loop. ;This will process the row of the screen ;chars for the whole screen to be read ;according to the low and high byte of ;the screen being read from the data ;table. selfmod ldy #$00 lda screenlostore clc adc #$28 ;Next row of chars sta screenlostore bcc skipmod inc screenhistore skipmod dex bne bgcloop rts ;The building is hit by the bomb so we ;do a simple routine which replaces the ;building's char with a spacebar char smashed lda #$20 sta (screenlostore),y ;Let player score points per char ;hit. (Player gets 10 points per block ;smashed). inc $07cb ;last but one digit ;where the score is ldx #$04 scoreloop lda $07c7,x cmp #$3a ;If char is over #$39 bne scok ;zero the digit lda #$30 ;Zero character sta $07c7,x inc $07c6,x scok dex bne scoreloop terminate rts ;The second background collision is ;exactly the same proceedure, except ;for that it is the player who is ;going to be crashing into buildings bgrcoll2 lda playerdead cmp #$01 beq terminate lda playery sec sbc #$32 lsr a lsr a lsr a tay lda screenlo,y sta screenlostore2 lda screenhi,y sta screenhistore2 lda playerx sec sbc #$0a ;Size of X sprite area ;(Player). lsr a lsr a tay ldx #$03 sty selfmod2+1 bgcloop2 lda (screenlostore2),y cmp #$41 beq dead cmp #$42 beq dead cmp #$43 beq landed iny lda (screenlostore2),y cmp #$41 beq dead cmp #$42 beq dead cmp #$43 beq landed jmp selfmod2 ;Self modifying loop. ;This will process the row of the ;screen chars for the whole screen ;to be read, according to the low and ;high byte of the screen being read ;from a data table. selfmod2 ldy #$00 lda screenlostore2 clc adc #$28 sta screenlostore2 bcc skipmod2 inc screenhistore2 skipmod2 dex bne bgcloop2 rts ;The player crashes into the building, ;so now we switch on the player death ;routine, so that we see the player ;is exploding :) dead lda #$00 sta animpointer sta animdelay lda #$01 sta playerdead rts ;Check if player's X-position is over ;#$9c after the player has landed. If ;the player has landed safely then ;show WELL DONE, otherwise, just ignore ;until at that position. landed lda playerx cmp #$92 bne belowpos jmp welldone belowpos rts ;Game over - Player is dead, the game ;is over, so let's end the game until ;the player presses the fire button to ;play again. gameover ldx #$00 putgo lda gomessage,x sec sbc #$40 sta $05c5,x lda #$02 sta $d9c5,x inx cpx #$09 bne putgo ;Check for high score, by checking each ;digit of the hiscore to the player's ;score individually. lda $07c7 sec lda $07e7 sbc $07cc lda $07e6 sbc $07cb lda $07e5 sbc $07ca lda $07e4 sbc $07c9 lda $07e3 sbc $07c8 lda $07e2 sbc $07c7 bpl nohiscore ldx #$00 puthi lda $07c7,x sta $07e2,x sta statusbar+$22,x lda #$30 ;zero score sta statusbar+$07,x inx cpx #$06 bne puthi ;Score reset. nohiscore hitfire lda $dc00 lsr a lsr a lsr a lsr a lsr a bit firebutton ror firebutton bvc hitfire bmi hitfire jmp initall ;Well Done. The same with Game Over, but ;we are using the Well Done text instead welldone ldx #$00 putwdmess lda wdmessage,x sec sbc #$40 sta $05c5,x lda #$05 sta $d9c5,x inx cpx #$09 bne putwdmess ;Copy current score to the status player ;status bar. ldx #$00 copytobar lda $07c7,x sta statusbar+$07,x inx cpx #$06 bne copytobar jmp hitfire ;IRQ raster interrupts and sync control irq inc $d019 lda #$fc sta $d012 lda #$01 sta synctimer jsr $1003 ;Music play jmp $ea7e ;Game status bar (40 chars) !ct scr statusbar !text "score: 000000 " !text " hi: 000000" gomessage !text "game over" wdmessage !text "well done" ;Sprite position tables playerx !byte $00 playery !byte $36 bombx !byte $00 bomby !byte $00 !byte 0,0,0,0,0,0,0,0,0,0,0,0 synctimer !byte $00 ;The low and high byte of the screen ;chars. We need to use this to carry ;out a check for the software sprite ;to character collision. screenhi !byte $04,$04,$04,$04,$04 !byte $04,$04,$05,$05,$05 !byte $05,$05,$05,$06,$06 !byte $06,$06,$06,$06,$07 !byte $07,$07,$07,$07,$07 !byte $07 screenlo !byte $00,$28,$50,$78,$a0 !byte $c8,$f0,$18,$40,$68 !byte $90,$b8,$e0,$08,$30 !byte $58,$80,$a8,$d0,$f8 !byte $20,$48,$70,$98,$c0 !byte $e8 ;Finally, to finish off, we have the ;animation table for the player sprite ;and also for the explosion routine. ;Player alive frame playerframe !byte $80,$81,$82,$81 ;Player exploding, and dead :) explosionframe !byte $83,$84,$85,$86,$87,$88