- Created detailed documentation for the Minecart sprite, outlining its properties, constants, collision setup, main logic, and design patterns. - Added documentation for the Pedestal sprite, including its vanilla overrides, custom logic for item interaction, and event triggering based on area context. - Introduced documentation for the Portal sprite, detailing its two-way warping system, initialization, main logic, and helper routines for seamless transitions. - Documented the Switch Track sprite, explaining its interactive behavior, state-based animation, and integration with external switches for dynamic track manipulation.
9.9 KiB
Portal Sprite
Overview
The Portal sprite (!SPRID = Sprite_Portal) implements a sophisticated two-way warping system within the game. It allows Link to instantly travel between designated Blue and Orange portals, which can be placed in both dungeons and the overworld. This sprite features complex logic for portal activation, collision detection with Link, and seamless management of Link's state during warps.
Sprite Properties
!SPRID:Sprite_Portal(Custom symbol, likely a remapped vanilla ID)!NbrTiles:01!Harmless:00!HVelocity:00!Health:00!Damage:00!DeathAnimation:00!ImperviousAll:00!SmallShadow:00!Shadow:00!Palette:00!Hitbox:00!Persist:01(Continues to live off-screen)!Statis:00!CollisionLayer:00!CanFall:00!DeflectArrow:00!WaterSprite:00!Blockable:00!Prize:00!Sound:00!Interaction:00!Statue:00!DeflectProjectiles:00!ImperviousArrow:00!ImpervSwordHammer:00!Boss:00
Main Structure (Sprite_Portal_Long)
This routine handles the Portal's drawing and dispatches to its main logic if the sprite is active.
Sprite_Portal_Long:
{
PHB : PHK : PLB
JSR Sprite_Portal_Draw
JSL Sprite_CheckActive : BCC .SpriteIsNotActive
JSR Sprite_Portal_Main
.SpriteIsNotActive
PLB
RTL
}
Initialization (Sprite_Portal_Prep)
This routine initializes the Portal upon spawning. It sets SprDefl, X to 0 (ensuring persistence outside the camera view), modifies SprHitbox, X properties, sets SprTileDie, X to 0, and makes the portal bulletproof (SprBulletproof, X to $FF).
Sprite_Portal_Prep:
{
PHB : PHK : PLB
; Persist outside of camera
LDA #$00 : STA.w SprDefl, X
LDA.w SprHitbox, X : AND.b #$C0 : STA.w SprHitbox, X
STZ.w SprTileDie, X
LDA.b #$FF : STA.w SprBulletproof, X
PLB
RTL
}
Portal Data Memory Locations
BluePortal_X,BluePortal_Y,OrangePortal_X,OrangePortal_Y: WRAM addresses storing the X and Y coordinates of the Blue and Orange portals, respectively.BlueActive,OrangeActive: Flags indicating whether the Blue and Orange portals are currently active.OrangeSpriteIndex,BlueSpriteIndex: Store the sprite indices of the Orange and Blue portals.
Main Logic & State Machine (Sprite_Portal_Main)
This routine manages the various states and behaviors of the portals, including their creation, activation, and warping functionality.
StateHandler: CallsCheckForDismissPortalandRejectOnTileCollision. It then checks$7E0FA6(likely a flag indicating which portal is being spawned). If$7E0FA6is0, it sets up an Orange Portal (stores coordinates, setsSprSubtype, Xto01, and transitions toOrangePortal). Otherwise, it sets up a Blue Portal (stores coordinates, setsSprSubtype, Xto02, and transitions toBluePortal).BluePortal/OrangePortal: Plays an animation. It checks if Link has been warped ($11compared to$2A). It then checks for overlap with Link's hitbox (CheckIfHitBoxesOverlap). If Link overlaps, it determines if Link is in a dungeon or overworld ($1B) and transitions to the appropriate warp state (BluePortal_WarpDungeon,OrangePortal_WarpDungeon,BluePortal_WarpOverworld,OrangePortal_WarpOverworld).BluePortal_WarpDungeon/OrangePortal_WarpDungeon: Warps Link's coordinates ($20,$22), sets camera scroll boundaries, stores the other portal's coordinates, sets itsSprTimerD, X, sets$11to$14, and returns to the respective portal state.BluePortal_WarpOverworld/OrangePortal_WarpOverworld: Warps Link's coordinates ($20,$22), sets camera scroll boundaries, applies Link's movement to the camera (JSL ApplyLinksMovementToCamera), stores the other portal's coordinates, sets itsSprTimerD, X, sets$5Dto$01, and returns to the respective portal state.
Sprite_Portal_Main:
{
LDA.w SprAction, X
JSL JumpTableLocal
dw StateHandler
dw BluePortal
dw OrangePortal
dw BluePortal_WarpDungeon
dw OrangePortal_WarpDungeon
dw BluePortal_WarpOverworld
dw OrangePortal_WarpOverworld
StateHandler:
{
JSR CheckForDismissPortal
JSR RejectOnTileCollision
LDA $7E0FA6 : BNE .BluePortal
LDA #$01 : STA $0307
TXA : STA.w OrangeSpriteIndex
LDA.w SprY, X : STA.w OrangePortal_X
LDA.w SprX, X : STA.w OrangePortal_Y
LDA.b #$01 : STA.w SprSubtype, X
%GotoAction(2)
RTS
.BluePortal
LDA #$02 : STA $0307
TXA : STA.w BlueSpriteIndex
LDA.w SprY, X : STA.w BluePortal_X
LDA.w SprX, X : STA.w BluePortal_Y
LDA.b #$02 : STA.w SprSubtype, X
%GotoAction(1)
RTS
}
BluePortal:
{
%StartOnFrame(0)
%PlayAnimation(0,1,8)
LDA $11 : CMP.b #$2A : BNE .not_warped_yet
STZ $11
.not_warped_yet
CLC
LDA.w SprTimerD, X : BNE .NoOverlap
JSL Link_SetupHitBox
JSL $0683EA ; Sprite_SetupHitbox_long
JSL CheckIfHitBoxesOverlap : BCC .NoOverlap
CLC
LDA $1B : BEQ .outdoors
%GotoAction(3) ; BluePortal_WarpDungeon
.NoOverlap
RTS
.outdoors
%GotoAction(5) ; BluePortal_WarpOverworld
RTS
}
OrangePortal:
{
%StartOnFrame(2)
%PlayAnimation(2,3,8)
LDA $11 : CMP.b #$2A : BNE .not_warped_yet
STZ $11
.not_warped_yet
CLC
LDA.w SprTimerD, X : BNE .NoOverlap
JSL Link_SetupHitBox
JSL $0683EA ; Sprite_SetupHitbox_long
JSL CheckIfHitBoxesOverlap : BCC .NoOverlap
CLC
; JSL $01FF28 ; Player_CacheStatePriorToHandler
LDA $1B : BEQ .outdoors
%GotoAction(4) ; OrangePortal_WarpDungeon
.NoOverlap
RTS
.outdoors
%GotoAction(6) ; OrangePortal_WarpOverworld
RTS
}
BluePortal_WarpDungeon:
{
LDA $7EC184 : STA $20
LDA $7EC186 : STA $22
LDA $7EC188 : STA $0600
LDA $7EC18A : STA $0604
LDA $7EC18C : STA $0608
LDA $7EC18E : STA $060C
PHX
LDA.w OrangeSpriteIndex : TAX
LDA #$40 : STA.w SprTimerD, X
LDA.w SprY, X : STA $7EC184
STA.w BluePortal_Y
LDA.w SprX, X : STA $7EC186
STA.w BluePortal_X
PLX
LDA #$14 : STA $11
%GotoAction(1) ; Return to BluePortal
RTS
}
OrangePortal_WarpDungeon:
{
LDA $7EC184 : STA $20
LDA $7EC186 : STA $22
; Camera Scroll Boundaries
LDA $7EC188 : STA $0600 ; Small Room North
LDA $7EC18A : STA $0604 ; Small Room South
LDA $7EC18C : STA $0608 ; Small Room West
LDA $7EC18E : STA $060C ; Small Room South
PHX
LDA.w BlueSpriteIndex : TAX
LDA #$40 : STA.w SprTimerD, X
LDA.w SprY, X : STA $7EC184
STA.w OrangePortal_Y
LDA.w SprX, X : STA $7EC186
STA.w OrangePortal_X
PLX
LDA #$14 : STA $11
%GotoAction(2) ; Return to OrangePortal
RTS
}
BluePortal_WarpOverworld:
{
LDA.w OrangePortal_X : STA $20
LDA.w OrangePortal_Y : STA $22
LDA $7EC190 : STA $0610
LDA $7EC192 : STA $0612
LDA $7EC194 : STA $0614
LDA $7EC196 : STA $0616
JSL ApplyLinksMovementToCamera
PHX ; Infinite loop prevention protocol
LDA.w OrangeSpriteIndex : TAX
LDA #$40 : STA.w SprTimerD, X
PLX
LDA #$01 : STA $5D
;LDA #$2A : STA $11
%GotoAction(1) ; Return to BluePortal
RTS
}
OrangePortal_WarpOverworld:
{
LDA.w BluePortal_X : STA $20
LDA.w BluePortal_Y : STA $22
LDA $7EC190 : STA $0610
LDA $7EC192 : STA $0612
LDA $7EC194 : STA $0614
LDA $7EC196 : STA $0616
JSL ApplyLinksMovementToCamera
PHX
LDA.w BlueSpriteIndex : TAX
LDA #$40 : STA.w SprTimerD, X
PLX
LDA #$01 : STA $5D
;LDA #$2A : STA $11
%GotoAction(2) ; Return to BluePortal
RTS
}
}
Helper Routines
CheckForDismissPortal: Checks a ticker ($06FE). If it exceeds02, it despawns the active portals (Blue and Orange) and decrements the ticker. Otherwise, it increments the ticker. This ticker needs to be reset during room and map transitions.RejectOnTileCollision: Checks for tile collision. If a portal is placed on an invalid tile (tile attribute0or48), it despawns the portal, plays an error sound (SFX2.3C), and decrements the ticker ($06FE).
Drawing (Sprite_Portal_Draw)
This routine handles OAM allocation and animation for the Portal. It explicitly uses REP #$20 and SEP #$20 for 16-bit coordinate calculations, ensuring accurate sprite rendering.
Design Patterns
- Two-Way Warping System: Implements a complex two-way portal system that allows Link to instantly travel between two designated points, enhancing exploration and puzzle design.
- Context-Sensitive Warping: Portals can intelligently warp Link between dungeons and the overworld, adapting to the current game context and providing seamless transitions.
- Persistent Portal Locations: Portal coordinates are stored in WRAM, allowing them to be placed and remembered across game sessions, enabling dynamic puzzle setups.
- Link State Management: Modifies Link's coordinates, camera boundaries, and game mode during warps, ensuring a smooth and consistent player experience during transitions.
- Collision Detection: Utilizes
CheckIfHitBoxesOverlapto accurately detect when Link enters a portal, triggering the warp sequence. - Error Handling: Includes logic to dismiss portals if they are placed on invalid tiles, preventing game-breaking scenarios and providing feedback to the player.
- 16-bit OAM Calculations: Demonstrates explicit use of
REP #$20andSEP #$20for precise 16-bit OAM coordinate calculations, crucial for accurate sprite rendering.