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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
This tutorial will teach you how to add a new sprite for use indoors or in the overworld.
## Contents
1. [Determining which kind of sprite will be needed](#1-determining-which-kind-of-sprite-will-be-needed)
2. [Define a new constant](#2-define-a-new-constant)
3. [Design and include the GFX files](#3-design-and-include-the-gfx-files)
4. [Defining properties](#4-defining-properties)
5. [Define which maps will use each sprite](#5-define-which-maps-will-use-each-sprite)
## 1. Determining which kind of sprite will be needed
Sprites can either face the player or be completely still. Depending on the purpose of the sprite you're adding, there is a small difference in how they're handled.
Most of the sprites in the game are regular ones, which can face any direction. Still sprites, on the other hand, won't face it's direction even if the player interacts with it. Some examples of still sprites are the overworld Pokéballs and the asleep Gambler in Viridian City.
For this tutorial, I'll add a regular sprite (Brock from GSC) and a still sprite (a 1-frame, edited GSC Equine icon as a sprite).
## 2. Define a new constant
Edit [constants/sprite_constants.asm](../blob/master/constants/sprite_constants.asm).
For regular sprites:
```diff
; overworld sprites
; SpriteSheetPointerTable indexes (see data/sprites/sprites.asm)
const_def
const SPRITE_NONE ; $00
const SPRITE_RED ; $01
...
const SPRITE_SEEL ; $3c
+ const SPRITE_BROCK
```
For still sprites:
```diff
FIRST_STILL_SPRITE EQU const_value
const SPRITE_POKE_BALL ; $3d
const SPRITE_FOSSIL ; $3e
...
const SPRITE_GAMBLER_ASLEEP ; $48
+ const SPRITE_EQUINE
```
## 3. Design and include the GFX files
Regular sprites can either be 16x48 if they don't need to move, or 16x96 if they need to move. Still sprites are 16x16.
```diff
SECTION "NPC Sprites 1", ROMX
ScientistSprite:: INCBIN "gfx/sprites/scientist.2bpp"
...
LoreleiSprite:: INCBIN "gfx/sprites/lorelei.2bpp"
SeelSprite:: INCBIN "gfx/sprites/seel.2bpp"
+
+SECTION "NPC Sprites 3", ROMX
+
+BrockSprite:: INCBIN "gfx/sprites/brock.2bpp"
+EquineSprite:: INCBIN "gfx/sprites/equine.2bpp"
```
## 4. Defining properties
Edit [data/sprites/sprites.asm](../blob/data/sprites/sprites.asm). Here you'll define how many tiles each graphics, defined in the prior session, will need.
```diff
SpriteSheetPointerTable:
table_width 4, SpriteSheetPointerTable
; graphics, tile count
overworld_sprite RedSprite, 12 ; SPRITE_RED
...
overworld_sprite SeelSprite, 12 ; SPRITE_SEEL
+ overworld_sprite BrockSprite, 12
...
overworld_sprite GamblerAsleepSprite, 4 ; SPRITE_GAMBLER_ASLEEP
+ overworld_sprite EquineSprite, 4
```
## 5. Define which maps will use each sprite
Edit the corresponding file in [data/maps/objects](../blob/data/maps/objects). I changed `SPRITE_SUPER_NERD` to `SPRITE_BROCK` in [data/maps/objects/PewterGym.asm](../blob/data/maps/objects/PewterGym.asm) so Brock's sprite would show up.
```diff
PewterGym_Object:
db $3 ; border block
def_warps
...
def_objects
- object SPRITE_SUPER_NERD, 4, 1, STAY, DOWN, 1, OPP_BROCK, 1
+ object SPRITE_BROCK, 4, 1, STAY, DOWN, 1, OPP_BROCK, 1
object SPRITE_COOLTRAINER_M, 3, 6, STAY, RIGHT, 2, OPP_JR_TRAINER_M, 1
object SPRITE_GYM_GUIDE, 7, 10, STAY, DOWN, 3 ; person
def_warps_to PEWTER_GYM
```
I decided to change the asleep Gambler sprite in [data/maps/objects/ViridianCity.asm](../blob/data/maps/objects/ViridianCity.asm) with the Equine sprite.
```diff
ViridianCity_Object:
db $f ; border block
def_warps
warp 23, 25, 0, VIRIDIAN_POKECENTER
...
object SPRITE_GIRL, 17, 9, STAY, RIGHT, 4 ; person
- object SPRITE_GAMBLER_ASLEEP, 18, 9, STAY, NONE, 5 ; person
+ object SPRITE_EQUINE, 18, 9, STAY, NONE, 5 ; person
object SPRITE_FISHER, 6, 23, STAY, DOWN, 6 ; person
object SPRITE_GAMBLER, 17, 5, WALK, LEFT_RIGHT, 7 ; person
def_warps_to VIRIDIAN_CITY
```
Since it's used in the overworld, [data/maps/sprite_sets.asm](../blob/data/maps/sprite_sets.asm) needs to be edited as well.
```diff
MapSpriteSets:
table_width 1, MapSpriteSets
db $01 ; PALLET_TOWN
db $01 ; VIRIDIAN_CITY
...
; sprite set $01
table_width 1
db SPRITE_BLUE
db SPRITE_YOUNGSTER
db SPRITE_GIRL
db SPRITE_FISHER
db SPRITE_COOLTRAINER_M
db SPRITE_GAMBLER
db SPRITE_SEEL
db SPRITE_OAK
db SPRITE_SWIMMER
db SPRITE_POKE_BALL
- db SPRITE_GAMBLER_ASLEEP
+ db SPRITE_EQUINE
assert_table_length SPRITE_SET_LENGTH
```

|