Show an icon for the current weather - pret/pokecrystal GitHub Wiki
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.
Contents
1. Add the code to display the sprites
Edit engine/battle/core.asm:
BattleTurn:
...
.skip_iteration
call ParsePlayerAction
+ push af
+ call ClearSprites
+ pop af
jr nz, .loop1
MoveSelectionScreen:
...
.battle_player_moves
call MoveInfoBox
+ call GetWeatherImage
ld a, [wSwappedMove]
...
.place_textbox_start_over
+ push hl
+ call ClearSprites
+ pop hl
call StdBattleTextbox
...
These changes are just to clear the sprite when we don't need it and to add the call function to the code below.
Add this function in the same file:
+GetWeatherImage:
+ ld a, [wBattleWeather]
+ and a
+ ret z
+ ld de, RainWeatherImage
+ lb bc, PAL_BATTLE_OB_BLUE, 4
+ cp WEATHER_RAIN
+ jr z, .done
+ ld de, SunWeatherImage
+ ld b, PAL_BATTLE_OB_YELLOW
+ cp WEATHER_SUN
+ jr z, .done
+ ld de, SandstormWeatherImage
+ ld b, PAL_BATTLE_OB_BROWN
+ cp WEATHER_SANDSTORM
+ ret nz
+
+.done
+ push bc
+ ld b, BANK(WeatherImages) ; c = 4
+ ld hl, vTiles0
+ call Request2bpp
+ pop bc
+ ld hl, wShadowOAMSprite00
+ 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 image's bank, de
is the image's address in memory, hl
is where you want to copy it to, and c
is how many tiles to copy.
If you want to convert an image into 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 for a better description of the OAM structure.
2. Add the graphics
Create gfx/battle/weather and add these graphics:
Create a new file called gfx/weather_images.asm:
+WeatherImages::
+
+RainWeatherImage:
+INCBIN "gfx/battle/weather/rain_icon.2bpp"
+
+SunWeatherImage:
+INCBIN "gfx/battle/weather/sun_icon.2bpp"
+
+SandstormWeatherImage:
+INCBIN "gfx/battle/weather/sand_icon.2bpp"
And add this section to main.asm:
+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 Weather Images"
to layout.link and specify in which bank it should be placed.
3. 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.
GetWeatherImage:
ld a, [wBattleWeather]
and a
ret z
ld de, RainWeatherImage
lb bc, PAL_BATTLE_OB_BLUE, 4
- cp WEATHER_RAIN
+ dec a
jr z, .done
ld de, SunWeatherImage
ld b, PAL_BATTLE_OB_YELLOW
- cp WEATHER_SUN
+ dec a
jr z, .done
ld de, SandstormWeatherImage
ld b, PAL_BATTLE_OB_BROWN
- cp WEATHER_SANDSTORM
+ dec a
ret nz
You can do this because WEATHER_RAIN
= 1, WEATHER_SUN
= WEATHER_RAIN
+ 1, and WEATHER_SANDSTORM
= WEATHER_SUN
+ 1. For more info, check out how to optimize assembly code in general.
That format can be continued to be used if whatever new weather effects equal one more than the last.
4. Addendum
Here is a pre-made graphic for Hail made by Bronzeswagger if you decide to add Hail to your hack.