aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/background.s28
-rw-r--r--src/jetpac.s1
-rw-r--r--src/player.s135
3 files changed, 130 insertions, 34 deletions
diff --git a/src/background.s b/src/background.s
new file mode 100644
index 0000000..5a9c5fe
--- /dev/null
+++ b/src/background.s
@@ -0,0 +1,28 @@
+.segment "CODE"
+
+.scope Background
+ ;; Screen coordinates on the Y axis for the ground.
+ GROUND_Y_COORD = $C8
+
+ ;; To make them easier to traverse when performing background collision
+ ;; checking, each platform is laid out in tile coordinates and spanning
+ ;; three bytes: tile row, tile column beginning, tile column end.
+ platforms:
+ ;; Top of the screen.
+ .byte $03, $00, $FF
+
+ ;; Left platform.
+ .byte $09, $18, $1D
+
+ ;; Center platform.
+ .byte $0C, $03, $08
+
+ ;; Right platform.
+ .byte $0F, $0F, $12
+
+ ;; Ground.
+ .byte $19, $00, $FF
+
+ ;; End of the list.
+ .byte $FF
+.endscope
diff --git a/src/jetpac.s b/src/jetpac.s
index e997af1..66d5457 100644
--- a/src/jetpac.s
+++ b/src/jetpac.s
@@ -38,6 +38,7 @@
.include "../include/globals.s"
.include "assets.s"
+.include "background.s"
.include "player.s"
.include "driver.s"
.include "title.s"
diff --git a/src/player.s b/src/player.s
index cee79cf..3ae90c9 100644
--- a/src/player.s
+++ b/src/player.s
@@ -25,20 +25,26 @@
;; - Translating positions into screen coordinates it's a matter of simply
;; rolling the low nibble of the high byte into the low byte.
- INIT_Y_POSITION_LO = $80
- INIT_Y_POSITION_HI = $0C
+ ;; The height of the player, which is 24 pixels long as it's made up of 3
+ ;; sprites.
+ PLAYER_HEIGHT = $18
+
+ ;; The initial position is the ground minus the height of the sprite (as the
+ ;; Y accounts for the top left pixel). For the high byte we only want to
+ ;; high nibble put into its low nibble, and for the low byte we shift the
+ ;; low nibble into a high one and leave subpixels to 0.
+ INIT_Y_POSITION_LO = ((Background::GROUND_Y_COORD - PLAYER_HEIGHT) & $0F) << 4
+ INIT_Y_POSITION_HI = (Background::GROUND_Y_COORD - PLAYER_HEIGHT) >> 4
INIT_Y_VELOCITY = $08
+ ;; The initial position on the X axis is more or less at the center.
INIT_X_POSITION_LO = $00
- INIT_X_POSITION_HI = $04
+ INIT_X_POSITION_HI = $07
THROTTLE = $D8
BLAST_OFF = $F8
GRAVITY = $28
- UPPER_LIMIT = 10
- GROUND_LIMIT = 200
-
zp_screen_y = $40
zp_position_y = $41 ; NOTE: 16-bit.
zp_target_velocity_y = $43 ; TODO: needed?
@@ -115,7 +121,7 @@
;; coordinates, eject out from boundaries and platforms, and update the
;; sprite with the new state.
jsr position_to_screen
- jsr bound_check
+ jsr background_check
JAL update_sprite
.endproc
@@ -236,42 +242,103 @@
;; Check on whether the player is out of bounds in any way and provide an
;; ejection logic for each situation.
- .proc bound_check
- ;; Are we at the top?
- ;; TODO: actually buggy, but nevermind for now
+ .proc background_check
+ ;; If we are going down, the player's height should be added to the
+ ;; coordinate, as we are checking for the bottom.
lda zp_screen_y
- cmp #UPPER_LIMIT
- beq @too_high_icarus
- bcs @check_ground
- @too_high_icarus:
- lda #0
- sta zp_velocity_y
- lda #UPPER_LIMIT
- sta zp_screen_y
- rts
-
- ;; Nope, are we at the ground?
- @check_ground:
- cmp #(GROUND_LIMIT - 24)
- bcc @above_ground
+ ldx zp_velocity_y
+ bmi :+
+ clc
+ adc #PLAYER_HEIGHT
+ :
+ ;; And convert raw screen coordinates into a tile coordinate.
+ lsr
+ lsr
+ lsr
+ sta Globals::zp_tmp0
- ;; We appear to be either at the ground or below it (e.g. we are
- ;; standing still but initial gravity is pulling us down). In this case,
- ;; just reset the Y velocity and the Y position.
- lda #0
- sta zp_velocity_y
- lda #(GROUND_LIMIT - 24)
+ ;; We do the same for the X axis.
+ lda zp_screen_x
+ tay
+ lsr
+ lsr
+ lsr
+ sta Globals::zp_tmp1
+ tya
+ clc
+ adc #16
+ lsr
+ lsr
+ lsr
+ sta Globals::zp_tmp2
+
+ ;; Let's first check if there's any match on the vertical axis.
+ ldx #0
+ @vertical_check:
+ lda Background::platforms, x
+
+ ;; End of the list, no matches: begone!
+ cmp #$FF
+ beq @end
+
+ ;; Prepare for either horizontal check (which require one 'inx') or the
+ ;; next iteration (which require three 'inx').
+ inx
+
+ ;; The first byte is the vertical tile coordinate. If that doesn't
+ ;; match, go for the next one.
+ cmp Globals::zp_tmp0
+ beq @horizontal_check
+ inx
+ inx
+ jmp @vertical_check
+
+ @horizontal_check:
+ ;; Save up this value just in case we are actually grounded.
+ sta Globals::zp_tmp3
+
+ ;; Check that the right corner of the player is to the right of the left
+ ;; edge of the platform.
+ lda Background::platforms, x
+ cmp Globals::zp_tmp2
+ bcs @end
+
+ ;; And now check that the left corner of the player is to the left of
+ ;; the right edge of the platform.
+ inx
+ lda Background::platforms, x
+ cmp Globals::zp_tmp1
+ bcc @end
+
+ ;; Hey, we have a collision! Are we grounded or fighting with a ceiling?
+ ldy zp_velocity_y
+ bmi @ceiling
+
+ ;; Translate the stored Y tile index into coordinates and account for
+ ;; the player's height. That's the final screen position.
+ lda Globals::zp_tmp3
+ asl
+ asl
+ asl
+ sec
+ sbc #PLAYER_HEIGHT
sta zp_screen_y
+
+ ;; Clearing out the subpixel value does the job.
lda #$F0
and zp_position_y
sta zp_position_y
+
+ ;; And reset the velocity on the Y axis as we are grounded.
+ lda #0
+ sta zp_velocity_y
+
rts
- ;; Nope, let's check for the platforms.
- @above_ground:
- ;; TODO: notice how ground and top are just cases on the general
- ;; "collision up/down". Next commits will merge these logics.
+ @ceiling:
+ ;; TODO
+ @end:
rts
.endproc