This tutorial is for how to add a new map object movement behavior. Map objects are defined by `object_event`s in map event scripts, and their assigned `SPRITEMOVEDATA_*` constants define their movement behavior. This controls how the objects' sprite appears, how it moves, and how it interacts with the player. For example, objects with `SPRITEMOVEDATA_WALK_UP_DOWN` appear as a 16x16 pixel sprite that walks up and down within a certain radius; while objects with `SPRITEMOVEDATA_BIGDOLL` appear as a 32x32 pixel sprite that does not move. (Map objects are *not* the same as sprites. A sprite is an 8x8 pixel entity, of which you can have 40 on-screen at a time. Map objects are composed of sprites—a 16x16 pixel object consists of four sprites, for instance—but sprites are used throughout the game, not just in the overworld map engine.) ## Contents 1. [Define sprite movement constant and data](#1-define-sprite-movement-constant-and-data) ## 1. Define sprite movement constant and data At a minimum, you need to define a new `SPRITEMOVEDATA_*` constant and its corresponding data. As an example, we'll define `SPRITEMOVEDATA_SWIM_UP_DOWN`. Edit [constants/map_object_constants.asm](../blob/master/constants/map_object_constants.asm): ```diff ; SpriteMovementData indexes (see data/sprites/map_objects.asm) const_def const SPRITEMOVEDATA_00 ; 00 ... const SPRITEMOVEDATA_SWIM_WANDER ; 24 + const SPRITEMOVEDATA_SWIM_UP_DOWN NUM_SPRITEMOVEDATA EQU const_value ``` And edit [data/sprites/map_objects.asm](../blob/master/data/sprites/map_objects.asm): ```diff SpriteMovementData:: ; entries correspond to SPRITEMOVEDATA_* constants ; SPRITEMOVEDATA_00 db SPRITEMOVEFN_00 ; movement function db DOWN ; facing db OBJECT_ACTION_STAND ; action db WONT_DELETE ; flags1 db 0 ; flags2 db 0 ; palette flags ... ; SPRITEMOVEDATA_SWIM_WANDER db SPRITEMOVEFN_RANDOM_WALK_XY ; movement function db DOWN ; facing db OBJECT_ACTION_STAND ; action db 0 ; flags1 db 0 ; flags2 db SWIMMING ; palette flags -; 25 - db SPRITEMOVEFN_00 ; movement function - db DOWN ; facing - db OBJECT_ACTION_STAND ; action - db 0 ; flags1 - db 0 ; flags2 - db 0 ; palette flags +; SPRITEMOVEDATA_SWIM_UP_DOWN + db SPRITEMOVEFN_RANDOM_WALK_Y ; movement function + db DOWN ; facing + db OBJECT_ACTION_STAND ; action + db 0 ; flags1 + db 0 ; flags2 + db SWIMMING ; palette flags ``` Note that we had to delete some unused data at the bottom which didn't correspond to any `SPRITEMOVEDATA_*` constant. Here's what the individual `db` values mean: - **movement function:** A `SPRITEMOVEFN_*` constant, as defined in [constants/map_object_constants.asm](../blob/master/constants/map_object_constants.asm). - **facing:** `UP`, `DOWN`, `LEFT`, or `RIGHT`. - **action:** An `OBJECT_ACTION_*` constant, as defined in [constants/map_object_constants.asm](../blob/master/constants/map_object_constants.asm). - **flags1:** A combination of any of these values, or 0 for none of them: - `WONT_DELETE`: The object won't be deleted if it moves off-screen. Example: `SPRITEMOVEDATA_STRENGTH_BOULDER`, which needs to stay where it's been pushed. - `FIXED_FACING`: The object doesn't change its facing direction if it moves. Example: `SPRITEMOVEDATA_SHADOW`, which moves along with the player over a ledge but always looks the same. - `SLIDING`: The object doesn't animate its steps if it moves. Example: `SPRITEMOVEDATA_GRASS`, which moves along with the player through tall grass but doesn't have a "stepping" animation. - `MOVE_ANYWHERE`: The object isn't limited to moving within a particular radius. Example: `SPRITEMOVEDATA_STRENGTH_BOULDER`, which can be pushed anywhere. - `EMOTE_OBJECT`: The object is meant to be transient and gets deleted differently. Example: `SPRITEMOVEDATA_EMOTE`, which pops up briefly above an NPC. - **flags2:** A combination of any of these values, or 0 for none of them: - `LOW_PRIORITY`: The object will appear below other objects, which have normal priority by default. Example: `SPRITEMOVEDATA_BOULDERDUST`, which appears below Strength boulders when they're pushed. - `HIGH_PRIORITY`: The object will appear above other objects. Do not combine with `LOW_PRIORITY`. Example: `SPRITEMOVEDATA_GRASS`, which appears above the player when walking through tall grass. - `USE_OBP1`: The object will use SGB palette #1 instead of #0. This was relevant for Gold and Silver since they could be played on the Super Game Boy, but not Crystal. - **palette flags:** A combination of any of these values, or 0 for none of them: - `SWIMMING`: The object can move over water but is blocked by land, instead of vice-versa. Example: `SPRITEMOVEDATA_SWIM_WANDER`, which is used for the Lapras in Union Cave. - `STRENGTH_BOULDER`: The object blocks the player if they haven't used Strength. Example: `SPRITEMOVEDATA_STRENGTH_BOULDER` of course, but also the `SPRITEMOVEDATA_BIGDOLL*` data for some reason. - `BIG_OBJECT`: The object blocks the spaces below it, to its right, and to its bottom-right, not just the space its coordinates are at. Example: `SPRITEMOVEDATA_BIGDOLLSYM`, which is used for the Snorlax in Vermilion City. In the example, we based `SPRITEMOVEDATA_SWIM_UP_DOWN` off of `SPRITEMOVEDATA_SWIM_WANDER` but gave it the same movement function as `SPRITEMOVEDATA_WALK_UP_DOWN`. In particular, it needed the `SWIMMING` palette flag. One more thing: there happens to be a bug that affects objects which swim and move randomly; they're not actually limited by their movement radius. So be sure to [fix that](../blob/master/docs/bugs_and_glitches.md#swimming-npcs-arent-limited-by-their-movement-radius). Anyway, that's all! Now you can use `SPRITEMOVEDATA_SWIM_UP_DOWN` for `object_event`s just like the rest. ![Screenshot](screenshots/swimming.png) TODO: define new `SPRITEMOVEFN_*`, `OBJECT_ACTION_*`, and `FACING_*` data. TODO: define new `STEP_TYPE_*` and `STEP_*` data.