From 9a4d9e7fb755829cdde744a4f05e39a877c1e330 Mon Sep 17 00:00:00 2001 From: blondie7575 Date: Wed, 13 Sep 2017 07:53:40 -0600 Subject: [PATCH] First pass on terrain craters Also refactored collision/physics functions for improved appearance --- GSCats.xcodeproj/project.pbxproj | 2 + GenerateCircles.py | 49 +++++++++++++ V2Make.scpt | Bin 2460 -> 2460 bytes equates.s | 1 + gamemanager.s | 18 ++++- gscats.2mg | Bin 819264 -> 819264 bytes projectile.s | 122 ++++++++++++++++++++++--------- tables.s | 29 ++++++++ terrain.s | 56 +++++++++++++- 9 files changed, 242 insertions(+), 35 deletions(-) create mode 100755 GenerateCircles.py 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 050b92c37e624b7e7145f208a416c33e339945e9..eb180db3e574cd8fcbfb2819aeee9eaadc7db7d0 100644 GIT binary patch delta 22 ecmbOuJV$s#J{!|p_Q{28eoUK_HXmfW%>)2kdk8=P delta 22 ecmbOuJV$s#J{!}$?~@DJ{Fs&oZ9d3$n+X7C7YPFZ 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 75945a2a7d88085dea3c5d97cd44c58e355ec5b0..733bc52f958805b1f2e301a7ba73d512bca66b68 100644 GIT binary patch delta 2658 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 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