Story Screen

The story screen shows a basic story on 2 pages. Afterwards, it sends the player to the gameplay game state.

Initiating up the Story Screen

In the InitStoryState we’ll just going to turn on the LCD. Most of the game state’s logic will occur in its update function.

The text macros file is included so our story text has the proper character maps.

INCLUDE "src/main/utils/hardware.inc" INCLUDE "src/main/utils/macros/text-macros.inc" SECTION "StoryStateASM", ROM0 InitStoryState:: ; Turn the LCD on ld a, LCDCF_ON | LCDCF_BGON|LCDCF_OBJON | LCDCF_OBJ16 ld [rLCDC], a ret

Updating the Story Screen

Here’s the data for our story screen. We have this defined just above our UpdateStoryState function:

Story: .Line1 db "the galatic empire", 255 .Line2 db "rules the galaxy", 255 .Line3 db "with an iron", 255 .Line4 db "fist.", 255 .Line5 db "the rebel force", 255 .Line6 db "remain hopeful of", 255 .Line7 db "freedoms light", 255

The story text is shown using a typewriter effect. This effect is done similarly to the “press a to play” text that was done before, but here we wait for 3 vertical blank phases between writing each letter, giving some additional delay.

You could bind this to a variable and make it configurable via an options screen too!

For this effect, we’ve defined a function in our “src/main/utils/text-utils.asm” file:

DrawText_WithTypewriterEffect:: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Wait a small amount of time ; Save our count in this variable ld a, 3 ld [wVBlankCount], a ; Call our function that performs the code call WaitForVBlankFunction ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Check for the end of string character 255 ld a, [hl] cp 255 ret z ; Write the current character (in hl) to the address ; on the tilemap (in de) ld a, [hl] ld [de], a ; move to the next character and next background tile inc hl inc de jp DrawText_WithTypewriterEffect

We’ll call the DrawText_WithTypewriterEffect function exactly how we called the DrawTextTilesLoop function. We’ll pass this function which tile to start on in de, and the address of our text in hl.

We’ll do that four times for the first page, and then wait for the A button to be pressed:

UpdateStoryState:: ; Call Our function that typewrites text onto background/window tiles ld de, $9821 ld hl, Story.Line1 call DrawText_WithTypewriterEffect ; Call Our function that typewrites text onto background/window tiles ld de, $9861 ld hl, Story.Line2 call DrawText_WithTypewriterEffect ; Call Our function that typewrites text onto background/window tiles ld de, $98A1 ld hl, Story.Line3 call DrawText_WithTypewriterEffect ; Call Our function that typewrites text onto background/window tiles ld de, $98E1 ld hl, Story.Line4 call DrawText_WithTypewriterEffect ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Wait for A ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Save the passed value into the variable: mWaitKey ; The WaitForKeyFunction always checks against this vriable ld a, PADF_A ld [mWaitKey], a call WaitForKeyFunction ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Once the user presses the A button, we want to show the second page. To avoid any lingering “leftover” letters, we’ll clear the background. All this function does is turn off the LCD, fill our background tilemap with the first tile, then turn back on the lcd. We’ve defined this function in the “src/main/utils/background.utils.asm” file:

include "src/main/utils/hardware.inc" SECTION "Background", ROM0 ClearBackground:: ; Turn the LCD off xor a ld [rLCDC], a ld bc, 1024 ld hl, $9800 ClearBackgroundLoop: xor a ld [hli], a dec bc ld a, b or c jp nz, ClearBackgroundLoop ; Turn the LCD on ld a, LCDCF_ON | LCDCF_BGON|LCDCF_OBJON | LCDCF_OBJ16 ld [rLCDC], a ret

Getting back to our Story Screen: After we’ve shown the first page and cleared the background, we’ll do the same thing for page 2:

; Call Our function that typewrites text onto background/window tiles ld de, $9821 ld hl, Story.Line5 call DrawText_WithTypewriterEffect ; Call Our function that typewrites text onto background/window tiles ld de, $9861 ld hl, Story.Line6 call DrawText_WithTypewriterEffect ; Call Our function that typewrites text onto background/window tiles ld de, $98A1 ld hl, Story.Line7 call DrawText_WithTypewriterEffect ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Wait for A ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Save the passed value into the variable: mWaitKey ; The WaitForKeyFunction always checks against this vriable ld a, PADF_A ld [mWaitKey], a call WaitForKeyFunction ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

With our story full shown, we’re ready to move onto the next game state: Gameplay. We’ll end our UpdateStoryState function by updating our game state variable and jump back to the NextGameState label like previously discussed.

ld a, 2 ld [wGameState],a jp NextGameState