You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

320 lines
5.1 KiB

INCLUDE "hardware.inc"
INCLUDE "oam.inc"
INCLUDE "util.inc"
Section "Player Data", WRAM0
playerWorldX: dw
playerWorldY: dw
; player data
PLAYER_X:: db
PLAYER_Y:: dw
PLAYER_DIR:: db
PLAYER_JUMPING:: db
PLAYER_VY:: dw
Section "Player Code", ROM0
spriteData:
INCBIN "png/sprite/player.2bpp"
DEF SPRITE_OAM_IDX EQU 0
DEF SPRITE_IDX EQU 32 ; tile index, rename later
DEF SPRITE_WIDTH EQU 2
DEF SPRITE_HEIGHT EQU 2
DEF PLAYER_SPEED EQU 2
DEF TILE_WIDTH EQU 8 ; Width of tile in bytes
DEF TILE_HEIGHT EQU 8 ; Height of tile in bytes
DEF TILE_SIZE EQU 16 ; Total length of tile in bytes
DEF GRAVITY EQU (0 << 8) | $2e ; 0.18
DEF INIT_VY EQU (3 << 8) | $99 ; 3.60
DEF INIT_FALL_VY EQU ($ff << 8) | $1a ; a.b
Player_Init::
; Clear player data
ld hl, PLAYER_X
ld [hl], 0
inc hl
ld [hl], SCRN_Y - SPRITE_HEIGHT * (SCRN_Y - SPRITE_HEIGHT * TILE_HEIGHT)
inc hl
xor a
ld [hl+], a
ld [hl+], a
ld [hl+], a
ld [hl+], a
ld [hl+], a
; Copy sprite to VRAM
ld bc, _VRAM8000 + SPRITE_IDX * TILE_SIZE
ld hl, spriteData
ld d, TILE_SIZE * (SPRITE_WIDTH * SPRITE_HEIGHT)
call memcpy
; Initialize OAM entries with player state
call Player_UpdateOAM
ret
Player_Update::
; check for jump
ld a, [keys]
and PADF_UP
jr z, .jump_update_check
; initialize jump state if not already jumping
ld a, [PLAYER_JUMPING]
or a
jr nz, .jump_update
ld a, 1
ld [PLAYER_JUMPING], a
ld hl, PLAYER_VY
STORE16 INIT_VY
; todo: deduplicate
.jump_update_check:
ld a, [PLAYER_JUMPING]
or a
jr z, .right
.jump_update:
; load y velocity into bc
ld hl, PLAYER_VY
ld b, [hl]
inc hl
ld c, [hl]
; adjust velocity by gravity
ld a, c
sub LOW(GRAVITY)
ld c, a
ld a, b
sbc HIGH(GRAVITY)
ld b, a
ld hl, PLAYER_VY
STORE16 bc
; y -= floor(vy)
ld hl, PLAYER_Y + 1
ld a, [hl]
sub c
ld [hl-], a
ld a, [hl]
sbc b
ld [hl], a
; roll back jump if there was a collision
call player_bg_collides
jr z, .jump_Player_UpdateOAM
.jump_rollback:
ld hl, PLAYER_VY
bit 7, [hl]
ld hl, PLAYER_Y
jr z, .jump_rollback_down
dec [hl]
jr .jump_rollback_check
.jump_rollback_down:
inc [hl]
.jump_rollback_check:
call player_bg_collides
jr nz, .jump_rollback
; set PLAYER_JUMPING = 0 if VY < 0 (fell into ground)
ld hl, PLAYER_VY
bit 7, [hl]
; either way, set VY = 0.
; NOTE: MUST USE LD HERE TO KEEP FLAGS FROM BIT TEST
ld [hl], 0
ld hl, PLAYER_VY + 1
ld [hl], 0
jr z, .jump_Player_UpdateOAM
xor a
ld [PLAYER_JUMPING], a
.jump_Player_UpdateOAM:
call Player_UpdateOAM
; check for move right
.right:
ld a, [keys]
and PADF_RIGHT
jr z, .left
; check for right boundary
ld a, [PLAYER_X]
add 16
cp SCRN_X
jr nc, .left
.move_right:
ld hl, PLAYER_X
inc [hl]
inc [hl]
call player_bg_collides
jr nz, .right_rollback
xor a
ld [PLAYER_DIR], a
call Player_UpdateOAM
ret
.right_rollback:
ld hl, PLAYER_X
dec [hl]
dec [hl]
ret
.left:
; check for left button
ld hl, keys
ld a, [hl]
and PADF_LEFT
jr z, .fall
; check for left boundary
ld a, [PLAYER_X]
or a
jr z, .fall
sub PLAYER_SPEED
ld [PLAYER_X], a
call player_bg_collides
jr nz, .left_rollback
ld a, $ff
ld [PLAYER_DIR], a
call Player_UpdateOAM
jr .fall
.left_rollback:
ld hl, PLAYER_X
inc [hl]
inc [hl]
.fall:
call player_in_air
ret nz
; only set jump state if not already jumping
ld hl, PLAYER_JUMPING
ld a, [hl]
or a
ret nz
ld [hl], 1
ld hl, PLAYER_VY
STORE16 INIT_FALL_VY
ret
; Update player metasprite with positional data
Player_UpdateOAM::
ld hl, PLAYER_DIR
ld a, [hl-] ; dir (0 = right , $ff = left)
and OAMF_XFLIP
ld c, a
dec hl ; skip fractional part
ld a, [hl-] ; y
add 16
ld d, a
ld a, [hl] ; x
add 8
ld b, a
ld a, d
ld_OAM_y hl, SPRITE_OAM_IDX
; top left sprite
ld [hli], a
ld [hl], b
inc hl
ld [hl], SPRITE_IDX
inc hl
ld [hl], c
inc hl
; top right
ld d, a
ld a, b
add 8
ld b, a
ld a, d
ld [hli], a
ld [hl], b
inc hl
ld [hl], SPRITE_IDX + 1
inc hl
ld [hl], c
inc hl
; bottom left
add 8
ld d, a
ld a, b
sub 8
ld b, a
ld a, d
ld [hli], a
ld [hl], b
inc hl
ld [hl], SPRITE_IDX + 2
inc hl
ld [hl], c
inc hl
; bottom right
ld d, a
ld a, b
add 8
ld b, a
ld a, d
ld [hli], a
ld [hl], b
inc hl
ld [hl], SPRITE_IDX + 3
inc hl
ld [hl], c
; flip tile indices if necessary
ld a, c
or c
jr z, .done
; TODO: Can be sped up by using LD A, [NN]
ld_OAM_tile hl, SPRITE_OAM_IDX
ld [hl], SPRITE_IDX + 1
ld_OAM_tile hl, SPRITE_OAM_IDX + 1
ld [hl], SPRITE_IDX
ld_OAM_tile hl, SPRITE_OAM_IDX + 2
ld [hl], SPRITE_IDX + 3
ld_OAM_tile hl, SPRITE_OAM_IDX + 3
ld [hl], SPRITE_IDX + 2
.done:
ret