diff options
-rw-r--r-- | Add-weather-icons-when-selecting-a-move.md | 153 | ||||
-rw-r--r-- | Tutorials.md | 1 | ||||
-rw-r--r-- | screenshots/hail_icon.png | bin | 0 -> 267 bytes | |||
-rw-r--r-- | screenshots/rain_icon.png | bin | 0 -> 288 bytes | |||
-rw-r--r-- | screenshots/sand_icon.png | bin | 0 -> 288 bytes | |||
-rw-r--r-- | screenshots/sun_icon.png | bin | 0 -> 266 bytes |
6 files changed, 154 insertions, 0 deletions
diff --git a/Add-weather-icons-when-selecting-a-move.md b/Add-weather-icons-when-selecting-a-move.md new file mode 100644 index 0000000..1ffebb4 --- /dev/null +++ b/Add-weather-icons-when-selecting-a-move.md @@ -0,0 +1,153 @@ +Since Gen 5, the current weather gets displayed during battles on the bottom screen. This tutorial will explain how to do so in Gen 2, more specifically, during move selection. It works by creating a sprite for the weather icon, so you'll also learn how to work with sprite graphics on the Game Boy Color. + +## Add the code to display the sprites + +Edit [engine/battle/core.asm](../blob/master/engine/battle/core.asm) +```diff + BattleTurn: + ... + .skip_iteration + call ParsePlayerAction ++ push af ++ call ClearSprites ++ pop af + jr nz, .loop1 +``` +```diff + MoveSelectionScreen: + ... + .battle_player_moves + call MoveInfoBox ++ call GetWeatherImage + ld a, [wMoveSwapBuffer] + ... + .place_textbox_start_over ++ push hl ++ call ClearSprites ++ pop hl + call StdBattleTextbox +``` +There's not much to explain here. These changes are just to clear the sprite when we dont need it and to add the call function to the code below. + +Add this function to [engine/battle/core.asm](../blob/master/engine/battle/core.asm) +``` +GetWeatherImage: + ld a, [wBattleWeather] + and a + ret z + cp WEATHER_RAIN + ld de, RainWeatherImage + lb bc, PAL_BATTLE_OB_BLUE, 4 + jr z, .done + cp WEATHER_SUN + ld de, SunWeatherImage + ld b, PAL_BATTLE_OB_YELLOW + jr z, .done + cp WEATHER_SANDSTORM + ld de, SandstormWeatherImage + ld b, PAL_BATTLE_OB_BROWN + jr z, .done + ret + +.done + push bc + ld b, BANK(WeatherImages) ; c = 4 + ld hl, vTiles0 + call Request2bpp + pop bc + ld hl, wVirtualOAMSprite00 + ld de, .WeatherImageOAMData +.loop + ld a, [de] + inc de + ld [hli], a + ld a, [de] + inc de + ld [hli], a + dec c + ld a, c + ld [hli], a + ld a, b + ld [hli], a + jr nz, .loop + ret + +.WeatherImageOAMData +; positions are backwards since +; we load them in reverse order + db $88, $1c ; y/x - bottom right + db $88, $14 ; y/x - bottom left + db $80, $1c ; y/x - top right + db $80, $14 ; y/x - top left +``` +Request2bpp is an important function. It grabs the image from ROM and places it where you want, usually VRAM. The description of it is kind of weird, but basically `b` is the bank that the image resides, `de` is the address that the image resides, `hl` is where you want to copy it to, and `c` is how many tiles to copy. +If you're wanting to make an image a sprite, `wVirtualOAM` is where you want to go. You don't want to write directly to OAM because that would require specific timings that wouldn't be available all of the time. So, you must load the OAM data into `wVirtualOAM`. Every so often, many times per second actually, the game loads whatever is in `wVirtualOAM` into the actual OAM, when those timings I mentioned are available. +OAM data works like this, each sprite is an 8x8 tile just like the background or map tiles, but they can be put anywhere on the screen. Each sprite uses 4 bytes in this order, Y position, X position, Tile number, Attributes. Look [here](http://gbdev.gg8.se/wiki/articles/Video_Display#VRAM_Sprite_Attribute_Table_.28OAM.29) for a better description of the OAM structure. + +## Add the graphics + +Add these graphics to gfx/battle/weather + + +``` +SECTION "Battle Weather Images", ROMX + +INCLUDE "gfx/weather_images.asm" +``` + +RGBDS will add this section to any free space in a bank unless you add `"Battle WeatherImages"` to [pokecrystal.link](../blob/master/pokecrystal.link). + +## Optimize the code + +Now, if you plan on not adding any new weather effects or weather icons, optimization is straightforward. Otherwise, there's some tricks you can use to keep the code optimized. + +A quick and easy optimzation is to replace the `cp WEATHER_X` in GetWeatherImage to `dec a` like so. +```diff + GetWeatherImage: + ld a, [wBattleWeather] + and a + ret z +- cp WEATHER_RAIN ++ dec a + ld de, RainWeatherImage + lb bc, PAL_BATTLE_OB_BLUE, 4 + jr z, .done +- cp WEATHER_SUN ++ dec a + ld de, SunWeatherImage + ld b, PAL_BATTLE_OB_YELLOW + jr z, .done +- cp WEATHER_SANDSTORM ++ dec a + ld de, SandstormWeatherImage + ld b, PAL_BATTLE_OB_BROWN + jr z, .done + ret +``` + +You can do that because WEATHER_RAIN = 0 + 1, WEATHER_SUN = WEATHER_RAIN + 1, and WEATHER_SANDSTORM = WEATHER_SUN + 1. + +That format can be continued to be used if whatever new weather effects equal one more than the last. + +## Addendum + +Here is a pre-made graphic for Hail made by Bronzeswagger if you decide to add Hail to your hack. + + - [Puddles that splash when you walk](Puddles-that-splash-when-you-walk) - [Use G/S SGB palettes for maps](Use-GS-SGB-palettes-for-maps) +- [Add weather icons when selecting a move](Add-weather-icons-when-selecting-a-move) ## Assembly programming diff --git a/screenshots/hail_icon.png b/screenshots/hail_icon.png Binary files differnew file mode 100644 index 0000000..6e9b216 --- /dev/null +++ b/screenshots/hail_icon.png diff --git a/screenshots/rain_icon.png b/screenshots/rain_icon.png Binary files differnew file mode 100644 index 0000000..1c50312 --- /dev/null +++ b/screenshots/rain_icon.png diff --git a/screenshots/sand_icon.png b/screenshots/sand_icon.png Binary files differnew file mode 100644 index 0000000..f1983f1 --- /dev/null +++ b/screenshots/sand_icon.png diff --git a/screenshots/sun_icon.png b/screenshots/sun_icon.png Binary files differnew file mode 100644 index 0000000..fe8636f --- /dev/null +++ b/screenshots/sun_icon.png |