Lay some more groundwork for animating centipede segments. We now have an array of 96 (97 actually) entries which describe the position of the segment now or in the past. By keeping past information, body segments which follow head segments will take no calculation to update. We just have to animate head segments and body segments will follow them 8 pixels behind automatically.

This commit is contained in:
Jeremy Rand 2020-09-07 22:35:32 -04:00
parent 3b541f8482
commit 36617cbf9d
3 changed files with 153 additions and 55 deletions

View File

@ -17,13 +17,22 @@ gameSegments start
SEGMENT_MAX_NUM equ 12 SEGMENT_MAX_NUM equ 12
SEGMENT_MAX_OFFSET equ SEGMENT_MAX_NUM*2-2 SEGMENT_MAX_OFFSET equ SEGMENT_MAX_NUM*2-2
SEGMENT_STATE_NONE equ 0 SEGMENT_STATE_NONE equ 0
SEGMENT_STATE_HEAD equ 1 SEGMENT_STATE_HEAD equ 1
SEGMENT_STATE_BODY equ 2 SEGMENT_STATE_POISONED_HEAD equ 2
SEGMENT_STATE_BODY equ 3
SEGMENT_DIR_LEFT equ 0 SEGMENT_DIR_LEFT equ 0
SEGMENT_DIR_RIGHT equ 1 SEGMENT_DIR_RIGHT equ 1
SEGMENT_DIR_DOWN equ 0
SEGMENT_DIR_UP equ 1
; You would think I would need "facing up" variants here also. When the centipede gets to the bottom of
; the screen, it starts traveling up again and when it turns, you would think it would face up. Turns out
; the real arcade system uses "facing down" sprites even when the centipede is moving up. So, I guess I
; will too. I suspect that the players tend not to notice because by the time the centipede is traveling
; up, they are pretty occupied by the fact that they are now surrounded by segments.
SEGMENT_FACING_LEFT equ 0 SEGMENT_FACING_LEFT equ 0
SEGMENT_FACING_DOWN_LEFT equ 32 SEGMENT_FACING_DOWN_LEFT equ 32
SEGMENT_FACING_DOWN equ 64 SEGMENT_FACING_DOWN equ 64
@ -35,46 +44,55 @@ drawSegments entry
ldx #SEGMENT_MAX_OFFSET ldx #SEGMENT_MAX_OFFSET
drawSegments_nextSegment anop drawSegments_nextSegment anop
lda segmentStates,x lda segmentStates,x
beq drawSegments_skipSegment bne drawSegments_cont
jmp drawSegments_skipSegment
lda segmentFacing,x
clc
adc segmentSpriteOffset
tay
drawSegments_cont anop
phx
lda segmentStates,x lda segmentStates,x
cmp #SEGMENT_STATE_HEAD cmp #SEGMENT_STATE_BODY
beq drawSegments_head bne drawSegments_head
jsl segmentBodyJump jsl segmentBodyJump
bra drawSegments_handleTiles bra drawSegments_handleTiles
drawSegments_head anop drawSegments_head anop
jsl segmentHeadJump jsl segmentHeadJump
; By the time we come back from segment*Jump, the X register no longer has the original 0-22
; offset. Instead, we have a position offset which goes from 0-190. But that is good because
; we need to use that offset to update our dirty tiles.
drawSegments_handleTiles anop drawSegments_handleTiles anop
lda #TILE_STATE_DIRTY ; We do have to handle non-game tiles. When centipede reaches the bottom, new segements are
ldy segmentTileOffsetsUL,x ; added randomly in from the side. That segment needs to be clipped so we need to use non-game
sta tileDirty,y ; tiles to do that clipping for us.
_dirtyGameOrNonGameTileX segmentTileOffsetsUL
ldy segmentTileOffsetsUR,x _dirtyGameOrNonGameTileX segmentTileOffsetsUR
sta tileDirty,y _dirtyGameOrNonGameTileX segmentTileOffsetsLL
_dirtyGameOrNonGameTileX segmentTileOffsetsLR
ldy segmentTileOffsetsLL,x
sta tileDirty,y
ldy segmentTileOffsetsLR,x
sta tileDirty,y
; Get our original 0-22 offset we are iterating through that we pushed earlier because we know
; it was going to get trashed.
plx
drawSegments_skipSegment anop drawSegments_skipSegment anop
dex dex
dex dex
bpl drawSegments_nextSegment bmi drawSegments_done
jmp drawSegments_nextSegment
drawSegments_done anop drawSegments_done anop
rtl rtl
segmentHeadJump entry segmentHeadJump entry
lda segmentPosOffset,x
tax
lda segmentFacing,x
clc
adc segmentSpriteOffset
tay
lda segmentScreenShifts,x lda segmentScreenShifts,x
beq segmentHeadJump_noShift beq segmentHeadJump_noShift
@ -99,6 +117,14 @@ segmentHeadJump_jumpInst anop
nop nop
segmentBodyJump entry segmentBodyJump entry
lda segmentPosOffset,x
tax
lda segmentFacing,x
clc
adc segmentSpriteOffset
tay
lda segmentScreenShifts,x lda segmentScreenShifts,x
beq segmentBodyJump_noShift beq segmentBodyJump_noShift
@ -146,31 +172,44 @@ updateSegments_skipSpriteOffset anop
addBodySegment entry addBodySegment entry
lda numSegments lda #SEGMENT_MAX_NUM-1
sec
sbc numSegments
asl a asl a
tax tax
lda #SEGMENT_STATE_BODY lda #SEGMENT_STATE_BODY
sta segmentStates,x sta segmentStates,x
lda #SEGMENT_DIR_LEFT txa
sta segmentDirections,x asl a
asl a
asl a
sta segmentPosOffset,x
tay
lda #SEGMENT_FACING_LEFT lda #SEGMENT_DIR_RIGHT
sta segmentFacing,x sta segmentHorizontalDir,y
lda #SEGMENT_DIR_DOWN
sta segmentVerticalDir,y
lda #SEGMENT_FACING_RIGHT
sta segmentFacing,y
lda tileScreenOffset,x lda tileScreenOffset,x
sec sec
sbc #3 sbc #3
sta segmentScreenOffsets,x sta segmentScreenOffsets,y
stz segmentScreenShifts,x lda #0
sta segmentScreenShifts,y
txa txa
sta segmentTileOffsetsUL,x sta segmentTileOffsetsUL,y
sta segmentTileOffsetsUR,x sta segmentTileOffsetsUR,y
sta segmentTileOffsetsLL,x sta segmentTileOffsetsLL,y
sta segmentTileOffsetsLR,x sta segmentTileOffsetsLR,y
inc numSegments inc numSegments
@ -178,31 +217,44 @@ addBodySegment entry
addHeadSegment entry addHeadSegment entry
lda numSegments lda #SEGMENT_MAX_NUM-1
sec
sbc numSegments
asl a asl a
tax tax
lda #SEGMENT_STATE_HEAD lda #SEGMENT_STATE_HEAD
sta segmentStates,x sta segmentStates,x
lda #SEGMENT_DIR_LEFT txa
sta segmentDirections,x asl a
asl a
asl a
sta segmentPosOffset,x
tay
lda #SEGMENT_FACING_LEFT lda #SEGMENT_DIR_RIGHT
sta segmentFacing,x sta segmentHorizontalDir,y
lda #SEGMENT_DIR_DOWN
sta segmentVerticalDir,y
lda #SEGMENT_FACING_RIGHT
sta segmentFacing,y
lda tileScreenOffset,x lda tileScreenOffset,x
sec sec
sbc #3 sbc #3
sta segmentScreenOffsets,x sta segmentScreenOffsets,y
stz segmentScreenShifts,x lda #0
sta segmentScreenShifts,y
txa txa
sta segmentTileOffsetsUL,x sta segmentTileOffsetsUL,y
sta segmentTileOffsetsUR,x sta segmentTileOffsetsUR,y
sta segmentTileOffsetsLL,x sta segmentTileOffsetsLL,y
sta segmentTileOffsetsLR,x sta segmentTileOffsetsLR,y
inc numSegments inc numSegments
@ -216,15 +268,35 @@ shootSegment entry
numSegments dc i2'0' numSegments dc i2'0'
; The method used to track a segments position and other details on the screen are a bit
; funky. In order to have body segments follow a head segment, we keep information from
; the position of the head segment. The segmentPosOffset gives an offset into the other
; larger arrays (97 words) which describes the position of the segment. When a head is
; updated, the segmentPosOffset is decremented. That way, the previous positions are
; still there and body segments after that can reference it.
;
; We need at least 96 of them because a slow moving head segment goes through 8 positions
; before it can be re-used by the next body segment. If there are 12 segments max, we
; need (8*12) positions to ensure all segments can know where there position was and will
; be next.
;
; But I bump that count up to 97. When the segmentPosOffset is 0, the next one to use is
; the last. It is nice to assume that the previous position information is at (index + 2).
; That works all the time except when segmentPosOffset was 0 and now wraps around to 190
; or ((96 - 1) * 2). When that happens, we copy the info from 0 to 192 or (96 *2). That
; way the code can safely assume that the old position information is in fact always at.
; (index + 2).
segmentStates dc 12i2'SEGMENT_STATE_NONE' segmentStates dc 12i2'SEGMENT_STATE_NONE'
segmentDirections dc 12i2'SEGMENT_DIR_RIGHT' segmentPosOffset dc 12i2'0'
segmentFacing dc 12i2'SEGMENT_FACING_DOWN' segmentHorizontalDir dc 97i2'SEGMENT_DIR_RIGHT'
segmentScreenOffsets dc 12i2'0' segmentVerticalDir dc 97i2'SEGMENT_DIR_DOWN'
segmentScreenShifts dc 12i2'0' segmentFacing dc 97i2'SEGMENT_FACING_DOWN'
segmentTileOffsetsUL dc 12i2'0' segmentScreenOffsets dc 97i2'0'
segmentTileOffsetsUR dc 12i2'0' segmentScreenShifts dc 97i2'0'
segmentTileOffsetsLL dc 12i2'0' segmentTileOffsetsUL dc 97i2'0'
segmentTileOffsetsLR dc 12i2'0' segmentTileOffsetsUR dc 97i2'0'
segmentTileOffsetsLL dc 97i2'0'
segmentTileOffsetsLR dc 97i2'0'
SEGMENT_SPRITE_LAST_OFFSET gequ 7*4 SEGMENT_SPRITE_LAST_OFFSET gequ 7*4
segmentSpriteOffset dc i2'SEGMENT_SPRITE_LAST_OFFSET' segmentSpriteOffset dc i2'SEGMENT_SPRITE_LAST_OFFSET'

View File

@ -90,5 +90,31 @@ _dirtyGameTile_nonGame&SYSCNT anop
iny iny
sty numDirtyNonGameTiles sty numDirtyNonGameTiles
_dirtyGameTile_skip&SYSCNT anop
mend
macro
_dirtyGameOrNonGameTileX &tileOffset
ldy &tileOffset,x
cpy #RHS_FIRST_TILE_OFFSET
bge _dirtyGameTile_nonGame&SYSCNT
lda #TILE_STATE_DIRTY
sta tileDirty,y
bra _dirtyGameTile_skip&SYSCNT
_dirtyGameTile_nonGame&SYSCNT anop
lda tileDirty,y
bne _dirtyGameTile_skip&SYSCNT
lda #TILE_STATE_DIRTY
sta tileDirty,y
tya
ldy numDirtyNonGameTiles
sta dirtyNonGameTiles,y
iny
iny
sty numDirtyNonGameTiles
_dirtyGameTile_skip&SYSCNT anop _dirtyGameTile_skip&SYSCNT anop
mend mend

View File

@ -8,7 +8,7 @@ s6d2 =
s7d1 = /Users/jrand/Library/Developer/Xcode/DerivedData/BuGS-bffpexoblaghkzcbtjtzxeulnuto/Build/Products/Debug/BuGS.2mg s7d1 = /Users/jrand/Library/Developer/Xcode/DerivedData/BuGS-bffpexoblaghkzcbtjtzxeulnuto/Build/Products/Debug/BuGS.2mg
g_limit_speed = 3 g_limit_speed = 0
bram1[00] = 00 00 00 01 00 00 0d 06 02 01 01 00 01 00 00 00 bram1[00] = 00 00 00 01 00 00 0d 06 02 01 01 00 01 00 00 00