summaryrefslogtreecommitdiff
path: root/Add-a-new-map-object-movement-behavior.md
diff options
context:
space:
mode:
Diffstat (limited to 'Add-a-new-map-object-movement-behavior.md')
-rw-r--r--Add-a-new-map-object-movement-behavior.md101
1 files changed, 101 insertions, 0 deletions
diff --git a/Add-a-new-map-object-movement-behavior.md b/Add-a-new-map-object-movement-behavior.md
new file mode 100644
index 0000000..dc2841d
--- /dev/null
+++ b/Add-a-new-map-object-movement-behavior.md
@@ -0,0 +1,101 @@
+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.