diff --git a/memory.asm b/memory.asm index 93f24e8..c63d41d 100644 --- a/memory.asm +++ b/memory.asm @@ -15,6 +15,8 @@ ; 0040-009F: {sprite, x, y, x-velocity, y-velocity, unused} per player shot. ; If sprite is 0, the shot is disabled. ; 00A0-015F: As above, for enemy shots. +; 0160-????: {sprite, x, y, move AI type, shoot AI type, shot cooldown} +; per enemy ship. ; [gap] ; Sprite table buffers -- copied each frame to OAM during VBlank, using DMA. ; 1000-11FF: table 1 (4 bytes each: x/y coord, tile #, flip/priority/palette) @@ -38,6 +40,10 @@ .define enemyShotArray $A0 .define enemyShotArrayLength 32 .define shotSize 6 +.define enemyShipArray $160 +.define enemyShipArrayLength 4 +.define enemyShipSize 6 + .define numSprites 128 .define spriteTableStart $1000 diff --git a/pewpew.asm b/pewpew.asm index 99efa8d..634edf0 100644 --- a/pewpew.asm +++ b/pewpew.asm @@ -471,7 +471,9 @@ MaybeShootDone: UpdateWorld: jsr UpdateShotCooldown + jsr SpawnEnemyShips jsr SpawnEnemyShots + jsr UpdateEnemyShips jsr UpdateShotPositions jsr CheckCollisionsWithPlayer jsr UpdateBackgroundScroll @@ -491,12 +493,86 @@ UpdateShotCooldown: +SpawnEnemyShips: + GetRandomByte + bit #%00111111 ; Spawn ships every this-many frames (on average). + beq + + rts ++ + ; Find an empty spot in the array. + ldy #0 +- + lda enemyShipArray, Y + cmp #0 + beq + + .rept enemyShipSize + iny + .endr + cpy #(enemyShipArrayLength * enemyShipSize) + bne - + rts ; Too many ships; bail. + ++ + lda #4 ; Sprite number. + sta enemyShipArray, Y + + lda #(256 - 32) + sta enemyShipArray + 1, Y ; x. + +- + GetRandomByte + cmp #(224 - 32) + bcs - ; Keep trying. + sta enemyShipArray + 2, Y ; y. + + lda #0 + sta enemyShipArray + 3, Y ; move AI type. + sta enemyShipArray + 4, Y ; shoot AI type. + + lda #8 + sta enemyShipArray + 5, Y ; shot cooldown. + + rts + + + +; TODO(mcmillen): reap ships if they move off the top, bottom, or right too. +UpdateEnemyShips: + ldy #0 +-- + lda enemyShipArray, Y + cmp #0 + beq ++ + + lda enemyShipArray + 1, Y ; x + clc + adc #-2 + bcs + + lda #0 + sta enemyShipArray, Y ; reap it. + bra ++ ++ + sta enemyShipArray + 1, Y + + +++ + .rept enemyShipSize + iny + .endr + + cpy #(enemyShipArrayLength * enemyShipSize) + bne -- + rts + + + SpawnEnemyShots: lda vBlankCounter bit #%00001111 ; Spawn shots every this-many frames. beq + rts + + ; Find an empty spot in the array. ldy #0 - lda enemyShotArray, Y @@ -604,7 +680,7 @@ ShotDone: .rept shotSize inx .endr - cpx #(playerShotArrayLength * enemyShotArrayLength * shotSize) + cpx #((playerShotArrayLength + enemyShotArrayLength) * shotSize) bne UpdateShot rts @@ -699,7 +775,7 @@ UpdateBackgroundScroll: -UpdateSprites: +UpdateSprites: ; TODO(mcmillen): refactor into smaller pieces. ; This page is a good reference on SNES sprite formats: ; http://wiki.superfamicom.org/snes/show/SNES+Sprites ; It uses the same approach we're using, in which we keep a buffer of the @@ -745,6 +821,42 @@ UpdateSprites: .endr iny + ; Now add enemy ships. + sty $00 ; Save sprite table 2 index. + ldy #0 ; Index into enemyShipArray. +- + lda enemyShipArray, Y + cmp #0 ; If not enabled, skip to next ship. + beq + + ; Update sprite table 1. + sta spriteTableStart + 2, X ; sprite number + lda enemyShipArray + 1, Y + sta spriteTableStart, X ; x + lda enemyShipArray + 2, Y + sta spriteTableStart + 1, X ; y + lda #%01000000 ; flip horizontally. + sta spriteTableStart + 3, X + ; Update secondary sprite table. + phy ; Save enemyShipArray index. + ldy $00 + lda #%11000000 ; Enable large sprite. + sta spriteTableScratchStart, Y + iny + sty $00 + ply ; Restore enemyShipArray index. + + .rept 4 + inx + .endr + ++ + .rept enemyShipSize + iny + .endr + cpy #(enemyShipArrayLength * enemyShipSize) + bne - + ldy $00 ; Restore Y to its rightful self. + ; Now add shots. sty $00 ; Save sprite table 2 index. ldy #0 ; Index into playerShotArray.