Add new sprite documentation for Minecart, Pedestal, Portal, and Switch Track
- 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.
This commit is contained in:
242
Docs/Sprites/Enemies/Leever.md
Normal file
242
Docs/Sprites/Enemies/Leever.md
Normal file
@@ -0,0 +1,242 @@
|
||||
# Leever
|
||||
|
||||
## Overview
|
||||
The Leever sprite is a custom implementation that overrides the vanilla Leever behavior (`Sprite_71_Leever`). It features distinct states for being underground, emerging, attacking, and digging back down, with randomized timers controlling its transitions.
|
||||
|
||||
## Vanilla Override
|
||||
This custom Leever implementation hooks into the vanilla sprite ID $71. It uses a custom flag at `$0FFF` to determine whether to execute its custom logic (`Sprite_Leever_Long`) or fall back to the original vanilla Leever behavior (`Sprite_71_Leever`).
|
||||
|
||||
```asm
|
||||
pushpc
|
||||
|
||||
Sprite_71_Leever = $06CBA2
|
||||
|
||||
org $069365 : dw Sprite_71_Leever_Alt
|
||||
|
||||
Sprite_71_Leever_Alt:
|
||||
{
|
||||
LDA.w $0FFF : BEQ +
|
||||
JSL Sprite_Leever_Long
|
||||
JMP ++
|
||||
+
|
||||
JSR Sprite_71_Leever
|
||||
++
|
||||
RTS
|
||||
}
|
||||
assert pc() <= $06A5C0
|
||||
|
||||
pullpc
|
||||
```
|
||||
|
||||
## Sprite Properties
|
||||
Explicit sprite properties (`!SPRID`, `!Health`, etc.) are not defined within this file, suggesting it either inherits vanilla properties for sprite ID $71 or these are defined in a separate configuration file.
|
||||
|
||||
## Main Structure (`Sprite_Leever_Long`)
|
||||
This routine is the main entry point for the custom Leever logic, executed every frame. It handles bank setup, conditional drawing (skipping drawing when underground), and dispatches to the main logic if the sprite is active.
|
||||
|
||||
```asm
|
||||
Sprite_Leever_Long:
|
||||
{
|
||||
PHB : PHK : PLB
|
||||
LDA.w SprAction, X : BEQ +
|
||||
JSR Sprite_Leever_Draw
|
||||
+
|
||||
JSL Sprite_CheckActive : BCC .SpriteIsNotActive
|
||||
JSR Sprite_Leever_Main
|
||||
.SpriteIsNotActive
|
||||
PLB
|
||||
RTL
|
||||
}
|
||||
```
|
||||
|
||||
## Movement Routine (`Sprite_Leever_Move`)
|
||||
A shared routine for handling the Leever's movement, including applying speed towards the player, moving the sprite, and bouncing off tiles.
|
||||
|
||||
```asm
|
||||
Sprite_Leever_Move:
|
||||
{
|
||||
JSL Sprite_ApplySpeedTowardsPlayer
|
||||
JSL Sprite_Move
|
||||
JSL Sprite_BounceFromTileCollision
|
||||
RTS
|
||||
}
|
||||
```
|
||||
|
||||
## Main Logic & State Machine (`Sprite_Leever_Main`)
|
||||
The Leever's core behavior is managed by a state machine with four distinct states:
|
||||
|
||||
* **`Leever_Underground`**: The Leever moves underground. After a timer (`SprTimerA`) expires, it transitions to `Leever_Emerge`.
|
||||
* **`Leever_Emerge`**: The Leever plays a backwards animation as it emerges. After a randomized timer, it transitions to `Leever_Attack`.
|
||||
* **`Leever_Attack`**: The Leever plays an attack animation, checks for damage to/from Link, and moves. After a timer, it transitions to `Leever_Dig`.
|
||||
* **`Leever_Dig`**: The Leever plays an animation as it digs back into the ground. After a randomized timer, it transitions back to `Leever_Underground`.
|
||||
|
||||
```asm
|
||||
Sprite_Leever_Main:
|
||||
{
|
||||
JSL Sprite_DamageFlash_Long
|
||||
LDA.w SprAction, X
|
||||
JSL JumpTableLocal
|
||||
|
||||
dw Leever_Underground
|
||||
dw Leever_Emerge
|
||||
dw Leever_Attack
|
||||
dw Leever_Dig
|
||||
|
||||
Leever_Underground:
|
||||
{
|
||||
LDA.w SprTimerA, X : BNE +
|
||||
LDA.b #$40 : STA.w SprTimerA, X
|
||||
INC.w SprAction, X
|
||||
+
|
||||
LDA.b #$10
|
||||
JSR Sprite_Leever_Move
|
||||
RTS
|
||||
}
|
||||
|
||||
Leever_Emerge:
|
||||
{
|
||||
%PlayAnimBackwards(3, 2, 10)
|
||||
LDA.w SprTimerA, X : BNE +
|
||||
JSL GetRandomInt
|
||||
AND.b #$3F
|
||||
ADC.b #$A0
|
||||
STA.w $0DF0,X
|
||||
INC.w SprAction, X
|
||||
STZ.w SprXSpeed, X : STZ.w SprYSpeed, X
|
||||
+
|
||||
RTS
|
||||
}
|
||||
|
||||
Leever_Attack:
|
||||
{
|
||||
%PlayAnimation(0, 1, 10)
|
||||
LDA.w SprTimerA, X : BNE +
|
||||
LDA.b #$7F : STA.w SprTimerA, X
|
||||
INC.w SprAction, X
|
||||
+
|
||||
PHX
|
||||
JSL Sprite_CheckIfRecoiling
|
||||
JSL Sprite_CheckDamageToPlayerSameLayer
|
||||
JSL Sprite_CheckDamageFromPlayer
|
||||
PLX
|
||||
LDA.b #$0C
|
||||
JSR Sprite_Leever_Move
|
||||
RTS
|
||||
}
|
||||
|
||||
Leever_Dig:
|
||||
{
|
||||
%PlayAnimation(2, 3, 10)
|
||||
LDA.w SprTimerA, X : BNE +
|
||||
JSL GetRandomInt
|
||||
AND.b #$1F
|
||||
ADC.b #$40
|
||||
STA.w $0DF0,X
|
||||
STZ.w SprAction, X
|
||||
+
|
||||
LDA.b #$08
|
||||
JSR Sprite_Leever_Move
|
||||
RTS
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Drawing (`Sprite_Leever_Draw`)
|
||||
The drawing routine handles OAM allocation and animation. It explicitly uses `REP #$20` and `SEP #$20` for 16-bit coordinate calculations.
|
||||
|
||||
```asm
|
||||
Sprite_Leever_Draw:
|
||||
{
|
||||
JSL Sprite_PrepOamCoord
|
||||
JSL Sprite_OAM_AllocateDeferToPlayer
|
||||
|
||||
LDA $0DC0, X : CLC : ADC $0D90, X : TAY;Animation Frame
|
||||
LDA .start_index, Y : STA $06
|
||||
LDA.w SprFlash, X : STA $08
|
||||
|
||||
|
||||
PHX
|
||||
LDX .nbr_of_tiles, Y ;amount of tiles -1
|
||||
LDY.b #$00
|
||||
.nextTile
|
||||
|
||||
PHX ; Save current Tile Index?
|
||||
|
||||
TXA : CLC : ADC $06 ; Add Animation Index Offset
|
||||
|
||||
PHA ; Keep the value with animation index offset?
|
||||
|
||||
ASL A : TAX
|
||||
|
||||
REP #$20
|
||||
|
||||
LDA $00 : CLC : ADC .x_offsets, X : STA ($90), Y
|
||||
AND.w #$0100 : STA $0E
|
||||
INY
|
||||
LDA $02 : CLC : ADC .y_offsets, X : STA ($90), Y
|
||||
CLC : ADC #$0010 : CMP.w #$0100
|
||||
SEP #$20
|
||||
BCC .on_screen_y
|
||||
|
||||
LDA.b #$F0 : STA ($90), Y ;Put the sprite out of the way
|
||||
STA $0E
|
||||
.on_screen_y
|
||||
|
||||
PLX ; Pullback Animation Index Offset (without the *2 not 16bit anymore)
|
||||
INY
|
||||
LDA .chr, X : STA ($90), Y
|
||||
INY
|
||||
LDA .properties, X : ORA $08 : STA ($90), Y
|
||||
|
||||
PHY
|
||||
|
||||
TYA : LSR #2 : TAY
|
||||
|
||||
LDA .sizes, X : ORA $0F : STA ($92), Y ; store size in oam buffer
|
||||
|
||||
PLY : INY
|
||||
|
||||
PLX : DEX : BPL .nextTile
|
||||
|
||||
PLX
|
||||
|
||||
RTS
|
||||
|
||||
.start_index
|
||||
db $00, $01, $02, $03
|
||||
.nbr_of_tiles
|
||||
db 0, 0, 0, 0
|
||||
.x_offsets
|
||||
dw 0
|
||||
dw 0
|
||||
dw 0
|
||||
dw 0
|
||||
.y_offsets
|
||||
dw 0
|
||||
dw 0
|
||||
dw 0
|
||||
dw 0
|
||||
.chr
|
||||
db $C4
|
||||
db $C6
|
||||
db $C2
|
||||
db $C0
|
||||
.properties
|
||||
db $33
|
||||
db $33
|
||||
db $33
|
||||
db $33
|
||||
.sizes
|
||||
db $02
|
||||
db $02
|
||||
db $02
|
||||
db $02
|
||||
}
|
||||
```
|
||||
|
||||
## Design Patterns
|
||||
* **Vanilla Override**: Explicitly overrides a vanilla sprite's behavior, demonstrating how to replace existing game logic with custom implementations.
|
||||
* **Conditional Logic**: Uses a custom flag (`$0FFF`) to dynamically switch between vanilla and custom behaviors, offering flexibility in game design.
|
||||
* **Emerging/Digging State Machine**: Implements a robust state machine to manage the Leever's characteristic emerging from and digging back into the ground, with randomized timers for unpredictable transitions.
|
||||
* **Animation Control**: Utilizes `%PlayAnimBackwards` for specific animation effects, such as the Leever emerging from the ground.
|
||||
* **16-bit OAM Calculations**: Demonstrates explicit use of `REP #$20` and `SEP #$20` for precise 16-bit OAM coordinate calculations, essential for accurate sprite rendering.
|
||||
Reference in New Issue
Block a user