Fix a bug where it was possible for the player to collide with an exploding bug and then die. Change explosions so they are drawn using background colours which do not result in player collisions.

This commit is contained in:
Jeremy Rand 2021-01-18 00:18:31 -05:00
parent 678a9ee104
commit 1b7d2e240b
6 changed files with 172 additions and 163 deletions

View File

@ -4,12 +4,16 @@ BUGS
This is a list of the software bugs (as opposed to the bugs in the game that you shoot) that still need attention:
* The sound is muddy at times on real HW. Especially when lots of stuff is going on, the sound ends up coming out garbled. This isn't happening on emulators where everything is always quite clear. Perhaps I am reaching some limit of the Ensoniq. Do I need to reduce some sampling frequencies perhaps?
* It seems to be possible to both shoot and be killed by the spider in a single frame. Either the spider should be killed by the shot or the spider should kill the player but not both.
* I tried reducing the sampling frequency from 11025 for most of the samples to 5513 and I didn't notice any improvement in the quality of the sound on real HW. Nor did I notice any real degredation on real HW or on an emulator.
FIXED
=======
* It seems to be possible to both shoot and be killed by the spider in a single frame. Either the spider should be killed by the shot or the spider should kill the player but not both.
* Based on the code, I don't think it is possible that this happened in a single frame. Instead, I think what is happening is that the spider is being shot and then goes through a small number of explosion frames. The colour used in those explosion frames were detected as a collision to the player.
* I have changed the colours of the explosion to no longer be detected as a collision for the player.
* It is possible to shoot between two segments of a centipede. The problem is that there are black pixels between the segments and if things are timed just right (or just wrong), the shot can slot in at those black pixels and end up missing both segments.
* I am not sure how much can be done about this given how collisions are detected.
* I have implemented a fix which I believe solves this problem. The shot is a single pixel wide which allows it to slot in between a segment. I have changed the collision code to detect a collision if it is also if there is any pixel on in the byte (ie two pixels wide). That should ensure that the shot cannot pass through a centipede. Note it also makes things slightly easier to hit where before it might have passed right next to.

View File

@ -57,12 +57,8 @@ initPlayer_loop2 anop
bne initPlayer_loop2
initPlayer_done anop
jmp playerSwitch
jmp scoreSwitchPlayer
playerSwitch entry
jsl scoreSwitchPlayer
rtl
playerLevelStart entry
stz playerIgnoreFirstPoll

View File

@ -149,8 +149,8 @@ updateShot_collision anop
bge updateShot_onScreen
rtl
updateShot_onScreen anop
and #$3333
bne updateShot_maybeMushroom
and #$cccc
beq updateShot_maybeMushroom
txy
txa

View File

@ -16,9 +16,9 @@ explosions start spriteSeg
explosion1 entry
_spriteHeader
; $c - Green
; $4 - Red
; $8 - Off-white
; $1 - Green (c)
; $2 - Red (4)
; $3 - Off-white (8)
;
; ..RR|.R..
; .OGR|G...
@ -32,22 +32,22 @@ explosion1 entry
lda $0,s
and #$00ff
ora #$4400
ora #$2200
sta $0,s
lda $2,s
and #$fff0
ora #$0004
ora #$0002
sta $2,s
lda $a0,s
and #$00f0
ora #$c408
ora #$1203
sta $a0,s
lda $a2,s
; and #$ff0f not necessary with pure green
ora #$00c0
and #$ff0f
ora #$0010
sta $a2,s
tsc
@ -55,22 +55,21 @@ explosion1 entry
tcs
lda $0,s
; and #$ff0f not necessary with pure green
ora #$cc0c
and #$ff0f
ora #$1101
sta $0,s
lda $2,s
and #$0f00
ora #$40cc
ora #$2011
sta $2,s
lda #$cc4c
lda #$1121
sta $a0,s
lda $a2,s
and #$0f00
ora #$80cc
ora #$3011
sta $a2,s
tsc
@ -79,18 +78,18 @@ explosion1 entry
lda $0,s
and #$0f00
ora #$c04c
ora #$1021
sta $0,s
lda $2,s
; and #$fff0 not necessary with pure green
ora #$c0cc
and #$fff0
ora #$1011
sta $2,s
lda #$cc8c
lda #$1131
sta $a0,s
lda #$8ccc
lda #$3111
sta $a0,s
tsc
@ -99,22 +98,22 @@ explosion1 entry
lda $0,s
and #$00f0
ora #$cc08
ora #$1103
sta $0,s
lda $2,s
and #$0f00
ora #$804c
ora #$3021
sta $2,s
lda $a0,s
and #$00f0
ora #$8404
ora #$3202
sta $a0,s
lda $a2,s
and #$f0f0
ora #$0c04
ora #$0102
sta $a2,s
_spriteFooter
@ -124,9 +123,9 @@ explosion1 entry
explosion2 entry
_spriteHeader
; $c - Green
; $4 - Red
; $8 - Off-white
; $1 - Green
; $2 - Red
; $3 - Off-white
;
; ..GR|G.R.
; .GGG|GGRG
@ -140,61 +139,61 @@ explosion2 entry
lda $0,s
and #$00ff
ora #$c400
ora #$1200
sta $0,s
lda $2,s
and #$0f0f
ora #$40c0
ora #$2010
sta $2,s
lda $a0,s
; and #$00f0 not necessary with pure green
ora #$cc0c
and #$00f0
ora #$1101
sta $a0,s
lda #$4ccc
lda #$2111
sta $a2,s
tsc
adc #$143
tcs
pea $c8cc
pea $cc8c
pea $1311
pea $1131
adc #$a0
tcs
pea $cc8c
pea $c88c
pea $1131
pea $1331
adc #$a0
tcs
pea $c88c
pea $c88c
pea $1331
pea $1331
adc #$a0
tcs
pea $cccc
pea $cc8c
pea $1111
pea $1131
adc #$a0
tcs
pea $c8cc
pea $c48c
pea $1311
pea $1231
lda $a1,s
and #$f0f0
ora #$040c
ora #$0201
sta $a1,s
lda $a3,s
; and #$f0f0 not necessary for pure green
ora #$000c
and #$f0f0
ora #$0001
sta $a3,s
_spriteFooter
@ -204,9 +203,9 @@ explosion2 entry
explosion3 entry
_spriteHeader
; $c - Green
; $4 - Red
; $8 - Off-white
; $1 - Green
; $2 - Red
; $3 - Off-white
;
; .GOG|RG..
; G.GG|GGGR
@ -219,43 +218,43 @@ explosion3 entry
lda $0,s
and #$00f0
ora #$8c0c
ora #$3101
sta $0,s
lda $2,s
and #$ff00
ora #$004c
ora #$0021
sta $2,s
lda $a0,s
; and #$000f not necessary with pure green
ora #$ccc0
and #$000f
ora #$1110
sta $a0,s
lda #$c4cc
lda #$1211
sta $a2,s
tsc
adc #$140
tcs
lda #$c8cc
lda #$1311
sta $0,s
lda $2,s
and #$0f00
ora #$c0c8
ora #$1013
sta $2,s
lda $a0,s
and #$0f00
ora #$804c
ora #$3021
sta $a0,s
lda $a2,s
; and #$00f0 not necessary with pure green
ora #$cc0c
and #$00f0
ora #$1101
sta $a2,s
tsc
@ -263,41 +262,41 @@ explosion3 entry
tcs
lda $0,s
; and #$ff00 not necessary with pure green
ora #$00cc
and #$ff00
ora #$0011
sta $0,s
lda $2,s
; and #$fff0 not necessary with pure green
ora #$000c
and #$fff0
ora #$0001
sta $2,s
lda #$4cc4
lda #$2112
sta $a0,s
lda #$cc4c
lda #$1121
sta $a2,s
tsc
adc #$140
tcs
lda #$cc4c
lda #$1121
sta $0,s
lda $2,s
; and #$0f00 not necessary with pure green
ora #$c0cc
and #$0f00
ora #$1011
sta $2,s
lda $a0,s
and #$0ff0
ora #$c008
ora #$1003
sta $a0,s
lda $a2,s
and #$f0f0
ora #$080c
ora #$0301
sta $a2,s
_spriteFooter
@ -323,22 +322,22 @@ explosion4 entry
lda $0,s
and #$000f
ora #$c8c0
ora #$1310
sta $0,s
lda $2,s
and #$f0f0
ora #$0c04
ora #$0102
sta $2,s
lda $a0,s
and #$f0f0
ora #$0c08
ora #$0103
sta $a0,s
lda $a2,s
; and #$0f0f not necessary with pure green
ora #$c0c0
and #$0f0f
ora #$1010
sta $a2,s
tsc
@ -347,22 +346,22 @@ explosion4 entry
lda $0,s
and #$f000
ora #$044c
ora #$0221
sta $0,s
lda $2,s
and #$f0f0
ora #$0408
ora #$0203
sta $2,s
lda $a0,s
and #$0f0f
ora #$40c0
ora #$2010
sta $a0,s
lda $a2,s
; and #$0fff not necessary with pure green
ora #$c000
and #$0fff
ora #$1000
sta $a2,s
tsc
@ -370,23 +369,23 @@ explosion4 entry
tcs
lda $0,s
; and #$ff00 not necessary with pure green
ora #$00cc
and #$ff00
ora #$0011
sta $0,s
lda $2,s
and #$f0ff
ora #$0800
ora #$0300
sta $2,s
lda $a0,s
and #$f0f0
ora #$0404
ora #$0202
sta $a0,s
lda $a2,s
and #$00f0
ora #$c804
ora #$1302
sta $a2,s
tsc
@ -395,22 +394,22 @@ explosion4 entry
lda $0,s
and #$0f0f
ora #$4080
ora #$2030
sta $0,s
lda $2,s
and #$000f
ora #$c440
ora #$1220
sta $2,s
lda $a0,s
and #$f000
ora #$0c4c
ora #$0121
sta $a0,s
lda $a2,s
and #$0f00
ora #$80cc
ora #$3011
sta $a2,s
_spriteFooter
@ -435,23 +434,23 @@ explosion5 entry
;
lda $0,s
; and #$000f not necessary with pure green
ora #$000c
and #$000f
ora #$0001
sta $0,s
lda $2,s
; and #$f0f0 not necessary with pure green
ora #$c0c0
and #$f0f0
ora #$1010
sta $2,s
lda $a0,s
and #$00f0
ora #$8c04
ora #$3102
sta $a0,s
lda $a2,s
and #$0ff0
ora #$c004
ora #$1002
sta $a2,s
tsc
@ -460,22 +459,22 @@ explosion5 entry
lda $0,s
and #$ff00
ora #$00c8
ora #$0013
sta $0,s
lda $2,s
and #$f00f
ora #$08c0
ora #$0310
sta $2,s
lda $a0,s
and #$fff0
ora #$0004
ora #$0002
sta $a0,s
lda $a2,s
and #$0fff
ora #$4000
ora #$2000
sta $a2,s
tsc
@ -484,22 +483,22 @@ explosion5 entry
lda $0,s
and #$0f0f
ora #$40c0
ora #$2010
sta $0,s
lda $2,s
and #$f0f0
ora #$0404
ora #$0202
sta $2,s
lda $a0,s
and #$f0f0
ora #$0c08
ora #$0103
sta $a0,s
lda $a2,s
and #$0ff0
ora #$800c
ora #$3001
sta $a2,s
tsc
@ -508,22 +507,22 @@ explosion5 entry
lda $0,s
and #$0f00
ora #$404c
ora #$2021
sta $0,s
lda $2,s
; and #$0fff not necessary with pure green
ora #$c000
and #$0fff
ora #$1000
sta $2,s
lda $a0,s
; and #$f0f0 not necessary with pure green
ora #$0c0c
and #$f0f0
ora #$0101
sta $a0,s
lda $a2,s
and #$ff00
ora #$0084
ora #$0032
sta $a2,s
_spriteFooter
@ -549,22 +548,22 @@ explosion6 entry
lda $0,s
and #$f0f0
ora #$0c08
ora #$0103
sta $0,s
lda $2,s
; and #$0fff not necessary with pure green
ora #$c000
and #$0fff
ora #$1000
sta $2,s
lda $a0,s
and #$0f0f
ora #$c040
ora #$1020
sta $a0,s
lda $a2,s
and #$f000
ora #$0484
ora #$0232
sta $a2,s
tsc
@ -572,37 +571,37 @@ explosion6 entry
tcs
lda $a0,s
; and #$ff0f not necessary with pure green
ora #$00c0
sta $a0,s
lda $a2,s
; and #$0fff not necessary with pure green
ora #$c000
sta $a2,s
tsc
adc #$140
tcs
lda $0,s
and #$fff0
ora #$0008
sta $0,s
lda $2,s
; and #$f0ff not necessary with pure green
ora #$0c00
sta $2,s
lda $a0,s
and #$fff0
ora #$0008
and #$ff0f
ora #$0010
sta $a0,s
lda $a2,s
and #$0fff
ora #$8000
ora #$1000
sta $a2,s
tsc
adc #$140
tcs
lda $0,s
and #$fff0
ora #$0003
sta $0,s
lda $2,s
and #$f0ff
ora #$0100
sta $2,s
lda $a0,s
and #$fff0
ora #$0003
sta $a0,s
lda $a2,s
and #$0fff
ora #$3000
sta $a2,s
tsc
@ -611,22 +610,22 @@ explosion6 entry
lda $0,s
and #$0f0f
ora #$c040
ora #$1020
sta $0,s
lda $2,s
; and #$f0ff not necessary with pure green
ora #$0c00
and #$f0ff
ora #$0100
sta $2,s
lda $a0,s
and #$f0f0
ora #$0808
ora #$0303
sta $a0,s
lda $a2,s
and #$0f0f
ora #$4040
ora #$2020
sta $a2,s
_spriteFooter

View File

@ -16,9 +16,9 @@ scores start spriteSeg
score300 entry
_spriteHeader
; $c - Green
; $4 - Red
; $8 - Off-white
; $1 - Green
; $2 - Red
; $3 - Off-white
;
; ....|....|....
; ....|....|....
@ -123,9 +123,9 @@ score300 entry
score600 entry
_spriteHeader
; $c - Green
; $4 - Red
; $8 - Off-white
; $1 - Green
; $2 - Red
; $3 - Off-white
;
; ....|....|....
; ....|....|....
@ -231,9 +231,9 @@ score600 entry
score900 entry
_spriteHeader
; $c - Green
; $4 - Red
; $8 - Off-white
; $1 - Green
; $2 - Red
; $3 - Off-white
;
; ....|....|....
; ....|....|....

View File

@ -40,10 +40,14 @@ Each colour is 4 bits wide. All zeros is always black in all the different pall
* numbers
* letters
* symbols
* spider scores (300, 600 and 900)
* bug explosions
* solid squares (primarily the all black square)
These sprites generally draw first and overwrite what may have been there before. After the background layer is drawn, other things are drawn in this order:
* spiders/scores
These sprites generally draw first and overwrite what may have been there before. There are exceptions though. Spider scores and bug explosions do generally layer on top of the background but these things still use the "background colours" when drawn. The reason for this is that these background colours are not considered to be a collision if present when the player is drawn. We do not want the player to be considered dead just because it touched a spider score or bug explosion.
After the background layer is drawn, other things are drawn in this order:
* spiders
* scorpions
* fleas
* centipede segments
@ -63,3 +67,9 @@ An exception to the "background is drawn first" rule though is the non-playable
We also need to clip a flea which is dropping down from the top. The solution there is that the game allocates memory before the SHR page, enough for an extra unseen tile above the screen. A partially obscured flea is drawn offscreen into that part of memory before the SHR page.
There is a similar problem when the flea reaches the bottom of the screen. I have decided to just not handle it. The flea disappears once it reaches the bottom of the screen. It does not scroll off the bottom.
## Collisions
There are two sprites which need to detect collisions. We need to detect if the player has collided with a bug when we draw the player. The way that is done is that any pixel that the player will draw, we check to see if anding that pixel with $c results in a non-zero value. At least one of those two high bits will be set if the pixel has been drawn by a bug. Background sprites never set those bits. From there, we need to figure out if the bug that was collided with is a spider, flea of centipede segment. The player cannot collide with a scorpion because the are always in different parts of the screen. Once we know there is a collision, the code looks for tile overlap between the player and the spider, flea or centipede segment in order to figure out what collided.
The player's shot also collides with these things but also collides with mushrooms which are a background sprite. So, in this case, any non-zero value in a pixel being drawn to by the shot is considered to be a collision. In fact, the shot is only one pixel wide but a collision is said to occur if either nibble in the byte is non-zero. Once we have the data from the collision, that is anded with $c and if that is zero, that indicates that a mushroom collision may have occurred. Based on the address of the collision, that turns into a tile lookup. Otherwise, that may be a bug collision. As with player collisions, a check for tile overlap is what is used to figure out what kind of bug caused the collision.