summaryrefslogtreecommitdiff
path: root/Add-a-new-map-object-movement-behavior.md
blob: dc2841d12d1df37ab78644aa9d3aed45b8e25f44 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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.