This tutorial is for how to add a new overworld sprite. As an example, we'll add three different kinds of sprites. ## Contents 1. [Know which kind of sprite you need](#1-know-which-kind-of-sprite-you-need) 2. [Define a sprite constant](#2-define-a-sprite-constant) 3. [Update files depending on the kind of sprite](#3-update-files-depending-on-the-kind-of-sprite) - [Regular sprite: define graphics and properties](#regular-sprite-define-graphics-and-properties) - [Pokémon sprite: define corresponding Pokémon](#pokémon-sprite-define-corresponding-pokémon) - [Variable sprite: initialize appearance](#variable-sprite-initialize-appearance) ## 1. Know which kind of sprite you need There are three kinds of overworld sprites: - **Regular sprites** have their own individual graphics. - **Pokémon sprites** reuse the menu icons for party Pokémon. - **Variable sprites** do not have any graphics, but can appear as any other sprite. (The sprite they appear as can be changed, hence "variable".) ## 2. Define a sprite constant Edit [constants/sprite_constants.asm](../blob/master/constants/sprite_constants.asm): ```diff ; sprite ids ; OverworldSprites indexes (see data/sprites/sprites.asm) const_def const SPRITE_NONE ; 00 ... const SPRITE_STANDING_YOUNGSTER ; 66 + const SPRITE_GIOVANNI ; SpriteMons indexes (see data/sprites/sprite_mons.asm) const_def $80 SPRITE_POKEMON EQU const_value const SPRITE_UNOWN ; 80 ... const SPRITE_HO_OH ; a2 + const SPRITE_EGG ; special GetMonSprite values (see engine/overworld/overworld.asm) const_def $e0 const SPRITE_DAY_CARE_MON_1 ; e0 const SPRITE_DAY_CARE_MON_2 ; e1 ; wVariableSprites indexes (see wram.asm) const_def $f0 SPRITE_VARS EQU const_value const SPRITE_CONSOLE ; f0 ... const SPRITE_JANINE_IMPERSONATOR ; fc + const SPRITE_LOOKER ``` We've defined three new sprites: `SPRITE_GIOVANNI` is regular, `SPRITE_EGG` is a Pokémon, and `SPRITE_LOOKER` is variable. (The intention is that [Looker](https://bulbapedia.bulbagarden.net/wiki/Looker), the International Police officer, can appear in disguise.) The Pokémon sprites all come after defining `SPRITE_POKEMON`, and the variable sprites after `SPRITE_VARS`. Notice how their exact starting values are set by `const_def`; the particular values don't matter, so for example, if you need space for more Pokémon sprites you can lower the `SPRITE_POKEMON` starting value (thus eating into slots which could otherwise have been used for regular sprites). ## 3. Update files depending on the kind of sprite Each kind of sprite uses data in different files. ### Regular sprite: define graphics and properties First, create **gfx/sprites/giovanni.png**: ![gfx/sprites/giovanni.png](screenshots/gfx-sprites-giovanni.png) Then edit [gfx/sprites.asm](../blob/master/gfx/sprites.asm): ```diff +SECTION "Sprites 3", ROMX + +GiovanniSpriteGFX:: INCBIN "gfx/sprites/giovanni.2bpp" ``` It doesn't matter where new sprite graphics go, so you can add them in the existing sections or create new ones. New sections will automatically be placed wherever they'll fit when you run `make`, so you don't have to deal with bank overflow errors. Finally, edit [data/sprites/sprites.asm](../blob/master/data/sprites/sprites.asm): ```diff OverworldSprites: ; entries correspond to SPRITE_* constants overworld_sprite ChrisSpriteGFX, 12, WALKING_SPRITE, PAL_OW_RED ... overworld_sprite StandingYoungsterSpriteGFX, 12, STANDING_SPRITE, PAL_OW_BLUE + overworld_sprite GiovanniSpriteGFX, 12, WALKING_SPRITE, PAL_OW_BROWN ``` The `overworld_sprite` macro takes four arguments: - **pointer:** The label of the sprite graphics. - **length:** How many tiles the sprite uses, not counting alternate walking frames. A single frame is 16x16 pixels and 2x2 = 4 tiles; a standing or walking sprite has three basic frames, so 12 tiles total. - **type:** Either `WALKING_SPRITE`, `STANDING_SPRITE`, or `STILL_SPRITE`. - **palette:** The default color palette for overworld events that don't assign a particular one. Note that `BigSnorlaxSpriteGFX`, `BigLaprasSpriteGFX`, and `BigOnixSpriteGFX` do not have the usual three-frame structure (facing down, up, and to the side), but they still use the `STANDING_SPRITE` type. This is because the type just affects how many tiles get loaded when the sprite is used. NPC events in map scripts that use these sprites will also use the movement functions `SPRITEMOVEDATA_BIGDOLL`, `SPRITEMOVEDATA_BIGDOLLSYM` (for the symmetrical Snorlax or Lapras), or `SPRITEMOVEDATA_BIGDOLLASYM` (for the asymmetrical Onix). Different movement functions can make display the sprites' tiles in different ways than the usual 2-by-2 NPC structure. (Designing your own nonstandard sprites is beyond the scope of this tutorial.) ### Pokémon sprite: define corresponding Pokémon Edit [data/sprites/sprite_mons.asm](../blob/master/data/sprites/sprite_mons.asm): ```diff SpriteMons: ; entries correspond to SPRITE_* constants past SPRITE_POKEMON db UNOWN ... db HO_OH + db EGG ``` This means that `SPRITE_EGG` will use the same menu icon as `EGG`, just like `SPRITE_UNOWN` uses the icon for `UNOWN`, etc. There's one problem: `EGG` doesn't actually *have* a defined menu icon, since the party menu code treats Eggs as a special case. So edit [data/pokemon/menu_icons.asm](../blob/master/data/pokemon/menu_icons.asm): ```diff MonMenuIcons: db ICON_BULBASAUR ; BULBASAUR ... db ICON_HUMANSHAPE ; CELEBI + db ICON_MONSTER ; MON_FC + db ICON_EGG ; EGG + db ICON_MONSTER ; MON_FE ``` Now `EGG` (and the two unused Pokémon slots) has its menu icon defined in the usual way, so `SPRITE_EGG` will appear correctly. ### Variable sprite: initialize appearance Edit [engine/events/std_scripts.asm](../blob/master/engine/events/std_scripts.asm): ```diff InitializeEventsScript: ... variablesprite SPRITE_WEIRD_TREE, SPRITE_SUDOWOODO ... variablesprite SPRITE_JANINE_IMPERSONATOR, SPRITE_LASS + variablesprite SPRITE_LOOKER, SPRITE_ROCKET ``` `InitializeEventsScript` is called once at the very start of the game. It sets a lot of events, since they're all unset by default, and initializes how variable sprites will look. The variable sprites' appearances are stored in `wVariableSprites` in [wram.asm](../blob/master/wram.asm). We don't need to edit that, since it's automatically sized to fit all the variable sprites. Note that if you change the `const_def` before `SPRITE_VARS` to fit more (or fewer) variable sprites, the size of `wVariableSprites` will change, and it might get too big to fit in its bank. Then you'll have to find unused space in wram.asm to delete (like the `ds 40` a few lines above `wVariableSprites`). When event scripts use variable sprites, they use the `variablesprite` command to assign a new appearance, followed by `special LoadUsedSpritesGFX` if a sprites needs to visibly change its appearance. For example, in [maps/FuchsiaPokecenter1F.asm](../blob/master/maps/FuchsiaPokecenter1F.asm): ``` variablesprite SPRITE_JANINE_IMPERSONATOR, SPRITE_JANINE special LoadUsedSpritesGFX ... variablesprite SPRITE_JANINE_IMPERSONATOR, SPRITE_LASS special LoadUsedSpritesGFX ``` Anyway, that's all we need to do. Now the new `SPRITE_*` constants can be used just like any others. ![Screenshot](screenshots/overworld-sprites.png)