Add sprite analysis documentation for various bosses and mini-bosses
- Created detailed documentation for the Kydrog Boss sprite, outlining its phases, behaviors, and mechanics. - Added analysis for the Manhandla sprite, including its transformation into Big Chuchu and phase management. - Documented the Octoboss sprite, highlighting its unique mechanics and interactions with a "brother" Octoboss. - Provided an overview of the Twinrova boss sprite, detailing its transformation and phase-based attacks. - Included analysis for the Vampire Bat mini-boss, emphasizing its enhanced behavior compared to standard Keese. - Documented the Wolfos mini-boss, focusing on its integration into a mask quest and unique pacification mechanics.
This commit is contained in:
@@ -31,6 +31,11 @@ At the top of your new sprite file, define its core properties using the provide
|
||||
!Prize = 01 ; Prize pack dropped on death (0-15)
|
||||
; ... and so on for all properties ...
|
||||
|
||||
; --- Design Considerations ---
|
||||
; * **Multi-purpose Sprite IDs:** A single `!SPRID` can be used for multiple distinct behaviors (e.g., Dark Link and Ganon) through the use of `SprSubtype`. This is a powerful technique for reusing sprite slots and creating multi-phase bosses or variations of enemies.
|
||||
; * **Damage Handling for Bosses:** For boss sprites, `!Damage = 0` is acceptable if damage is applied through other means, such as spawned projectiles or direct contact logic within the main routine.
|
||||
; * **Custom Boss Logic:** Setting `!Boss = 00` for a boss sprite indicates that custom boss logic is being used, rather than relying on vanilla boss flags. This is important for understanding how boss-specific behaviors are implemented.
|
||||
|
||||
; This macro MUST be called after the properties
|
||||
%Set_Sprite_Properties(Sprite_MyNewEnemy_Prep, Sprite_MyNewEnemy_Long)
|
||||
```
|
||||
@@ -103,13 +108,16 @@ Sprite_MyNewEnemy_Main:
|
||||
RTS
|
||||
}
|
||||
|
||||
State_Hurt:
|
||||
{
|
||||
; Sprite was hit, flash and get knocked back
|
||||
JSL Sprite_DamageFlash_Long
|
||||
RTS
|
||||
}
|
||||
}
|
||||
; State_Hurt:
|
||||
; {
|
||||
; ; Sprite was hit, flash and get knocked back
|
||||
; JSL Sprite_DamageFlash_Long
|
||||
; RTS
|
||||
; }
|
||||
; }
|
||||
;
|
||||
; --- Code Readability Note ---
|
||||
; For improved readability and maintainability, always prefer using named constants for hardcoded values (e.g., timers, speeds, health, magic numbers) and named labels for `JSL` calls to project-specific functions instead of direct numerical addresses.
|
||||
```
|
||||
|
||||
## 6. Drawing (`_Draw` routine)
|
||||
@@ -135,11 +143,66 @@ Sprite_MyNewEnemy_Draw:
|
||||
db $C0, $C2, $C4, $C6, $C8, $CA, $CC, $CE
|
||||
.properties ; OAM properties (palette, priority, flips)
|
||||
db $3B, $7B, $3B, $7B, $3B, $7B, $3B, $7B
|
||||
.sizes ; Size of each tile (e.g., $02 for 16x16)
|
||||
db $02, $02, $02, $02, $02, $02, $02, $02
|
||||
}
|
||||
; .sizes ; Size of each tile (e.g., $02 for 16x16)
|
||||
; db $02, $02, $02, $02, $02, $02, $02, $02
|
||||
; }
|
||||
;
|
||||
; --- Code Readability Note ---
|
||||
; For improved readability and maintainability, always prefer using named constants for hardcoded values (e.g., OAM properties, tile numbers) and named labels for `JSL` calls to project-specific functions instead of direct numerical addresses.
|
||||
```
|
||||
|
||||
## 7. Final Integration
|
||||
|
||||
The `%Set_Sprite_Properties()` macro you added in Step 2 handles the final integration. It automatically adds your sprite's `_Prep` and `_Long` routines to the game's sprite tables in `Core/sprite_new_table.asm`. Your sprite is now ready to be placed in the game world!
|
||||
The %Set_Sprite_Properties() macro you added in Step 2 handles the final integration. It automatically adds your sprite's _Prep and _Long routines to the game's sprite tables in Core/sprite_new_table.asm. Your sprite is now ready to be placed in the game world!
|
||||
|
||||
## 8. Advanced Sprite Design Patterns
|
||||
|
||||
### 8.1. Multi-Part Sprites and Child Sprites
|
||||
For complex bosses or entities, you can break them down into a main parent sprite and multiple child sprites.
|
||||
|
||||
* **Parent Sprite Responsibilities:**
|
||||
* Spawns and manages its child sprites (e.g., Kydreeok spawning `kydreeok_head` instances).
|
||||
* Monitors the state/health of its child sprites to determine its own phases, actions, or defeat conditions.
|
||||
* Often handles overall movement, phase transitions, and global effects.
|
||||
* Uses global variables (e.g., `Offspring1_Id`, `Offspring2_Id`) to store the sprite IDs of its children for easy referencing.
|
||||
* **Child Sprite Responsibilities:**
|
||||
* Handles its own independent logic, movement, and attacks.
|
||||
* May be positioned relative to the parent sprite.
|
||||
* Can use `SprSubtype` to differentiate between multiple instances of the same child sprite ID (e.g., left head vs. right head).
|
||||
* **Shared Sprite IDs for Variations:** A single `!SPRID` can also be used for different enemy variations (e.g., Keese, Fire Keese, Ice Keese, Vampire Bat) by assigning unique `SprSubtype` values. This is an efficient way to reuse sprite slots and base logic.
|
||||
|
||||
### 8.2. Multi-Phase Bosses and Dynamic Health Management
|
||||
Boss fights can be made more engaging by implementing multiple phases and dynamic health management.
|
||||
|
||||
* **Phase Transitions:** Trigger new phases based on health thresholds, timers, or the defeat of child sprites. Phases can involve:
|
||||
* Changing the boss's graphics or palette.
|
||||
* Altering movement patterns and attack routines.
|
||||
* Spawning new entities or environmental hazards.
|
||||
* **Health Management:** Boss health can be managed in various ways:
|
||||
* Directly via the parent sprite's `SprHealth`.
|
||||
* Indirectly by monitoring the health or state of child sprites (e.g., Kydreeok's main body health is tied to its heads).
|
||||
* Using custom variables (e.g., `!KydrogPhase`) to track overall boss progression.
|
||||
* **Quest Integration and Pacification:** Sprites can be integrated into quests where "defeat" might mean pacification rather than outright killing. This can involve refilling health and changing the sprite's state to a subdued or quest-complete action (e.g., Wolfos granting a mask after being subdued by the Song of Healing).
|
||||
|
||||
### 8.3. Code Reusability and Modularity
|
||||
When designing multiple sprites, especially bosses, look for opportunities to reuse code and create modular components.
|
||||
|
||||
* **Shared Logic:** If multiple sprites perform similar actions (e.g., spawning stalfos, specific movement patterns), consider creating common functions or macros that can be called by different sprites. This reduces code duplication and improves maintainability.
|
||||
* **Refactoring:** Regularly refactor duplicated code into reusable components. This makes it easier to apply changes consistently across related sprites.
|
||||
|
||||
### 8.4. Configurability and Avoiding Hardcoded Values
|
||||
To improve sprite reusability and ease of placement in different maps, avoid hardcoding values that might change.
|
||||
|
||||
* **Activation Triggers:** Instead of hardcoding specific screen coordinates or camera values for activation (e.g., Octoboss's Y-coordinate trigger), consider using:
|
||||
* Sprite properties (`SprMiscA`, `SprMiscB`, etc.) to store configurable trigger values.
|
||||
* Room-specific flags or events that can be set externally.
|
||||
* Relative positioning or distance checks to Link.
|
||||
* **Timers, Speeds, Offsets:** Always prefer using named constants (`!CONSTANT_NAME = value`) for numerical values that control behavior (timers, speeds, offsets, health thresholds). This significantly improves readability and makes it easier to adjust parameters without searching through code.
|
||||
* **Function Calls:** Use named labels for `JSL` calls to project-specific functions instead of direct numerical addresses.
|
||||
|
||||
### 8.5. Overriding Vanilla Behavior
|
||||
When creating new boss sequences or modifying existing enemies, it's common to override vanilla sprite behavior.
|
||||
|
||||
* **Hooking Entry Points:** Identify the entry points of vanilla sprites (e.g., `Sprite_Blind_Long`, `Sprite_Blind_Prep`) and use `org` directives to redirect execution to your custom routines.
|
||||
* **Contextual Checks:** Within your custom routines, perform checks (e.g., `LDA.l $7EF3CC : CMP.b #$06`) to determine if the vanilla behavior should be executed or if your custom logic should take over.
|
||||
* **SRAM Flags:** Utilize SRAM flags (`$7EF3XX`) to track quest progression or conditions that dictate whether vanilla or custom behavior is active.
|
||||
Reference in New Issue
Block a user