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!

Thomas,
I know this is jumping the gun a bit, but it’d be great if you could devote a future post to the overall structure of your game design. I know that’s a general subject, but it’d be great to see something catered to the peculiarities of the NES. For instance, how do you switch from title screen to the game, then to an end state? Where do those things go in code? What is the main loop and what happens there? Those are the kind of concepts I find confusing.
This is fascinating to read so far. No one’s done a step-by-step design doc like this for NES before, especially for an actual multi-screen game. Nice work.
@noattack: Sure! I plan to cover just about anything I can think of and those topics make the list. I don’t have a title screen or ending yet, so I haven’t written any state-changing code. But when I do, I’ll write about it for sure.
I’m trying to write blog entries as I program the game so the ideas are still fresh in my mind when I write. I’m still playing catchup though. My game engine already has sprite movement with background collision working. I’m itching to make a new video and put it up, but I’m going to wait until the blog posts catch up to that point. Also I haven’t talked about sound at all, but I have a basic music engine working in the game. I’ll get there eventually though.
In the meantime, I recommend this document by Disch:
http://nesdevhandbook.googlepages.com/index.html
Looks like you commented in the thread over at nesdev, so you’ve probably read it already, but it’s worth reading several times. I pretty much follow his program structure verbatim, except that I don’t buffer the room drawing (I turn the PPU off).
Here’s my main loop so far:
forever:
jsr do_frame ;see Disch’s doc
jsr handle_joypad
jsr update_hero_sprite
jmp forever
handle_joypad checks for arrow presses. If there are any, it sets a hero_moving flag and sets her direction. update_hero_sprite does the actual movement, checking for collisions and changing rooms if the hero reaches a room boundary. It also cycles the sprite animations.
Thanks for the kind words!
[...] Tummai Games development blog for NES games « Explorer: 7 – Sprite Time [...]
Noattack! Yet another person I’ve had the pleasure of actually meeting : D Great to see you are still interested in NES dev, dude!
http://nesdevhandbook.googlepages.com/index.html seems to be a broken link as it prompts me to download the html file instead of opening it… :-(
Googlepages changed somehow in between now and when I wrote this post. I don’t know how to get to the page to display as-is in the browser. index.html only gives you a table of contents. For the meat, try http://sites.google.com/site/nesdevhandbook/theframe.html (you will still have to download the html and view it locally. Formatting appears a little broken).
I should contact Disch and see if he’ll let me host a copy of his document here.