BuGS/BuGS/level.s
Jeremy Rand 1d4f783a3e Change the code for centipede speed to skip slow speed segments entirely once the score is more than 40000.
Add segments at the start of the next level in reverse order so the single head segments are added first.  This ensures they do collision detection properly in the updateSegment code.
Fix a bug where a set of 16 tiles were always marked as occupied by a centipede segment because we didn't clear it properly on each updateSegment call.  This fixed a problem with segments changing direction for no apparent reason.
Test for collisions on the two tiles the segment is spanning and change direction if either is occupied.  This should eliminate single segments travelling on top of each other.
Add scorpions randomly during a game once we get to level 4.  They are added with a 1 in 512 chance every 60 seconds so you should see a scorpion about once every 10 seconds or so.
When the score is above 20000, add scorpions at fast speed 3/4 of the time, slow speed the other 1/4 of the time.  Lower scores, the scorpion is always slow.
2020-10-23 00:20:18 -04:00

517 lines
14 KiB
ArmAsm

;
; level.s
; BuGS
;
; Created by Jeremy Rand on 2020-10-12.
;Copyright © 2020 Jeremy Rand. All rights reserved.
;
case on
mcopy level.macros
keep level
level start
using globalData
NEXT_LEVEL_FRAME_COUNT equ 60
levelInit entry
stz gameLevel
stz centipedeLevelNum
stz colourLevelNum
lda #SEGMENT_SPEED_FAST
sta levelOne+2
rtl
levelStart entry
lda colourLevelNum
jsl setColour
ldx centipedeLevelNum
lda levelTable,x
tax
lda |$0,x
sta centipedeNum
; We add centipedes in reverse order which means we need to load X up with the address
; of the last centipede. To do so, we:
; - subtract one from the number of centipedes
; - multiply by eight
; - add the starting location of the level information
; - add 2 to skip past the number of centipedes so we should now be
; at the start of the last centipede
; We do this because it is important that the single head segments are the ones which
; need to "avoid" the other segments and that happens when they are added first.
; See the update code in gameSegments.s to see why.
dec a
asl a
asl a
asl a
ldx centipedeLevelNum
clc
adc levelTable,x
tax
inx
inx
levelStart_loop anop
jsl addCentipede
dec centipedeNum
beq levelStart_done
txa
sec
sbc #8
tax
bra levelStart_loop
levelStart_done anop
rtl
updateLevel entry
lda gameRunning
bne updateLevel_done
lda nextLevelFrameCount
beq updateLevel_checkSegments
dec a
sta nextLevelFrameCount
bne updateLevel_done
jsl levelNext
jmp levelStart
updateLevel_checkSegments anop
lda numSegments
bne updateLevel_done
lda #NEXT_LEVEL_FRAME_COUNT
sta nextLevelFrameCount
updateLevel_done anop
rtl
levelNext entry
lda colourLevelNum
inc a
cmp #NUM_COLOUR_PALETTES
blt levelNext_skip
lda #0
levelNext_skip anop
sta colourLevelNum
inc gameLevel
lda gameScore+2
bne levelNext_fastOnly
lda gameScore
cmp #40000
bge levelNext_fastOnly
ldy centipedeLevelNum
ldx levelTable,y
lda |$2,x
cmp #SEGMENT_SPEED_FAST
beq levelNext_slowIncrement
lda #SEGMENT_SPEED_FAST
sta |$2,x
rtl
levelNext_slowIncrement anop
lda centipedeLevelNum
cmp #LEVEL_TABLE_LAST_OFFSET
bge levelNext_slowWrap
inc a
inc a
bra levelNext_slowNoWrap
levelNext_slowWrap anop
lda #0
levelNext_slowNoWrap anop
sta centipedeLevelNum
tay
ldx levelTable,y
lda #SEGMENT_SPEED_SLOW
sta |$2,x
rtl
levelNext_fastOnly anop
lda centipedeLevelNum
cmp #LEVEL_TABLE_LAST_OFFSET
bge levelNext_fastWrap
inc a
inc a
bra levelNext_fastNoWrap
levelNext_fastWrap anop
lda #0
levelNext_fastNoWrap anop
sta centipedeLevelNum
tay
ldx levelTable,y
lda #SEGMENT_SPEED_FAST
sta |$2,x
rtl
centipedeLevelNum dc i2'0'
colourLevelNum dc i2'0'
centipedeNum dc i2'0'
nextLevelFrameCount dc i2'0'
; The level structure looks like this:
; number of independent centipedes (2 bytes)
; { (for each independent centipede)
; segment speed (2 bytes)
; segment direction (2 bytes)
; tile offset where it appears (2 bytes)
; number of body segments (2 bytes)
; }
levelOne dc i2'1'
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'26' ; Tile offset
dc i2'11' ; Number of body segments
levelTwo dc i2'2'
dc i2'SEGMENT_SPEED_SLOW'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'26' ; Tile offset
dc i2'10' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'14' ; Tile offset
dc i2'0' ; Number of body segments
levelThree dc i2'3'
dc i2'SEGMENT_SPEED_SLOW'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'26' ; Tile offset
dc i2'9' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'14' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'38' ; Tile offset
dc i2'0' ; Number of body segments
levelFour dc i2'4'
dc i2'SEGMENT_SPEED_SLOW'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'26' ; Tile offset
dc i2'8' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'6' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'14' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'38' ; Tile offset
dc i2'0' ; Number of body segments
levelFive dc i2'5'
dc i2'SEGMENT_SPEED_SLOW'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'26' ; Tile offset
dc i2'7' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'6' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'14' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'38' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'46' ; Tile offset
dc i2'0' ; Number of body segments
levelSix dc i2'6'
dc i2'SEGMENT_SPEED_SLOW'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'26' ; Tile offset
dc i2'6' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'6' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'14' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'18' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'38' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'46' ; Tile offset
dc i2'0' ; Number of body segments
levelSeven dc i2'7'
dc i2'SEGMENT_SPEED_SLOW'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'26' ; Tile offset
dc i2'5' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'6' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'14' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'18' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'30' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'38' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'46' ; Tile offset
dc i2'0' ; Number of body segments
levelEight dc i2'8'
dc i2'SEGMENT_SPEED_SLOW'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'26' ; Tile offset
dc i2'4' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'2' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'6' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'14' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'18' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'30' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'38' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'46' ; Tile offset
dc i2'0' ; Number of body segments
levelNine dc i2'9'
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'26' ; Tile offset
dc i2'3' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'2' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'6' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'14' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'18' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'30' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'38' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'42' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'46' ; Tile offset
dc i2'0' ; Number of body segments
levelTen dc i2'10'
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'26' ; Tile offset
dc i2'2' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'2' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'6' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'10' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'14' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'18' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'30' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'38' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'42' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'46' ; Tile offset
dc i2'0' ; Number of body segments
levelEleven dc i2'11'
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'26' ; Tile offset
dc i2'1' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'2' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'6' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'10' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'14' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'18' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'30' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'34' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'38' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'42' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'46' ; Tile offset
dc i2'0' ; Number of body segments
levelTwelve dc i2'12'
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'26' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'2' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'6' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'10' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'14' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'18' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_LEFT'
dc i2'22' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'30' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'34' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'38' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'42' ; Tile offset
dc i2'0' ; Number of body segments
dc i2'SEGMENT_SPEED_FAST'
dc i2'SEGMENT_DIR_RIGHT'
dc i2'46' ; Tile offset
dc i2'0' ; Number of body segments
; Once we reach level 26 of the centipede levels, we go back to level 15. This is because
; we only have fast speed centipedes, with one more head at the start and one less body
; segment until they are all head segments and then back to a single 12 segment centipede at
; fast speed. By looping back from 26th level to the 15th level, we do this.
LEVEL_TABLE_LAST_OFFSET gequ 11*2
levelTable dc i2'levelOne'
dc i2'levelTwo'
dc i2'levelThree'
dc i2'levelFour'
dc i2'levelFive'
dc i2'levelSix'
dc i2'levelSeven'
dc i2'levelEight'
dc i2'levelNine'
dc i2'levelTen'
dc i2'levelEleven'
dc i2'levelTwelve'
end