Implement View Map mode [commit 4]: draw arrows OAM and refactor previous commit to support this (#29)

This commit is contained in:
xCrystal 2023-11-04 13:04:25 +01:00
parent c2e7422ba0
commit 8f3e9b04e2
11 changed files with 194 additions and 50 deletions

View File

@ -187,7 +187,11 @@ DEF BOARD_MENU_BG_FIRST_TILE EQU "A"
; Object tile locations (vTiles0)
DEF SECONDARY_SPRITES_FIRST_TILE EQU $20
DEF BOARD_MENU_OAM_FIRST_TILE EQU SECONDARY_SPRITES_FIRST_TILE
DEF DIE_ROLL_OAM_FIRST_TILE EQU BOARD_MENU_OAM_FIRST_TILE + 45 ; max(BOARD_MENU_ITEM_SIZE * NUM_BOARD_MENU_ITEMS, DIE_SIZE * 10)
DEF DIE_NUMBERS_OAM_FIRST_TILE EQU BOARD_MENU_OAM_FIRST_TILE
DEF BRANCH_ARROWS_OAM_FIRST_TILE EQU DIE_NUMBERS_OAM_FIRST_TILE + 40 ; DIE_NUMBER_SIZE * 10
DEF VIEW_MAP_MODE_OAM_FIRST_TILE EQU SECONDARY_SPRITES_FIRST_TILE

View File

@ -12,6 +12,7 @@ DEF AUTO_INPUT EQU $ff
const SECONDARYSPRITES_DIE_ROLL_F ; 1
const SECONDARYSPRITES_SPACES_LEFT_F ; 2
const SECONDARYSPRITES_BRANCH_ARROWS_F ; 3
const SECONDARYSPRITES_VIEW_MAP_MODE_F ; 4
; wCurDexMode::
const_def

View File

@ -120,3 +120,10 @@ BranchArrowsOAM:
dbsprite 7, 10, 4, 0, BRANCH_ARROWS_OAM_FIRST_TILE + 1, PAL_OW_RED ; left
dbsprite 9, 8, 4, 0, BRANCH_ARROWS_OAM_FIRST_TILE + 2, PAL_OW_RED ; up
dbsprite 9, 12, 4, 0, BRANCH_ARROWS_OAM_FIRST_TILE + 3, PAL_OW_RED ; down
ViewMapModeArrowsOAM:
; the PAL_ argument is unused (actual palette comes from the player gender)
dbsprite 10, 18, 4, 4, VIEW_MAP_MODE_OAM_FIRST_TILE + 3, PAL_OW_RED ; down
dbsprite 10, 2, 4, 4, VIEW_MAP_MODE_OAM_FIRST_TILE + 2, PAL_OW_RED ; up
dbsprite 1, 10, 4, 0, VIEW_MAP_MODE_OAM_FIRST_TILE + 1, PAL_OW_RED ; left
dbsprite 19, 10, 4, 0, VIEW_MAP_MODE_OAM_FIRST_TILE, PAL_OW_RED ; right

View File

@ -77,6 +77,7 @@ BoardMenuScript::
callasm .EnterViewMapMode
appearplayermock
closetext
callasm .ViewMapModeOAM
end
.EnterViewMapMode:
@ -102,6 +103,13 @@ BoardMenuScript::
set INVISIBLE_F, [hl]
ret
.ViewMapModeOAM:
; this runs after closetext to prevent graphical glitches with the board menu OAM
farcall LoadViewMapModeGFX
ld hl, wDisplaySecondarySprites
set SECONDARYSPRITES_VIEW_MAP_MODE_F, [hl]
ret
.SubmenuCallback:
; if submenu has requested a callback through wMenuReturn,
; it has also taken care of queuing it into wQueuedScriptBank/wQueuedScriptAddr.

View File

@ -48,3 +48,13 @@ LoadBranchArrowsGFX::
.BranchArrowsOAMGFX:
INCBIN "gfx/board/branch_arrows.2bpp"
LoadViewMapModeGFX::
ld de, .ViewMapModeArrowsOAMGFX
ld hl, vTiles0 + VIEW_MAP_MODE_OAM_FIRST_TILE * LEN_2BPP_TILE
lb bc, BANK(.ViewMapModeArrowsOAMGFX), NUM_DIRECTIONS
call Get2bppViaHDMA
ret
.ViewMapModeArrowsOAMGFX:
INCBIN "gfx/board/view_map_arrows.2bpp"

View File

@ -3114,6 +3114,8 @@ InitSecondarySprites:
call nz, InitSpacesLeftNumberSprites
bit SECONDARYSPRITES_BRANCH_ARROWS_F, a
call nz, InitBranchArrowsSprites
bit SECONDARYSPRITES_VIEW_MAP_MODE_F, a
call nz, InitViewMapModeSprites
ret
InitBoardMenuSprites:
@ -3254,4 +3256,59 @@ InitBranchArrowsSprites:
pop af
ret
InitViewMapModeSprites:
push af
; find the beginning of free space in OAM, and assure there's space for 4 objects
ldh a, [hUsedSpriteIndex]
cp (NUM_SPRITE_OAM_STRUCTS * SPRITEOAMSTRUCT_LENGTH) - (NUM_DIRECTIONS * SPRITEOAMSTRUCT_LENGTH) + 1
jr nc, .oam_full
ld hl, ViewMapModeArrowsOAM
ld de, wTileDown
ld c, NUM_DIRECTIONS
.loop
ld a, [de]
cp $ff
jr z, .next1 ; skip this arrow if this direction is not valid
gender_to_pal
ld b, a
; draw this arrow and advance hUsedSpriteIndex
; preserve loop variables d, e, c
push de
push bc
ldh a, [hUsedSpriteIndex]
ld e, a
ld d, HIGH(wShadowOAM)
; copy all bytes minus the attributes one.
; the palette matches the player's color palette.
push bc
ld bc, SPRITEOAMSTRUCT_LENGTH - 1
call CopyBytes
pop bc
ld a, b ; palette
ld [de], a
inc de
ld a, e
ldh [hUsedSpriteIndex], a
pop bc
pop de
jr .next2
.next1
inc hl ;
inc hl ;
inc hl ;
.next2
inc hl ; next object in ViewMapModeArrowsOAM
inc de
dec c
jr nz, .loop
.oam_full
pop af
ret
INCLUDE "data/sprites/secondary_sprites.asm"

View File

@ -133,80 +133,96 @@ DoPlayerMovement::
.ViewMapMode:
; if View Map mode, ignore regular collisions but account for going off-limits or off-range
call .GetAction
call .CheckViewMapModeCollision
call .ViewMapMode_CheckCollision
; perform a normal step (Stand in place if wWalkingDirection is STANDING)
ld a, STEP_WALK
call .DoStep
scf
ret
.CheckViewMapModeCollision:
.ViewMapMode_CheckCollision:
; return STANDING into wWalkingDirection if trying to walk
; off-limits (unless there is a connected map) or off-range
ld a, [wWalkingDirection]
; as wTileDown, wTileUp, wTileLeft, and wTileRight are not used in this mode,
; they are borrowed in order to signal valid directions to InitSecondarySprites
xor a
ld hl, wTileDown
ld [hli], a
ld [hli], a ; wTileUp
ld [hli], a ; wTileLeft
ld [hl], a ; wTileRight
ld hl, wYCoord
ld de, wMapHeight
ld bc, wSouthConnectedMapGroup
cp DOWN
jr z, .next1
; ld hl, wYCoord
ld a, DOWN
call .ViewMapMode_CheckDirectionOffLimits
ld hl, wYCoord
ld de, .TopLimit
ld bc, wNorthConnectedMapGroup
cp UP
jr z, .next1
ld a, UP
call .ViewMapMode_CheckDirectionOffLimits
ld hl, wXCoord
ld de, wMapWidth
ld bc, wEastConnectedMapGroup
cp RIGHT
jr z, .next1
; ld hl, wXCoord
ld a, RIGHT
call .ViewMapMode_CheckDirectionOffLimits
ld hl, wXCoord
ld de, .LeftLimit
ld bc, wWestConnectedMapGroup
cp LEFT
jr z, .next1
ret ; wWalkingDirection is already STANDING
ld a, LEFT
call .ViewMapMode_CheckDirectionOffLimits
; check if walking off-limits
; now check in which directions the player would be walking off-range
ld hl, wViewMapModeRange
ld de, wViewMapModeDisplacementY
ld bc, wTileDown
ld a, [de]
cp [hl]
jr nz, .next1
ld a, $ff
ld [bc], a
.next1
ld a, [bc] ; connected map group
inc a
jr nz, .next2 ; it's ok if there's any connected map in this direction
ld a, [de] ; map dimension size (in metatiles), or 0 if moving up/left
add a
and a
jr z, .ok
dec a ; if e.g. size is 0x10, limit is at coord=0x1f
.ok
cp [hl] ; player coord (in half-metatiles)
jr z, .already_in_limit
.next2
; not walking off-limits; check if walking off-range
ld hl, wViewMapModeDisplacementY
ld a, [wWalkingDirection]
cp DOWN
jr z, .next3
cp UP
jr z, .next3
ld hl, wViewMapModeDisplacementX
.next3
ld c, [hl]
cp DOWN
jr z, .next4
cp RIGHT
jr z, .next4
; if UP or LEFT, the displacement to check is negative
ld a, c
inc bc ; wTileUp
ld a, [de]
xor $ff
inc a
ld c, a
cp [hl]
jr nz, .next2
ld a, $ff
ld [bc], a
.next2
ld de, wViewMapModeDisplacementX
inc bc ; wTileLeft
ld a, [de]
xor $ff
inc a
cp [hl]
jr nz, .next3
ld a, $ff
ld [bc], a
.next3
inc bc ; wTileRight
ld a, [de]
cp [hl]
jr nz, .next4
ld a, $ff
ld [bc], a
.next4
ld a, [wViewMapModeRange]
cp c
ret nz
; fallthrough
.already_in_limit
; finally return STANDING into wWalkingDirection in the current direction at
; wWalkingDirection has had its corresponding wTile* address set to $ff.
ld a, [wWalkingDirection]
cp STANDING
ret z
ld hl, wTileDown
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
inc a ; cp $ff
ret nz
ld a, STANDING
ld [wWalkingDirection], a
ret
@ -215,6 +231,36 @@ DoPlayerMovement::
.LeftLimit:
db 0
; check if player would be walking off-limits in this direction
.ViewMapMode_CheckDirectionOffLimits:
push af
ld a, [bc] ; connected map group
inc a
jr nz, .valid ; it's ok if there's any connected map in this direction
ld a, [de] ; map dimension size (in metatiles), or 0 if moving up/left
add a
and a
jr z, .ok
dec a ; if e.g. size is 0x10, limit is at coord=0x1f
.ok
cp [hl] ; player coord (in half-metatiles)
jr nz, .valid
; not valid: set wTile* to $ff
pop af
ld hl, wTileDown
ld c, a
ld b, 0
add hl, bc
ld [hl], $ff
ret
.valid
pop af
ret
.CheckTile:
; Tiles such as waterfalls and warps move the player
; in a given direction, overriding input.

View File

@ -1277,6 +1277,8 @@ Script_reloadmapafterviewmapmode:
ld [wDefaultSpawnpoint], a
ld a, BOARDEVENT_REDISPLAY_MENU
ldh [hCurBoardEvent], a
ld hl, wDisplaySecondarySprites
res SECONDARYSPRITES_VIEW_MAP_MODE_F, [hl]
ld a, MAPSTATUS_ENTER
call LoadMapStatus
ld hl, wPlayerFlags

BIN
gfx/board/view_map_arrows.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 B

View File

@ -1515,6 +1515,12 @@ SaveScreen_LoadConnection::
ret
GetMovementPermissions::
; permissions are ignored in View Map mode
; collisions are handled differently in View Map mode
ld a, [hCurBoardEvent]
cp BOARDEVENT_VIEW_MAP_MODE
ret z
xor a
ld [wTilePermissions], a
call .LeftRight

View File

@ -171,6 +171,9 @@ wTileDown:: db
wTileUp:: db
wTileLeft:: db
wTileRight:: db
assert wTileUp - wTileDown == UP
assert wTileLeft - wTileDown == LEFT
assert wTileRight - wTileDown == RIGHT
wTilePermissions::
; set if tile behavior prevents