- ; applies gravity to an actor
- ; sets act_direction to DOWN
- ; inputs:
- ; de: actor
- ; returns:
- ; a: != 0 no gravity
- ; a: 0 gravity
-act_apply_gravity:
- ld a, [col_direction]
- and a, DIRUP
- ret nz
-
- ld a, [col_direction]
- or a, DIRDOWN
- ld [col_direction], a
-
- ld hl, act_pos_y
- add hl, de
- ld a, [hl]
- inc a
- ld [hl], a
-
- xor a, a
- ret
-
- ; stores current position in col_prev_pos
- ; inputs:
- ; de: actor
-act_backup_pos:
- ld hl, act_pos_y
- add hl, de
- ld a, [hl+]
- ld [col_prev_pos], a ; y
-
- ld a, [hl]
- ld [col_prev_pos+1], a ; x
- ret
-
- ; restores prev x pos
- ; inputs:
- ; de: actor
-act_rollback_pos_x:
- ld hl, act_pos_x
- add hl, de
- ld a, [col_prev_pos+1]
- ld [hl], a
- ret
-
- ; restores prev y pos
- ; inputs:
- ; de: actor
-act_rollback_pos_y:
- ld hl, act_pos_y
- add hl, de
- ld a, [col_prev_pos]
- ld [hl], a
- ret
-
- ; test collision based on an actor
- ; and a direction
- ; inputs:
- ; de: actor
- ; col_point_xx: collision points
- ; col_direction: set to direction moved in
- ; col_prev_pos: set to previous positions
- ; if collision occures rolls back to
- ; previous position
- ; retuns:
- ; col_tile_collided_with: directions collided with
-act_test_tile_collision:
- xor a, a
- ld [col_tile_collided_with], a
-
- push af
- ld a, [col_direction]
- and a, DIRUP
- call nz, _act_test_tile_up_collision
- pop bc
- or a, b
- push af
-
- ld a, [col_direction]
- and a, DIRDOWN
- call nz, _act_test_tile_down_collision
- pop bc
- or a, b
- push af
-
- ld a, [col_direction]
- and a, DIRLEFT
- call nz, _act_test_tile_left_collision
- pop bc
- or a, b
- push af
-
- ld a, [col_direction]
- and a, DIRRIGHT
- call nz, _act_test_tile_right_collision
- pop bc
- or a, b
-
- ld [col_tile_collided_with], a
-
- ret
-
- ; loads a collision point into bc
- ; point must be in hram
- ; inputs:
- ; $1: point name
- ; returns:
- ; b/c: y/x tile position
-#macro _act_col_load_pt
- ldh a, [$1]
- ld b, a
- ldh a, [$1+1]
- ld c, a
-#endmacro
-
- ; checks collision
- ; inputs:
- ; $1: point to check
- ; $2: y offset
- ; $3: x offset
- ; $4: label to jump to (jr)
-#macro _act_tile_col_check
- _act_col_load_pt $1
- ld a, b
- add a, $2
- ld b, a
-
- ld a, c
- add a, $3
- ld c, a
- div8 b
- div8 c
-
- call map_get_tile
- ld de, t_flags
- add hl, de
- ld a, [hl]
- and a, TF_WALL
- jr nz, $4 REL
-#endmacro
-
- ; test direction routines:
- ; preserve: de
- ; retunrs:
- ; a: collided direction bit
- ; a: 0 no collision
-_act_test_tile_left_collision:
- push de
-
- ; top left point
- _act_tile_col_check col_point_tl, (1 & 0xFF), 0, @collision
-
- ; bottom left point
- _act_tile_col_check col_point_bl, (-1 & 0xFF), 0, @collision
-
- ; center left point
- _act_tile_col_check col_point_lc, (-1 & 0xFF), 0, @collision
-
- pop de
- xor a, a
- ret
-@collision:
- pop de
- call act_rollback_pos_x
- ld a, DIRLEFT
- ret
-
-_act_test_tile_right_collision:
- push de
-
- ; top right point
- _act_tile_col_check col_point_tr, (1 & 0xFF), 0, @collision
-
- ; bottom right point
- _act_tile_col_check col_point_br, (-1 & 0xFF), 0, @collision
-
- ; center right point
- _act_tile_col_check col_point_rc, (-1 & 0xFF), 0, @collision
-
- pop de
- xor a, a
- ret
-@collision:
- pop de
- call act_rollback_pos_x
- ld a, DIRRIGHT
- ret
-
-_act_test_tile_up_collision:
- push de
-
- ; top left point
- _act_tile_col_check col_point_tl, 0, (1 & 0xFF), @collision
-
- ; top right point
- _act_tile_col_check col_point_tr, 0, (-1 & 0xFF), @collision
-
- ; top center point
- _act_tile_col_check col_point_tc, 0, (-1 & 0xFF), @collision
-
- pop de
- xor a, a
- ret
-@collision:
- pop de
- call act_rollback_pos_y
- ld a, DIRUP
- ret
-
-_act_test_tile_down_collision:
- push de
-
- ; bottom left point
- _act_tile_col_check col_point_bl, 0, (1 & 0xFF), @collision
-
- ; bottom rihgt point
- _act_tile_col_check col_point_br, 0, (-1 & 0xFF), @collision
-
- ; bottom center point
- _act_tile_col_check col_point_bc, 0, (-1 & 0xFF), @collision
-
- pop de
- xor a, a
- ret
-@collision:
- pop de
- call act_rollback_pos_y
- ld a, DIRDOWN
- ret
-
- ; update routines for each actor
-act_map_update_table:
-
- ; draw routine for each actor
-act_map_draw_table:
-
-
-
; updates and draws an actor
; calls different routines fro combat and map state
; inputs:
-
-#define DEBUG_COLLISION_MARKER 0x9E
-
- ; draws a point in debug mode
- ; inputs:
- ; $1: point ptr name
- ; hl: oam ptr
- ; returns:
- ; hl: next oam
-#macro debug_draw_point
- ; y pos
- ld a, [scroll_y]
- ld b, a
- ld a, [$1] ; y
-
- add a, OBJ_OFF_Y
- sub a, b
- ld [hl+], a
-
- ; x pos
- ld a, [scroll_x]
- ld b, a
- ld a, [$1+1] ; x
-
- add a, OBJ_OFF_X
- sub a, b
- ld [hl+], a
-
- ; tile
- ld a, DEBUG_COLLISION_MARKER
- ld [hl+], a
-
- ; flags
- xor a, a
- ld [hl+], a
-#endmacro
-
- ; draws col_point_nn
- ; using the debug sprite
- ; if enabled
-debug_draw_collision:
- ld a, 9
- call oamalloc
-
- ; draw each point
- debug_draw_point col_point_tl
- debug_draw_point col_point_bl
- debug_draw_point col_point_tr
- debug_draw_point col_point_br
- debug_draw_point col_point_ct
-
- debug_draw_point col_point_tc
- debug_draw_point col_point_bc
- debug_draw_point col_point_lc
- debug_draw_point col_point_rc
-
- ret
.de map_routine, 2
; ptr to actor table for this map
.de map_acts, 2
- ; ptr to exit table
- ; in the following order: up, down, left, right
-.de map_exits, 2
; pointers to tile banks to be loaded
; maps to map property tile_bank0, tile_bank1, tile_bank2, tile_bank3
; note that tile_bank1 and tile_bank2 are 128 bytes each
; 0x80 - 0x90 are used by dma routines
.org 0xFF90
-
- ; corner points
- ; used for actor -> actor center collision
- ; should form a rectangle
- ; also used for tile collision
- ;
- ; top left, top right
- ; bottom left, bottom right
-col_point_tl: .adv 2
-col_point_tr: .adv 2
-col_point_bl: .adv 2
-col_point_br: .adv 2
-
- ; mid points
- ; top, bottom, left, right center
- ; used for tile collision
-col_point_tc: .adv 2
-col_point_bc: .adv 2
-col_point_lc: .adv 2
-col_point_rc: .adv 2
-
- ; center point of the actor
- ; this is used to check for actor -> actor collision
-col_point_ct: .adv 2
-
-
- ; direction the movement is happening
- ; in. this is required so that the collision code
- ; can handle pushbacks in case of wall collision
-col_direction: .adv 2
- ; holds tile collision direction result
-col_tile_collided_with: .adv 1
-
- ; y/x previous position
-col_prev_pos: .adv 2
; where each tile has values and its current state. The map can be drawn from this.
l1:
- mapdef MAP_F_DO_FULL_REDRAW, map_r_nop, 0, l1_exits, tile_banks_default, tile_id_table
+ mapdef MAP_F_DO_FULL_REDRAW, map_r_nop, 0, tile_banks_default, tile_id_table
#include "spawn.inc"
tile_banks_default:
dw bank8C00
dw bank9000
-l1_exits:
- dw l1
- dw l1
- dw l1
- dw l1
-
-l2:
- mapdef 0, map_r_nop, 0, l1_exits, tile_banks_default, tile_id_table
-#include "spawn.inc"
; $1: flags
; $2: map routine
; $3: actors
- ; $4: exits
- ; $5: tile bank table
- ; $6: tile id table
+ ; $4: tile bank table
+ ; $5: tile id table
#macro mapdef
.db $1
dw $2
dw $3
dw $4
dw $5
- dw $6
#endmacro
; define a tile
push de
call map_tiles_load
pop de
-
- ; exit table
- ld hl, map_exits
- add hl, de
- ld a, [hl+]
- ld h, [hl]
- ld l, a
; load exits in the following order:
; up, down, left, right
ret
- ; checks the current map
- ; if the fully reload flag is set
- ; it will do a full redraw
- ; otherwise this routine just returns
- ; if a full redraw is requested this routine
- ; pops the previous caller's return from the stack
- ; and jumps to a full load
- ; inputs:
- ; de: new map ptr
-map_try_full_reload:
- ld a, [de] ; read flags
- and a, MAP_F_DO_FULL_REDRAW
- ret z
-
- pop hl ; remove previous caller from call stack
- jp map_load
-
- ; map transition routines
- ; gets the down exit and sets transition state
-map_get_exit_down_and_set_load:
- ; fix player position
- ld hl, player+act_pos_y
- xor a, a
- ld [hl], a
-
- ld hl, map_exit_down
- ld a, [hl+]
- ld d, [hl]
- ld e, a ; de = new map
-
- ; this call does not return
- ; if a full load is needed
- call map_try_full_reload
-
- ld hl, update_map_load_down
- call game_set_state
- ret
-
; nop map rotuine
map_r_nop:
ret
#define PLAYER_CURSOR_L 0x88
#define PLAYER_CURSOR_R 0x8A
-#define PLAYER_JUMP_MAX 32
-
; sets up the player actor
player_init:
ld a, 0x5A
ret
- ; writes collision points for player
- ; inputs:
- ; de: actor
-player_col_write_points:
- ld hl, act_pos_y
- add hl, de
-
- ld a, [hl+]
- ld b, a ; b = y
- ld a, [hl]
- ld c, a ; c = x
-
- ; top left point
- ld a, b
- add a, 2
- ldh [col_point_tl], a
- ld a, c
- add a, 2
- ldh [col_point_tl+1], a
-
- ; top right point
- ld a, b
- add a, 2
- ldh [col_point_tr], a
-
- ld a, c
- add a, 12
- ldh [col_point_tr+1], a
-
- ; bottom left point
- ld a, b
- add a, 14
- ldh [col_point_bl], a
- ld a, c
- add a, 2
- ldh [col_point_bl+1], a
-
- ; bottom right points
- ld a, b
- add a, 14
- ldh [col_point_br], a
- ld a, c
- add a, 12
- ldh [col_point_br+1], a
-
- ; center point
- ld a, b
- add a, 8
- ldh [col_point_ct], a
- ld a, c
- add a, 7
- ldh [col_point_ct+1], a
-
- ; top center point
- ld a, b
- add a, 2
- ldh [col_point_tc], a
- ld a, c
- add a, 7
- ldh [col_point_tc+1], a
-
- ; bottom center point
- ld a, b
- add a, 14
- ldh [col_point_bc], a
- ld a, c
- add a, 7
- ldh [col_point_bc+1], a
-
- ; left center point
- ld a, b
- add a, 8
- ldh [col_point_lc], a
- ld a, c
- add a, 2
- ldh [col_point_lc+1], a
-
- ; right center point
- ld a, b
- add a, 8
- ldh [col_point_rc], a
- ld a, c
- add a, 12
- ldh [col_point_rc+1], a
-
- ret
; updates the special player actor
player_update:
ld de, player
- ; call scroll_center_player
- call act_backup_pos
- call player_col_write_points
-
- push de
call player_handle_move
- pop de
- push de
- call act_apply_gravity
- cp a, 0
- jr nz, @no_gravity REL
- ld a, 1
- ld [player_jump_peak], a
-@no_gravity:
-
- pop de
- call act_test_tile_collision
-
- ; check if jump timer is > max
- ld a, [player_jump_timer]
- cp a, PLAYER_JUMP_MAX
- jr nc, @stop_jump REL
-
- ; check if collided with ceiling
- ld a, [col_tile_collided_with]
- and a, DIRUP
- jr z, @not_up_collision REL
-@stop_jump:
- ld a, 1
- ld [player_jump_peak], a
-@not_up_collision:
-
- ; check if touching floor
- ld a, [col_tile_collided_with]
- and a, DIRDOWN
- jr z, @not_down_collision REL
- ; wait for input button to be cleared before grounding player
- ld a, [curr_inputs]
- and a, BTNA
- jr nz, @not_down_collision REL
-
- xor a, a
- ld [player_jump_peak], a
- ld [player_jump_timer], a
-@not_down_collision:
-
- call player_check_map_transition_trigger
ret
; moves the player
; does not move out of bounds
; based on the last queued input
player_handle_move:
- xor a, a
- ld [col_direction], a
-
- ld b, BTNA
- input_held
- jr z, @not_up REL
- ld a, [player_jump_peak]
- cp a, 0
- jr nz, @not_up REL
-
- ld a, [player_jump_timer]
- inc a
- ld [player_jump_timer], a
-
- ld a, [player+act_pos_y]
- cp a, 0 ; min value
- jr z, @not_up REL
- dec a
- ld [player+act_pos_y], a
-
- ld a, [col_direction]
- or a, DIRUP
- ld [col_direction], a
-@not_up:
-
- ld b, BTNLEFT
- input_held
- jr z, @not_left REL
- ld a, [player+act_pos_x]
- cp a, 0 ; min value
- jr z, @not_left REL
- dec a
- ld [player+act_pos_x], a
-
- ld a, [col_direction]
- or a, DIRLEFT
- ld [col_direction], a
-@not_left:
-
- ld b, BTNRIGHT
- input_held
- jr z, @not_right REL
- ld a, [player+act_pos_x]
- cp a, 0x90 ; max value
- jr z, @not_right REL
- inc a
- ld [player+act_pos_x], a
-
- ld a, [col_direction]
- or a, DIRRIGHT
- ld [col_direction], a
-@not_right:
- ret
-
- ; tests player position to
- ; see if a map transiton point was hit
- ; if the position is too far off-screen
- ; it will initiate a map transition
-player_check_map_transition_trigger:
- ; check down
- ld a, [player+act_pos_y]
- cp a, 0x80 ; max y value
- call nc, map_get_exit_down_and_set_load
-
ret
; draws player at current location
call ui_update
-#ifdef DEBUG_COLLISION
- call debug_draw_collision
-#endif
-
-
; TODO: update map routine
ret
- ; game state
- ; for loading a map down
-update_map_load_down:
- ret
-
new_game:
ld de, l1
call map_load