diff --git a/GSCats.xcodeproj/project.pbxproj b/GSCats.xcodeproj/project.pbxproj index 320c646..acb90df 100644 --- a/GSCats.xcodeproj/project.pbxproj +++ b/GSCats.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 706DF1641F2D39F700AA6680 /* loader.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = loader.s; sourceTree = ""; }; 706DF1651F2D4A8100AA6680 /* terrain.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = terrain.s; sourceTree = ""; }; 7088096D1F2ECE8D00D4C950 /* GenerateRenderSpans.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = GenerateRenderSpans.py; sourceTree = ""; }; + 709175C01F60D263008FAFAB /* GenerateCircles.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = GenerateCircles.py; sourceTree = ""; }; 7099E3841F41022100182A82 /* gameobject.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = gameobject.s; sourceTree = ""; }; 7099E3851F4107B100182A82 /* GenerateVRAMYOffset.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = GenerateVRAMYOffset.py; sourceTree = ""; }; 70A80FB01F43D7F200BD34C9 /* gamemanager.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = gamemanager.s; sourceTree = ""; }; @@ -53,6 +54,7 @@ 7059502B1F37A0BE00BBE90F /* GenerateVRAMTable.py */, 7099E3851F4107B100182A82 /* GenerateVRAMYOffset.py */, 700F21E01F4A3A5500D7007D /* GenerateTrigTables.py */, + 709175C01F60D263008FAFAB /* GenerateCircles.py */, ); sourceTree = ""; }; diff --git a/GenerateCircles.py b/GenerateCircles.py new file mode 100755 index 0000000..22e8485 --- /dev/null +++ b/GenerateCircles.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 + +import sys +import math + +def main(argv): + + minRadius = 3 + maxRadius = 10 + + print ("circleTable:\t\t;-Y for each X, in words") + + for radius in range(0,maxRadius+1): + if radius < minRadius: + print ("\t.addr 0") + else: + print ("\t.addr circleTable%d" % radius) + + print() + + for radius in range(minRadius,maxRadius+1): + + print ("circleTable%d:" % radius) + print ("\t.word ",end="") + + skipMinus1 = 0 + for p in range(0,radius): + x = radius-p + y = (int)(math.sqrt(radius*radius - x*x)) + if p==radius-1: # A fudge to make circles close better + y = radius + y*=-4 # Because X=words and we need -Y + print (y, end=",") + + skipMinus1 = 0 + for p in range(0,radius): + x = p+1 + y = (int)(math.sqrt(radius*radius - x*x)) + if p==0: # A fudge to make circles close better + y = radius + + y*=-4 # Because X=words and we need -Y + if p==radius-1: + print(y) + else: + print (y, end=",") + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/V2Make.scpt b/V2Make.scpt index 050b92c..eb180db 100644 Binary files a/V2Make.scpt and b/V2Make.scpt differ diff --git a/equates.s b/equates.s index f0cf28c..c4f96a5 100644 --- a/equates.s +++ b/equates.s @@ -19,4 +19,5 @@ PARAML1 = $08 SCRATCH0 = $19 SCRATCH1 = $1a SCRATCHL = $19 ; 16-bit version of scratch +SCRATCHL2 = $67 ; Second 16-bit scratch PARAM24 = $67 ; 24-bit param (This is almost certainly messing up AppleSoft, but meh) diff --git a/gamemanager.s b/gamemanager.s index 3fb8dd6..8842bc4 100644 --- a/gamemanager.s +++ b/gamemanager.s @@ -22,6 +22,21 @@ beginGameplay: ; Generate, compile, and clip terrain jsr generateTerrain + +; lda #40 +; sta PARAML0 +; lda #30 +; sta PARAML1 +; ldy #12 +; jsr craterTerrain + +; lda #74 +; sta PARAML0 +; lda #30 +; sta PARAML1 +; ldy #16 +; jsr craterTerrain + jsr compileTerrain jsr clipTerrain @@ -83,8 +98,9 @@ gameplayLoopFire: gameplayLoopProjectiles: sta KBDSTROBE jsr unrenderProjectiles - jsr updateProjectiles + jsr updateProjectilePhysics jsr renderProjectiles + jsr updateProjectileCollisions lda turnRequested beq gameplayLoopVictoryCondition diff --git a/gscats.2mg b/gscats.2mg index 75945a2..733bc52 100644 Binary files a/gscats.2mg and b/gscats.2mg differ diff --git a/projectile.s b/projectile.s index d6e4aa5..ea21751 100644 --- a/projectile.s +++ b/projectile.s @@ -30,10 +30,11 @@ GRAVITY = $ffff ; 8.8 fixed point projectileTypes: ; Byte offsets into projectile type data structure .word 50 ; Damage - .word 0,0,0 ; Padding + .word 12 ; Crater radius + .word 0,0 ; Padding PT_DAMAGE = 0 - +PT_RADIUS = 2 .macro PROJECTILEPTR_Y @@ -133,17 +134,18 @@ fireProjectile: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; updateProjectiles +; updateProjectilePhysics ; ; Trashes SCRATCHL ; -updateProjectiles: +updateProjectilePhysics: SAVE_AY - lda projectileData+GO_POSX - bpl updateProjectilesActive - jmp updateProjectilesDone -updateProjectilesActive: + lda projectileData+GO_POSX + bpl updateProjectilePhysicsActive + jmp updateProjectilePhysicsDone + +updateProjectilePhysicsActive: ; Integrate gravity over velocity lda projectileData+JD_VY clc @@ -171,15 +173,11 @@ updateProjectilesActive: lsr lsr sta projectileData+GO_POSX - bmi updateProjectilesOffWorld + bmi updateProjectilePhysicsDelete cmp #TERRAINWIDTH-GAMEOBJECTWIDTH-1 - bpl updateProjectilesOffWorld - bra updateProjectilesContinue + bpl updateProjectilePhysicsDelete -updateProjectilesOffWorld: - jmp updateProjectilesDelete - -updateProjectilesContinue: +updateProjectilePhysicsContinue: ; Integrate Y velocity over position lda projectileData+JD_VY ; Convert 8.8 to 12.4 @@ -202,13 +200,31 @@ updateProjectilesContinue: lsr sta projectileData+GO_POSY cmp #GAMEOBJECTHEIGHT - bmi updateProjectilesDelete + bmi updateProjectilePhysicsDelete cmp #201 - bpl updateProjectilesDelete + bpl updateProjectilePhysicsDelete + +updateProjectilePhysicsDone: + RESTORE_AY + rts + +updateProjectilePhysicsDelete: + jsr endProjectile + bra updateProjectilePhysicsDone + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; updateProjectileCollisions +; +; Trashes SCRATCHL +; +updateProjectileCollisions: + SAVE_AY ; Check for player collisions ldy #0 lda projectileData+GO_POSX + bmi updateProjectileCollisionsDone ; Projectile not active sta rectParams lda projectileData+GO_POSY sta rectParams+2 @@ -217,17 +233,17 @@ updateProjectilesContinue: lda #GAMEOBJECTHEIGHT sta rectParams+6 -updateProjectilesPlayerLoop: +updateProjectileCollisionsPlayerLoop: iny cpy #NUMPLAYERS - beq updateProjectilesPlayerDone + beq updateProjectileCollisionsPlayerDone cpy currentPlayer - beq updateProjectilesPlayerLoop + beq updateProjectileCollisionsPlayerLoop jsr playerIntersectRect cmp #0 - bne updateProjectilesPlayerHit + bne updateProjectileCollisionsPlayerHit -updateProjectilesPlayerDone: +updateProjectileCollisionsPlayerDone: ; Check for terrain collisions lda projectileData+GO_POSX @@ -241,27 +257,36 @@ updateProjectilesPlayerDone: jsr intersectRectTerrain cmp #0 - bne updateProjectilesTerrainHit + bne updateProjectileCollisionsTerrainHit -updateProjectilesDone: +updateProjectileCollisionsDone: RESTORE_AY rts -updateProjectilesDelete: +updateProjectileCollisionsPlayerHit: + jsr processPlayerImpact + jsr endProjectile + bra updateProjectileCollisionsDone + +updateProjectileCollisionsTerrainHit: + jsr processTerrainImpact + jsr endProjectile + bra updateProjectileCollisionsDone + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; endProjectile +; +; Trashes A and Y +; +endProjectile: ldy #0 jsr deleteProjectile lda #1 sta turnRequested lda #-1 sta projectileActive - bra updateProjectilesDone - -updateProjectilesPlayerHit: - jsr processPlayerImpact - bra updateProjectilesDelete - -updateProjectilesTerrainHit: - bra updateProjectilesDelete + rts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -348,3 +373,34 @@ processPlayerImpactDeath: lda currentPlayer sta gameOver rts + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; processTerrainImpact +; +; Trashes A,Y +; +processTerrainImpact: + ldy #0 ; Assume projectile 0 + PROJECTILEPTR_Y + lda projectileData+GO_POSX,y + clc + adc #GAMEOBJECTWIDTH/2 + sta PARAML0 + lda projectileData+GO_POSY,y + sec + sbc #GAMEOBJECTHEIGHT + sta PARAML1 + + lda projectileData+JD_TYPE,y + tay + PROJECTILETYPEPTR_Y + + lda projectileTypes+PT_RADIUS,y + tay + + jsr craterTerrain + jsr compileTerrain + jsr clipTerrain + + rts diff --git a/tables.s b/tables.s index a2439aa..dfbe902 100644 --- a/tables.s +++ b/tables.s @@ -152,3 +152,32 @@ vramYOffset: .word $6400,$64a0,$6540,$65e0,$6680,$6720,$67c0,$6860,$6900,$69a0,$6a40,$6ae0,$6b80,$6c20,$6cc0,$6d60,$6e00,$6ea0,$6f40,$6fe0 .word $7080,$7120,$71c0,$7260,$7300,$73a0,$7440,$74e0,$7580,$7620,$76c0,$7760,$7800,$78a0,$7940,$79e0,$7a80,$7b20,$7bc0,$7c60 +circleTable: ;-Y for each X, in words + .addr 0 + .addr 0 + .addr 0 + .addr circleTable3 + .addr circleTable4 + .addr circleTable5 + .addr circleTable6 + .addr circleTable7 + .addr circleTable8 + .addr circleTable9 + .addr circleTable10 + +circleTable3: + .word 0,-8,-12,-12,-8,0 +circleTable4: + .word 0,-8,-12,-16,-16,-12,-8,0 +circleTable5: + .word 0,-12,-16,-16,-20,-20,-16,-16,-12,0 +circleTable6: + .word 0,-12,-16,-20,-20,-24,-24,-20,-20,-16,-12,0 +circleTable7: + .word 0,-12,-16,-20,-24,-24,-28,-28,-24,-24,-20,-16,-12,0 +circleTable8: + .word 0,-12,-20,-24,-24,-28,-28,-32,-32,-28,-28,-24,-24,-20,-12,0 +circleTable9: + .word 0,-16,-20,-24,-28,-32,-32,-32,-36,-36,-32,-32,-32,-28,-24,-20,-16,0 +circleTable10: + .word 0,-16,-24,-28,-32,-32,-36,-36,-36,-40,-40,-36,-36,-36,-32,-32,-28,-24,-16,0 diff --git a/terrain.s b/terrain.s index 76bdb06..787f57a 100644 --- a/terrain.s +++ b/terrain.s @@ -47,6 +47,60 @@ renderRowComplete: rts +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; craterTerrain +; +; PARAML0 = X pos of center in pixels from logical left terrain edge +; PARAML1 = Y pos of center in pixels from bottom terrain edge +; Y = Radius of circle, in pixels +; +; Trashes SCRATCHL +craterTerrain: + SAVE_AX + + lda #TERRAINWIDTH ; Convert X pos to terrain-right byte count + sec + sbc PARAML0 + sty SCRATCHL ; Center width + sbc SCRATCHL + lsr + and #$fffe + clc + adc #terrainData + sta PARAML0 + + phy + tya ; Look up circle data + lsr + tay + lda circleTable,y + sta SCRATCHL + ply + +craterTerrainLoop: + dey + dey + bmi craterTerrainDone + + lda (SCRATCHL),y ; Fetch circle Y value + clc + adc PARAML1 ; Convert to terrain-space + sta SCRATCHL2 + lda (PARAML0),y + cmp SCRATCHL2 + bmi craterTerrainLoop + + lda SCRATCHL2 ; Circle value is lower, so use that + sta (PARAML0),y + bra craterTerrainLoop + +craterTerrainDone: + lda #1 + sta terrainDirty + + RESTORE_AX + rts + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; clipTerrain @@ -272,7 +326,7 @@ generateTerrainLoop: -; Terrain data, stored as height values 4 pixels wide +; Terrain data, stored as height values 4 pixels wide (words) terrainData: .repeat TERRAINWIDTH/4 ; VISIBLETERRAINWIDTH