INCLUDE "oam.inc" SECTION "Collision", ROM0 DEF COLLF_WALK EQU (1 << 0) DEF COLLF_LADDER EQU (1 << 1) DEF COLLF_PORTAL EQU (1 << 2) ; Determines if player has hit the background ; @return NZ = false, Z = true player_bg_collides:: ; C = MAP X = PLAYER X / 8 + CAMERA X ld a, [PLAYER_X] call get_tile_coord ld c, a ld a, [CURRENT_CAMERA_X] add c ld c, a ; C < 0 ld a, c cpl bit 7, a ret z ; C >= MAP WIDTH ld a, [CURRENT_MAP_WIDTH] cp c jr nz, .load_y ret .load_y: ; B = MAP Y = PLAYER Y / 8 + CAMERA Y ld a, [PLAYER_Y] call get_tile_coord ld b, a ld a, [CURRENT_CAMERA_Y] add b ld b, a ; B < 0 ld a, b cpl bit 7, a ret z ; B >= MAP HEIGHT ld a, [CURRENT_MAP_HEIGHT] cp b jr nz, .check_tiles ; Set NZ or $ff ret .check_tiles: ; top left call can_move_to ret z ; top right inc c call can_move_to ret z ; bottom left dec c inc b call can_move_to ret z ; bottom right inc c call can_move_to ret ; Check if the player is in mid-air ; @note NZ = true, Z = false player_in_air:: ; c = x % 8 == 0 ? x/8 : x/8 + 1 ld a, [PLAYER_X] call get_tile_coord ld c, a ld a, [CURRENT_CAMERA_X] add c ld c, a ld a, [PLAYER_Y] call get_tile_coord ld b, a ld a, [CURRENT_CAMERA_Y] add b ld b, a ; check underneath player (2 tiles down from top-left sprite) inc b inc b call can_move_to ret z inc c call can_move_to ret ; Check whether the location can be moved to or not ; @param b y-coordinate ; @param c x-coordinate ; @destroy a, d, e ; @note NZ = true, Z = false can_move_to: push bc push hl ld a, [CURRENT_MAP_COLLISION] ld l, a ld a, [CURRENT_MAP_COLLISION + 1] ld h, a ld a, [CURRENT_MAP_WIDTH] ld d, 0 ld e, a ; compute map index (HL + B * (CURRENT_MAP_WIDTH + 1) + C) .mul_y_width: add hl, de dec b jr nz, .mul_y_width add hl, bc ld a, [hl] and COLLF_WALK pop hl pop bc ret ; Convert from pixel space to tile space ; @param a Screen pixel coordinate ; @destroys hl ; @returns Screen tile coordinate in A get_tile_coord: ld hl, sp - 1 ld [hl], a and %111 ld a, [hl] jr z, .skip_inc add 8 .skip_inc: srl a srl a srl a ret