diff options
-rw-r--r-- | Add-a-new-tileset.md | 246 | ||||
-rw-r--r-- | Tutorials.md | 3 | ||||
-rw-r--r-- | screenshots/gfx-tilesets-museum.png | bin | 0 -> 1119 bytes | |||
-rw-r--r-- | screenshots/museum-tileset.png | bin | 0 -> 1694 bytes | |||
-rw-r--r-- | screenshots/polished-map-edit-block.png | bin | 0 -> 4173 bytes | |||
-rw-r--r-- | screenshots/polished-map-edit-tile.png | bin | 0 -> 7025 bytes | |||
-rw-r--r-- | screenshots/polished-map-pewter-museum.png | bin | 0 -> 11211 bytes |
7 files changed, 248 insertions, 1 deletions
diff --git a/Add-a-new-tileset.md b/Add-a-new-tileset.md new file mode 100644 index 0000000..6f3d48e --- /dev/null +++ b/Add-a-new-tileset.md @@ -0,0 +1,246 @@ +This tutorial is for how to add a new tileset. As an example, we'll add Pewter Museum's tileset from [pokered](https://github.com/pret/pokered/) (since its unused palette data already exists in pokecrystal). + + +## Contents + +1. [Define a tileset constant](#1-define-a-tileset-constant) +2. [Point to the tileset's associated data](#2-point-to-the-tilesets-associated-data) +3. [Design its graphics](#3-design-its-graphics) +4. [Design its palette map](#4-design-its-palette-map) +5. [Design its blocks (aka metatiles)](#5-design-its-blocks-aka-metatiles) +6. [Define its collision data](#6-define-its-collision-data) +7. [Include the new files in the ROM](#7-include-the-new-files-in-the-rom) +8. [Define its animated tiles](#8-define-its-animated-tiles) + + +## 1. Define a tileset constant + +Edit [constants/tileset_constants.asm](../blob/master/constants/tileset_constants.asm): + +```diff + ; Tilesets indexes (see data/tilesets.asm) + const_def 1 + const TILESET_JOHTO ; 01 + ... + const TILESET_AERODACTYL_WORD_ROOM ; 24 ++ const TILESET_MUSEUM +``` + + +## 2. Point to the tileset's associated data + +Edit [data/tilesets.asm](../blob/master/data/tilesets.asm): + +```diff + ; Associated data: + ; - The *GFX, *Meta, and *Coll are defined in gfx/tilesets.asm + ; - The *PalMap are defined in gfx/tileset_palette_maps.asm + ; - The *Anim are defined in engine/tileset_anims.asm + + Tilesets:: + ; entries correspond to TILESET_* constants + tileset Tileset0 + tileset TilesetJohto + ... + tileset TilesetAerodactylWordRoom ++ tileset TilesetMuseum +``` + +The `tileset` macro simultaneously declares pointers to `Tileset*GFX`, `Tileset*Meta`, `Tileset*Coll`, `Tileset*PalMap`, and `Tileset*Anim`. Those five labels all need to be defined, and their respective data needs to be created. + +- `TilesetMuseumGFX` will be the label for **gfx/tilesets/museum.png** +- `TilesetMuseumMeta` will be the label for **data/tilesets/museum_metatiles.bin** +- `TilesetMuseumColl` will be the label for **data/tilesets/museum_collision.asm** +- `TilesetMuseumPalMap` will be the label for **gfx/tilesets/museum_palette_map.asm** +- `TilesetMuseumAnim` will be a label in [engine/tilesets/tileset_anims.asm](../blob/master/engine/tilesets/tileset_anims.asm) + + +## 3. Design its graphics + +Create **gfx/tilesets/museum.png**: + + + +This file is actually [gfx/tilesets/gate.png](https://github.com/pret/pokered/blob/master/gfx/tilesets/gate.png) from pokered. Despite its name there, it was also used for Pewter Museum. + +Tileset graphics can contain up to 192 tiles, each tile being 8x8 pixels. (Although this limit can be [expanded to 255 tiles](Expand-tilesets-from-192-to-255-tiles).) The graphics are four-color grayscale; we'll assign color palettes to the tiles next. + + +## 4. Design its palette map + +The way the GameBoy hardware works, tileset graphics aren't stored as a colored image. Instead the game has a set of grayscale tile graphics, a set of eight tile color palettes, and a way to assign the palettes to the tiles. In pokecrystal, each tile always has the same palette. (Although [this tutorial](Allow-tiles-to-have-different-attributes-in-different-blocks-\(including-X-and-Y-flip\)) explains how to give the same tile different colors in different places.) + +Rename [gfx/tilesets/unused_museum_palette_map.asm](../blob/master/unused_museum_palette_map.asm) to **gfx/tilesets/museum_palette_map.asm**. (Of course, if this were an original tileset, you would have to create the file.) + +These are its contents: + +``` + tilepal 0, WATER, RED, YELLOW, YELLOW, RED, GREEN, GREEN, BROWN + tilepal 0, BROWN, BROWN, GRAY, GRAY, GRAY, GRAY, GRAY, GRAY + tilepal 0, GRAY, GRAY, YELLOW, YELLOW, RED, GREEN, GREEN, BROWN + tilepal 0, BROWN, ROOF, GRAY, GRAY, GRAY, GRAY, GRAY, GRAY + tilepal 0, GRAY, GRAY, BROWN, BROWN, GRAY, BROWN, BROWN, ROOF + tilepal 0, ROOF, BROWN, BROWN, BROWN, ROOF, ROOF, ROOF, ROOF + tilepal 0, ROOF, ROOF, BROWN, BROWN, GRAY, BROWN, BROWN, ROOF + tilepal 0, ROOF, GRAY, ROOF, BROWN, ROOF, ROOF, GRAY, GRAY + tilepal 0, GRAY, GRAY, GRAY, GRAY, GRAY, GRAY, ROOF, ROOF + tilepal 0, GRAY, GRAY, GRAY, GRAY, GRAY, GRAY, RED, RED + tilepal 0, GRAY, GRAY, GRAY, GRAY, GRAY, GRAY, GRAY, GRAY + tilepal 0, GRAY, GRAY, GRAY, GRAY, GRAY, GRAY, GRAY, GRAY + +rept 16 + db $ff +endr + + tilepal 1, WATER, RED, YELLOW, YELLOW, RED, GREEN, GREEN, BROWN + tilepal 1, BROWN, BROWN, GRAY, GRAY, GRAY, GRAY, GRAY, GRAY + tilepal 1, GRAY, GRAY, YELLOW, YELLOW, RED, GREEN, GREEN, BROWN + tilepal 1, BROWN, ROOF, GRAY, GRAY, GRAY, GRAY, GRAY, GRAY + tilepal 1, GRAY, GRAY, BROWN, BROWN, GRAY, BROWN, BROWN, ROOF + tilepal 1, ROOF, BROWN, BROWN, BROWN, ROOF, ROOF, ROOF, ROOF + tilepal 1, ROOF, ROOF, BROWN, BROWN, GRAY, BROWN, BROWN, ROOF + tilepal 1, ROOF, GRAY, ROOF, BROWN, ROOF, ROOF, GRAY, GRAY + tilepal 1, GRAY, GRAY, GRAY, GRAY, GRAY, GRAY, ROOF, ROOF + tilepal 1, GRAY, GRAY, GRAY, GRAY, GRAY, GRAY, RED, RED + tilepal 1, GRAY, GRAY, GRAY, GRAY, GRAY, GRAY, GRAY, GRAY + tilepal 1, GRAY, GRAY, GRAY, GRAY, GRAY, GRAY, GRAY, GRAY +``` + +There are eight valid tile colors: `GRAY`, `RED`, `GREEN`, `WATER`, `YELLOW`, `BROWN`, `ROOF`, and `TEXT`. Some are special: + +- The lightest hue of `WATER` cycles between white, light blue, and dark blue in outdoor maps. This helps make the various water-related tiles look more animated, but it prevents you from using `WATER` for plain blue tiles. +- `YELLOW` appears to glow at night in outdoor maps. This is useful for windows, but it prevents you from using `YELLOW` for plain yellow tiles. +- `ROOF` is a light blue for indoor maps, but varies for outdoor maps depending on which map group they're in. For more information on `ROOF` colors, see the tutorial on [how to add a new map and landmark](Add-a-new-map-and-landmark). +- `TEXT` is reserved for textboxes and Crystal's popup map name signs. + +([This tutorial](Allow-map-tiles-to-appear-above-sprites-\(so-NPCs-can-walk-behind-tiles\)-with-PRIORITY-colors) explains how to add `PRIORITY` colors for tiles that appear above sprites.) + +Anyway, you can see how the colors pair up with the tile graphics, at least at first. Whenever a tile is drawn, the map engine refers to this list to get its color. There are actually more colors than there are tiles. This is harmless, but not necessary; if you're making a new tileset, you only need enough colors for each tile. (All the pokecrystal tilesets have palette data for every tile ID, even though few of them have that many tiles.) + +The `rept 16 db $ff endr` in the middle is skipping over tile IDs $60 to $7F, which are used for text characters instead of map tiles. ([This tutorial](Expand-tilesets-from-192-to-255-tiles) explains how to reorganize things so you can use all 255 tile IDs for maps.) + + +## 5. Design its blocks (aka metatiles) + +Maps in pokecrystal are designed with blocks, not tiles, where each block (aka "metatile") is a 4x4 square of tiles. + +Download [gfx/blocksets/gate.bst](https://github.com/pret/pokered/blob/master/gfx/blocksets/gate.bst) from pokered and save it as **data/tilesets/museum_metatiles.bin**. (Yes, the formats are identical from Gen 1 to Gen 2.) + +If this were an original tileset, you would have to create the file. You can create an empty text file with the extension .bin instead of .txt, or run the command `touch data/tilesets/museum_metatiles.bin` the same way you run `make`. Either way, you'd still have to define the blocks. You can technically design blocks with a hex editor, typing in tile IDs one by one, but that's tedious. + +Instead, you can use [Polished Map](https://github.com/Rangi42/polished-map). It's a program for editing maps and tilesets. Just open any of the [maps/\*.blk](../tree/master/maps/) files and pick "museum" as its tileset. As long as the graphics, palette map, and metatiles.bin files exist, this will work. Then click Tools → Resize Blockset… (or the blue **±** button) to add some blocks to the sidebar, and right-click one of them to open the block editor. + + + +You can also edit the tileset graphics and palette map from within Polished Map. Just click Tools → Edit Tileset… (or the green puzzle piece button). + + + +Note that the first block, with ID 0, is special. Whatever a map's border block is, block #0 will appear as that block. It will also be impassable, no matter what its collision data is, so you can't walk on it. If you know that every map will have the same border block (like the solid blackness surrounding indoor room maps), you can save space by designing that block as #0. But if, for example, some maps are surrounded by trees and others by water, you're better off just not using block #0. + +Anyway, once you've designed the blocks (and maybe edited the tiles), save your changes and close Polished Map. If you accidentally changed the map too, just revert the changes to the .blk file. (You *are* using Git to track your changes and frequently committing them, right?) + +Here, I copied [maps/museum1f.blk](https://github.com/pret/pokered/blob/master/maps/museum1f.blk) from pokered, saved it as **maps/PewterMuseum1F.blk**, and opened it in Polished Map as a 10x4 map with the museum tileset. + + + +Then I swapped block #0 (floor) and block #10 (solid black) and saved that change, so the border block would be #0 and the floor would be walkable. + + +## 6. Define its collision data + +Blocks are four times the size of NPCs. That means each block needs four pieces of collision data, defining how NPCs interact with the top-left, top-right, bottom-left, and bottom-right quadrants. + +Create **data/tilesets/museum_collision.asm**. As you can see from other collision data files, each block will need a `tilecoll` line defining the four quadrants. Valid collision values are in [constants/collision_constants.asm](../blob/master/constants/collision_constants.asm). + +The collision system in pokered was very different from pokecrystal, based on tiles instead of blocks, so we can't copy it this time. Here's a sample of valid collision data for the museum tileset: + +```diff ++ tilecoll WALL, WALL, WALL, WALL ; 00 ++ tilecoll FLOOR, WALL, FLOOR, WALL ; 01 ++ tilecoll WALL, FLOOR, WALL, FLOOR ; 02 ++ tilecoll WALL, WALL, FLOOR, FLOOR ; 03 ++ tilecoll FLOOR, FLOOR, FLOOR, FLOOR ; 04 ++ tilecoll LADDER, FLOOR, FLOOR, FLOOR ; 05 ++ tilecoll WALL, WALL, WALL, FLOOR ; 06 ++ tilecoll WALL, WALL, FLOOR, WALL ; 07 ++ tilecoll FLOOR, COUNTER, FLOOR, COUNTER ; 08 ++ tilecoll COUNTER, FLOOR, COUNTER, FLOOR ; 09 ++ tilecoll FLOOR, FLOOR, FLOOR, FLOOR ; 0a ++ tilecoll FLOOR, FLOOR, WARP_CARPET_DOWN, WARP_CARPET_DOWN ; 0b ++ tilecoll FLOOR, COUNTER, WARP_CARPET_DOWN, FLOOR ; 0c ++ tilecoll COUNTER, WALL, FLOOR, WALL ; 0d ++ tilecoll WALL, COUNTER, WALL, FLOOR ; 0e ++ tilecoll COUNTER, FLOOR, FLOOR, WARP_CARPET_DOWN ; 0f ++ ... +``` + +You'll have to define the other 112 blocks yourself. ;) + + +## 7. Include the new files in the ROM + +Edit [gfx/tilesets.asm](../blob/master/gfx/tilesets.asm): + +```diff + SECTION "Tileset Data 8", ROMX + + TilesetHoOhWordRoomMeta: + INCBIN "data/tilesets/ho_oh_word_room_metatiles.bin" + + TilesetKabutoWordRoomMeta: + INCBIN "data/tilesets/kabuto_word_room_metatiles.bin" + + TilesetOmanyteWordRoomMeta: + INCBIN "data/tilesets/omanyte_word_room_metatiles.bin" + + TilesetAerodactylWordRoomMeta: + INCBIN "data/tilesets/aerodactyl_word_room_metatiles.bin" ++ ++TilesetMuseumGFX: ++INCBIN "gfx/tilesets/museum.2bpp.lz" ++ ++TilesetMuseumMeta: ++INCBIN "data/tilesets/museum_metatiles.bin" ++ ++TilesetMuseumColl: ++INCLUDE "data/tilesets/museum_collision.asm" +``` + +It doesn't matter which `SECTION` these files go in. You can make new ones to keep them organized, or just keep filling the existing sections until they run out of space. (If `make` gives you a "Section is too big" or "Unable to place section in bank" error, you've overfilled a bank.) + +Now edit [gfx/tileset_palette_maps.asm](../blob/master/gfx/tileset_palette_maps.asm): + +```diff +-UnusedMuseumPalMap: +-INCLUDE "gfx/tilesets/unused_museum_palette_map.asm" ++TilesetMuseumPalMap: ++INCLUDE "gfx/tilesets/museum_palette_map.asm" +``` + +These files all go in the same section, so you can't have *too* many tilesets or the bank will overflow. That's unlikely to happen, but if it does, remember that most of the tilesets have excess palette data that can be removed. + + +## 8. Define its animated tiles + +Edit [engine/tilesets/tileset_anims.asm](../blob/master/engine/tilesets/tileset_anims.asm): + +```diff + TilesetBattleTowerOutsideAnim: + ... + TilesetAerodactylWordRoomAnim: ++TilesetMuseumAnim: + dw NULL, WaitTileAnimation + dw NULL, WaitTileAnimation + dw NULL, WaitTileAnimation + dw NULL, WaitTileAnimation + dw NULL, DoneTileAnimation +``` + +This tileset doesn't actually have any animated tiles, so it can share the same data as many other no-animation tilesets. If your tileset *does* have animated tiles—water, flowers, waterfalls, whirlpools, bubbling lava, etc—then look at how other tilesets do theirs. Each one basically has a list of commands that get run in sequence, until `DoneTileAnimation`, but the individual commands are all unique. + +Note that you can't animate tiles $80 and above. That's because they exist in VRAM bank 1, and the tile animation engine runs while in bank 0. + +Anyway, that's it. Now maps can use `TILESET_MUSEUM` like any other tileset. + + diff --git a/Tutorials.md b/Tutorials.md index 55c3c12..0b2499c 100644 --- a/Tutorials.md +++ b/Tutorials.md @@ -14,6 +14,7 @@ Tutorials may use diff syntax to show edits: **How to add a new…** - [Map and landmark](Add-a-new-map-and-landmark) +- [Tileset](Add-a-new-tileset) - [Pokémon species (up to 253)](Add-a-new-Pokémon) - [Trainer class](Add-a-new-trainer-class) - [Type (Fairy)](Add-a-new-Fairy-type) @@ -54,7 +55,7 @@ Tutorials may use diff syntax to show edits: - Spawn point (for Fly or Teleport) - Wild data - Roaming Pokémon -- Tileset, with animated tiles +- Animated tiles - Object facing - Map event script command - Move effect script command diff --git a/screenshots/gfx-tilesets-museum.png b/screenshots/gfx-tilesets-museum.png Binary files differnew file mode 100644 index 0000000..372e675 --- /dev/null +++ b/screenshots/gfx-tilesets-museum.png diff --git a/screenshots/museum-tileset.png b/screenshots/museum-tileset.png Binary files differnew file mode 100644 index 0000000..de272d6 --- /dev/null +++ b/screenshots/museum-tileset.png diff --git a/screenshots/polished-map-edit-block.png b/screenshots/polished-map-edit-block.png Binary files differnew file mode 100644 index 0000000..63f65cf --- /dev/null +++ b/screenshots/polished-map-edit-block.png diff --git a/screenshots/polished-map-edit-tile.png b/screenshots/polished-map-edit-tile.png Binary files differnew file mode 100644 index 0000000..17ddc5f --- /dev/null +++ b/screenshots/polished-map-edit-tile.png diff --git a/screenshots/polished-map-pewter-museum.png b/screenshots/polished-map-pewter-museum.png Binary files differnew file mode 100644 index 0000000..65cd757 --- /dev/null +++ b/screenshots/polished-map-pewter-museum.png |