- 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.
8.7 KiB
Village Dog / Eon Dog
Overview
The village_dog.asm file defines the behavior for two distinct dog NPCs: the "Village Dog" and the "Eon Dog." Their appearance and behavior are dynamically determined by the global WORLDFLAG. These dogs exhibit random movement, react to Link's proximity, can be lifted and thrown, and offer context-sensitive dialogue based on Link's current form.
Sprite Properties
!SPRID:Sprite_VillageDog(Custom symbol, likely a remapped vanilla ID)!NbrTiles:08!Harmless:01!HVelocity:00!Health:00!Damage:00!DeathAnimation:00!ImperviousAll:00!SmallShadow:00!Shadow:01!Palette:00!Hitbox:09!Persist:01(Continues to live off-screen)!Statis:00!CollisionLayer:01(Checks both layers for collision)!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_VillageDog_Long)
This routine acts as a dispatcher for drawing, selecting Sprite_VillageDog_Draw for the Village Dog (WORLDFLAG = 0) or Sprite_EonDog_Draw for the Eon Dog. It also handles shadow drawing and dispatches to the main logic if the sprite is active.
Sprite_VillageDog_Long:
{
PHB : PHK : PLB
LDA.w WORLDFLAG : BEQ .village
JSR Sprite_EonDog_Draw
JMP +
.village
JSR Sprite_VillageDog_Draw
+
JSL Sprite_DrawShadow
JSL Sprite_CheckActive : BCC .SpriteIsNotActive
JSR Sprite_VillageDog_Main
.SpriteIsNotActive
PLB
RTL
}
Initialization (Sprite_VillageDog_Prep)
This routine initializes the dog upon spawning. If it's an Eon Dog (WORLDFLAG is not 0), it sets SprAction, X to $07 and SprTimerA, X to $40.
Sprite_VillageDog_Prep:
{
PHB : PHK : PLB
LDA.w WORLDFLAG : BEQ .village
LDA.b #$07 : STA.w SprAction, X
LDA.b #$40 : STA.w SprTimerA, X
.village
PLB
RTL
}
HandleTossedDog
This routine manages the vertical movement of a dog that has been tossed. If SprHeight, X is not 0, it decrements it, simulating gravity.
LiftOrTalk
This routine determines whether Link can lift the dog or engage in dialogue. It checks Link's current form ($02B2). If Link is in Wolf or Minish form, it calls ShowMessageIfMinish. Otherwise, it checks if the dog is lifted (JSL Sprite_CheckIfLifted) and handles interactions with thrown sprites (JSL ThrownSprite_TileAndSpriteInteraction_long).
Main Logic & State Machine (Sprite_VillageDog_Main)
This routine manages the various states and behaviors of both Village Dogs and Eon Dogs.
Dog_Handler: Plays a sitting animation, callsHandleTossedDog, and if Link is nearby, sets a timer and transitions toDog_LookLeftAtLinkorDog_LookRightAtLink. It also callsLiftOrTalk.Dog_LookLeftAtLink/Dog_LookRightAtLink: Plays an animation of the dog looking towards Link. After a timer, it transitions toDog_MoveLeftTowardsLinkorDog_MoveRightTowardsLink.Dog_MoveLeftTowardsLink/Dog_MoveRightTowardsLink: Plays a walking animation, callsHandleTossedDog, and if Link is nearby, transitions toDog_WagTailLeftorDog_WagTailRight. It handles tile collisions, applies speed towards Link, and callsLiftOrTalk. After a timer, it returns toDog_Handler.Dog_WagTailLeft/Dog_WagTailRight: Plays a wagging tail animation, callsLiftOrTalkandHandleTossedDog. After a timer, it returns toDog_Handler.EonDog_Handler/EonDog_Right: These states are specific to the Eon Dog, playing animations and callingEonDog_Walk.
Sprite_VillageDog_Main:
{
LDA.w SprAction, X
JSL JumpTableLocal
dw Dog_Handler ; 00
dw Dog_LookLeftAtLink ; 01
dw Dog_LookRightAtLink ; 02
dw Dog_MoveLeftTowardsLink ; 03
dw Dog_MoveRightTowardsLink ; 04
dw Dog_WagTailLeft ; 05
dw Dog_WagTailRight ; 06
dw EonDog_Handler ; 07
dw EonDog_Right ; 08
; 0
Dog_Handler:
{
%PlayAnimation(8,8,8) ; Sitting
JSR HandleTossedDog
LDA $0309 : AND #$03 : BNE .lifting
LDA #$20 : STA.w SprTimerD, X
JSL Sprite_IsToRightOfPlayer : TYA : BEQ .walk_right
%GotoAction(1)
JMP .lifting
.walk_right
%GotoAction(2)
.lifting
JSR LiftOrTalk
JSL Sprite_Move
RTS
}
; 01
Dog_LookLeftAtLink:
{
%PlayAnimation(9,9,8)
JSR HandleTossedDog
LDA.w SprTimerD, X : BNE +
; Load the timer for the run
LDA.b #$60 : STA.w SprTimerD, X
%GotoAction(3)
+
RTS
}
; 02
Dog_LookRightAtLink:
{
%PlayAnimation(10,10,8)
JSR HandleTossedDog
LDA.w SprTimerD, X : BNE +
; Load the timer for the run
LDA.b #$60 : STA.w SprTimerD, X
%GotoAction(4)
+
RTS
}
; 03
Dog_MoveLeftTowardsLink:
{
%PlayAnimation(2,4,6)
JSR HandleTossedDog
; Check if the dog is near link, then wag the tail
JSR CheckIfPlayerIsNearby : BCC +
%GotoAction(5)
+
; Check for collision
JSL Sprite_CheckTileCollision
LDA $0E70, X : BEQ .no_collision
%GotoAction(0)
.no_collision
LDA.b #$0A
JSL Sprite_ApplySpeedTowardsPlayer
STZ $06 : STZ $07
JSL Sprite_MoveLong
JSR LiftOrTalk
LDA.w SprTimerD, X : BNE +
%GotoAction(0)
+
RTS
}
; 04
Dog_MoveRightTowardsLink:
{
%PlayAnimation(5,7,6)
JSR HandleTossedDog
JSR CheckIfPlayerIsNearby : BCC +
%GotoAction(6)
+
; Check for collision
JSL Sprite_CheckTileCollision
LDA $0E70, X : BEQ .no_collision
%GotoAction(0)
.no_collision
LDA.b #$0A
JSL Sprite_ApplySpeedTowardsPlayer
STZ $06 : STZ $07
JSL Sprite_MoveLong
JSR LiftOrTalk
LDA.w SprTimerD, X : BNE ++
%GotoAction(0)
++
RTS
}
; 05
Dog_WagTailLeft:
{
%PlayAnimation(0,1, 8)
JSR LiftOrTalk
JSR HandleTossedDog
LDA.w SprTimerD, X : BNE +
%GotoAction(0)
+
RTS
}
; 06
Dog_WagTailRight:
{
%PlayAnimation(11,12,8)
JSR LiftOrTalk
JSR HandleTossedDog
LDA.w SprTimerD, X : BNE +
%GotoAction(0)
+
RTS
}
EonDog_Handler:
{
%PlayAnimation(0,1,8)
JSR EonDog_Walk
RTS
}
EonDog_Right:
{
%PlayAnimation(2,3,8)
JSR EonDog_Walk
RTS
}
}
EonDog_Walk
This routine handles the Eon Dog's random movement. It moves the sprite (JSL Sprite_MoveLong), handles tile collision (JSL Sprite_BounceFromTileCollision), and after a timer, randomly selects a new direction and updates its speed and action.
CheckIfPlayerIsNearby
This routine checks if Link is within a specific rectangular area around the dog, returning with the carry flag set if true.
ShowMessageIfMinish
This routine displays a context-sensitive message based on Link's current form ($02B2). If Link is in Minish form, it displays message $18; otherwise, it displays message $1B.
Drawing (Sprite_VillageDog_Draw and Sprite_EonDog_Draw)
Both drawing routines handle OAM allocation and animation for their respective dog types. They explicitly use REP #$20 and SEP #$20 for 16-bit coordinate calculations. Each routine contains its own specific OAM data for rendering the character.
Design Patterns
- Multi-Character NPC (Conditional Drawing/Logic): A single sprite definition (
Sprite_VillageDog) is used to represent two distinct dog characters (Village Dog and Eon Dog) based onWORLDFLAG, showcasing efficient resource utilization and varied visual appearances. - Random Movement: The dogs exhibit random movement patterns, contributing to the environmental ambiance and making their movements less predictable.
- Player Interaction: The dogs can be lifted and thrown (
LiftOrTalk), and they react to Link's presence by looking at him and wagging their tails, adding to the interactive elements of the game world. - Conditional Dialogue: The
ShowMessageIfMinishroutine provides context-sensitive dialogue based on Link's current form, enhancing the narrative and player experience. - Player Collision: Implements
Sprite_PlayerCantPassThroughto make the dogs solid objects that Link cannot walk through. - 16-bit OAM Calculations: Demonstrates explicit use of
REP #$20andSEP #$20for precise 16-bit OAM coordinate calculations, crucial for accurate sprite rendering.