Now that I have some test rooms and can navigate between them, it’s time to stick a sprite in the game. I couldn’t draw a rock to save my life, much less a cool character sprite, so for now I am going to rip one from another game to use for testing. Here she is:
She's from The Guardian Legend.
This is the sprite from The Guardian Legend. I chose her as my test sprite for a few reasons:
- Her dimensions. She is 16×32, which is the size I want for my game’s hero sprite.
- Her proportions. Specifically her feet. I have narrow 16 pixel passages that the player will need to fit through. I want to allow a small amount of left-to-right and up-to-down movement within those 16 pixel hallways. If the sprite is too fat it will look like they are stomping on the walls.
- Her directions. She can face 8 different directions, which is what I want for my game.
- Her animation. She has a 4-frame animation that looks smooth and is CHR-efficient. Something I want to imitate.
Getting a sprite onscreen
First things first I need some variables for the hero. Right off the bat I know I will need to track her coordinates and direction:
.segment "ZP": zeropage
hero_x: .res 1 ;based on top left of sprite
hero_y: .res 1
hero_direction: .res 1
Next I will need to initialize those variables. This subroutine will be called when the game engine is loaded:
;direction indexes for tables
SPRITE_UP = $00
SPRITE_DOWN = $01
SPRITE_LEFT = $02
SPRITE_RIGHT = $03
SPRITE_UP_LEFT = $04
SPRITE_UP_RIGHT = $05
SPRITE_DOWN_LEFT = $06
SPRITE_DOWN_RIGHT = $07
initialize_hero:
lda #$50 ;place her somewhere on the map
sta hero_x
sta hero_y
lda #SPRITE_DOWN
sta hero_direction
jsr update_hero_sprite
rts
The hero will have a different appearance based on the direction she is facing. I will have lookup tables to find which CHR tile number to use. I index into these tables with a direction index. Those constants at the top define the direction indexes (indices? whatever).
update_hero_sprite is a routine that will be called every frame. It’s job will be to calculate the sprites’ x, y, tile number and flip/palette settings and store them in RAM. Later, in the NMI we will copy those values to the PPU (Picture Processing Unit) using DMA transfer.
Speaking of which, the hero sprite is actually made up of 4 sprites. On the NES, you have a choice between 8×8 sprites and 8×16 sprites. I will be using 8×16 sprites. The hero is 16×32, which is 4 8×16 sprites:
This character sprite is actually made up of 4 8x16 sprites
So let’s get her on the screen:
update_hero_sprite:
lda hero_direction
tax ;we use this index to read from tables
lda #hero_top_left ;sprite number.
asl
asl ;each sprite has 4 bytes of data
tay ;we use this index to write sprite data to RAM
;sprite data is stored, in order: y, tile #, attrib, x
lda hero_y
sta sprite_RAM, y
lda hero_x
sta sprite_RAM+3, y
lda sprite_tiles_top_left, x
sta sprite_RAM+1, y
lda hero_sprite_flips, x ;right, up_right and down_right
;are just flips of left, up_left
;and down_left. Flip values are
; stored in a table
sta sprite_RAM+2, y
lda #hero_top_right ;top right, sprite #
asl
asl
tay
lda hero_y
sta sprite_RAM, y
lda hero_x
clc
adc #$08 ;8 pixels to the right of the top left sprite
sta sprite_RAM+3, y
lda sprite_tiles_top_right, x
sta sprite_RAM+1, y
lda hero_sprite_flips, x
sta sprite_RAM+2, y
lda #hero_bottom_left ;bottom left, sprite #
....
;etc. add 16 to hero_y for the bottom two sprites
rts
And in the NMI:
;sprite DMA transfer
bit $2002
lda #$00
sta $2003
lda #>sprite_RAM
sta $4014
And she’s on the screen!
She's wearing green today.
Conclusion
Today’s post was short and sweet. Getting the hero sprite on the screen was pretty easy. My next step is to change her direction based on joypad input. See you then!










