From 36617cbf9ddbd723f0b57da1898b08faa4f9d56f Mon Sep 17 00:00:00 2001 From: Jeremy Rand Date: Mon, 7 Sep 2020 22:35:32 -0400 Subject: [PATCH] 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. --- BuGS/gameSegments.s | 180 ++++++++++++++++++++++++++++++------------- BuGS/global.macros | 26 +++++++ BuGS/make/config.txt | 2 +- 3 files changed, 153 insertions(+), 55 deletions(-) diff --git a/BuGS/gameSegments.s b/BuGS/gameSegments.s index ef0d3de..b6a2467 100644 --- a/BuGS/gameSegments.s +++ b/BuGS/gameSegments.s @@ -17,13 +17,22 @@ gameSegments start SEGMENT_MAX_NUM equ 12 SEGMENT_MAX_OFFSET equ SEGMENT_MAX_NUM*2-2 -SEGMENT_STATE_NONE equ 0 -SEGMENT_STATE_HEAD equ 1 -SEGMENT_STATE_BODY equ 2 +SEGMENT_STATE_NONE equ 0 +SEGMENT_STATE_HEAD equ 1 +SEGMENT_STATE_POISONED_HEAD equ 2 +SEGMENT_STATE_BODY equ 3 SEGMENT_DIR_LEFT equ 0 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_DOWN_LEFT equ 32 SEGMENT_FACING_DOWN equ 64 @@ -35,46 +44,55 @@ drawSegments entry ldx #SEGMENT_MAX_OFFSET drawSegments_nextSegment anop 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 - cmp #SEGMENT_STATE_HEAD - beq drawSegments_head + cmp #SEGMENT_STATE_BODY + bne drawSegments_head jsl segmentBodyJump bra drawSegments_handleTiles drawSegments_head anop 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 - lda #TILE_STATE_DIRTY - ldy segmentTileOffsetsUL,x - sta tileDirty,y - - ldy segmentTileOffsetsUR,x - sta tileDirty,y - - ldy segmentTileOffsetsLL,x - sta tileDirty,y - - ldy segmentTileOffsetsLR,x - sta tileDirty,y +; We do have to handle non-game tiles. When centipede reaches the bottom, new segements are +; added randomly in from the side. That segment needs to be clipped so we need to use non-game +; tiles to do that clipping for us. + _dirtyGameOrNonGameTileX segmentTileOffsetsUL + _dirtyGameOrNonGameTileX segmentTileOffsetsUR + _dirtyGameOrNonGameTileX segmentTileOffsetsLL + _dirtyGameOrNonGameTileX segmentTileOffsetsLR +; 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 dex dex - bpl drawSegments_nextSegment + bmi drawSegments_done + jmp drawSegments_nextSegment drawSegments_done anop rtl segmentHeadJump entry + lda segmentPosOffset,x + tax + + lda segmentFacing,x + clc + adc segmentSpriteOffset + tay + lda segmentScreenShifts,x beq segmentHeadJump_noShift @@ -99,6 +117,14 @@ segmentHeadJump_jumpInst anop nop segmentBodyJump entry + lda segmentPosOffset,x + tax + + lda segmentFacing,x + clc + adc segmentSpriteOffset + tay + lda segmentScreenShifts,x beq segmentBodyJump_noShift @@ -146,31 +172,44 @@ updateSegments_skipSpriteOffset anop addBodySegment entry - lda numSegments + lda #SEGMENT_MAX_NUM-1 + sec + sbc numSegments asl a tax lda #SEGMENT_STATE_BODY sta segmentStates,x + + txa + asl a + asl a + asl a + sta segmentPosOffset,x + tay - lda #SEGMENT_DIR_LEFT - sta segmentDirections,x + lda #SEGMENT_DIR_RIGHT + sta segmentHorizontalDir,y + + lda #SEGMENT_DIR_DOWN + sta segmentVerticalDir,y - lda #SEGMENT_FACING_LEFT - sta segmentFacing,x + lda #SEGMENT_FACING_RIGHT + sta segmentFacing,y lda tileScreenOffset,x sec sbc #3 - sta segmentScreenOffsets,x + sta segmentScreenOffsets,y - stz segmentScreenShifts,x + lda #0 + sta segmentScreenShifts,y txa - sta segmentTileOffsetsUL,x - sta segmentTileOffsetsUR,x - sta segmentTileOffsetsLL,x - sta segmentTileOffsetsLR,x + sta segmentTileOffsetsUL,y + sta segmentTileOffsetsUR,y + sta segmentTileOffsetsLL,y + sta segmentTileOffsetsLR,y inc numSegments @@ -178,31 +217,44 @@ addBodySegment entry addHeadSegment entry - lda numSegments + lda #SEGMENT_MAX_NUM-1 + sec + sbc numSegments asl a tax lda #SEGMENT_STATE_HEAD sta segmentStates,x - lda #SEGMENT_DIR_LEFT - sta segmentDirections,x + txa + asl a + asl a + asl a + sta segmentPosOffset,x + tay - lda #SEGMENT_FACING_LEFT - sta segmentFacing,x + lda #SEGMENT_DIR_RIGHT + sta segmentHorizontalDir,y + + lda #SEGMENT_DIR_DOWN + sta segmentVerticalDir,y + + lda #SEGMENT_FACING_RIGHT + sta segmentFacing,y lda tileScreenOffset,x sec sbc #3 - sta segmentScreenOffsets,x + sta segmentScreenOffsets,y - stz segmentScreenShifts,x + lda #0 + sta segmentScreenShifts,y txa - sta segmentTileOffsetsUL,x - sta segmentTileOffsetsUR,x - sta segmentTileOffsetsLL,x - sta segmentTileOffsetsLR,x + sta segmentTileOffsetsUL,y + sta segmentTileOffsetsUR,y + sta segmentTileOffsetsLL,y + sta segmentTileOffsetsLR,y inc numSegments @@ -216,15 +268,35 @@ shootSegment entry 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' -segmentDirections dc 12i2'SEGMENT_DIR_RIGHT' -segmentFacing dc 12i2'SEGMENT_FACING_DOWN' -segmentScreenOffsets dc 12i2'0' -segmentScreenShifts dc 12i2'0' -segmentTileOffsetsUL dc 12i2'0' -segmentTileOffsetsUR dc 12i2'0' -segmentTileOffsetsLL dc 12i2'0' -segmentTileOffsetsLR dc 12i2'0' +segmentPosOffset dc 12i2'0' +segmentHorizontalDir dc 97i2'SEGMENT_DIR_RIGHT' +segmentVerticalDir dc 97i2'SEGMENT_DIR_DOWN' +segmentFacing dc 97i2'SEGMENT_FACING_DOWN' +segmentScreenOffsets dc 97i2'0' +segmentScreenShifts dc 97i2'0' +segmentTileOffsetsUL dc 97i2'0' +segmentTileOffsetsUR dc 97i2'0' +segmentTileOffsetsLL dc 97i2'0' +segmentTileOffsetsLR dc 97i2'0' SEGMENT_SPRITE_LAST_OFFSET gequ 7*4 segmentSpriteOffset dc i2'SEGMENT_SPRITE_LAST_OFFSET' diff --git a/BuGS/global.macros b/BuGS/global.macros index fb18cc0..0c7a89b 100644 --- a/BuGS/global.macros +++ b/BuGS/global.macros @@ -90,5 +90,31 @@ _dirtyGameTile_nonGame&SYSCNT anop iny 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 mend diff --git a/BuGS/make/config.txt b/BuGS/make/config.txt index 4cf9182..6e02df5 100644 --- a/BuGS/make/config.txt +++ b/BuGS/make/config.txt @@ -8,7 +8,7 @@ s6d2 = 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