Ok, I got the hero to change directions based on user input. Now it’s time to move her. The first step for this is to have a hero_moving flag that the input handler will set if there is d-pad input:
hero_moving: .res 1
handle_joypad:
lda joypad1
and #$F0
beq @end
lsr
lsr
lsr
lsr
tay
lda direction_change_table, y
sta hero_direction
lda #$01
sta hero_moving
rts
@end:
lda #$00
sta hero_moving
rts
With this updated input handler, the hero_moving flag will be 1 when the d-pad is pressed, and 0 when it is not. And as before, our hero’s direction will be stored in hero_direction.
Next, I need to check the hero moving flag in my update_hero_sprite routine, which is called every frame:
update_hero_sprite:
lda hero_moving
beq @hero_moving_done
jsr move_hero
@hero_moving_done:
;...
;write sprite data to RAM as before
Now that I have the foundation laid, I need to write the move_hero routine.
move_hero
There are 8 possible directions the hero could be facing. The current direction is stored in a variable called hero_direction. The possible values for this variable are 0-7, as assigned by these constants:
;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
I need to alter the hero’s coordinates based on the direction the player is moving. If they are moving left, I need to subtract from hero_x. If they are moving right, I need to add to hero_x. If they are moving up, I need to subtract from hero_y. If they are moving down, I need to add to hero_y. If they are moving diagonally, I need to update both hero_x and hero_y. There are many possibilities, and rather than have a million branch instructions, I’ll use table lookups again. I will have one table for horizontal movement and one table for vertical movement. I will index into these tables using hero_direction. The tables look like this:
;up, down, left, right, up_left, up_right, down_left, down_rt
hero_movement_x:
.byte $00, $00, $FF, $01, $FF, $01, $FF, $01
hero_movement_y:
.byte $FF, $01, $00, $00, $FF, $FF, $01, $01
My move_hero routine will read from these tables and add to the hero coordinates. Note that adding $FF to a number (on an 8-bit system) is the same as subtracting 1, since it will wrap around from $FF to $00. Here is move_hero:
move_hero:
ldy hero_direction
lda hero_movement_x, y
clc
adc hero_x
sta hero_x
ldy hero_direction
lda hero_movement_y, y
clc
adc hero_y
sta hero_y
rts
And now she’s moving.
miau pointed out in a comment that diagonal movement should really alter x and y by SQRT(2) rather than 1 (see Pythagorean Theorum). This is something I didn’t consider before, so my hero covers ground a little more quickly when moving diagonally. I’m not sure yet if this is undesirable behavior or not. If I keep it a simple maze-solving game, it probably won’t be an issue. If I get more ambitious and change it to a more action-oriented game with enemies (something I’ve been seriously thinking about), it may be an issue. We’ll see :).
Animation
I want to talk very briefly about animating the sprite. To do animation, I need a few things:
- Graphics for the various frames of animation
- A counter to tell me when to change animation frames
- A variable telling me the current animation frame
I already have the graphics for my test sprite. The other two I need to make myself.
frame_counter: .res 1
hero_anim_frame: .res 1
The animation is a walking animation, so I don’t want the hero to animate unless she is moving. It makes sense then to do the animation frame-changing logic in the move_hero routine. The Guardian Legend hero sprite has a 4-frame walking animation, so here’s how I do it:
move_hero:
ldy hero_direction
lda hero_movement_x, y
clc
adc hero_x
sta hero_x
ldy hero_direction
lda hero_movement_y, y
clc
adc hero_y
sta hero_y
inc frame_counter
lda frame_counter
cmp #$0B ;change anim frame every 11 "moving frames"
;found this number by trial and error
bcc @end
lda #$00
sta frame_counter ;reset counter
inc hero_anim_frame ;go to next anim frame
lda hero_anim_frame ;make sure we stay between 0 and 3
and #$03
sta hero_anim_frame
@end:
rts
Then I will modify my CHR tile lookup tables to handle graphics for all four frames of animation for all 8 directions. Then I will update my update_hero_sprite routine to read from these tables based on the values of hero_anim_frame and hero_direction. I’m not going to post the code, because it’s a little long and there are a lot of tables. If anybody wants me to elaborate more, let me know in the comments :)
BTW, before I forget! When adding new variables, it’s a good idea to initialize them. Here is my updated initialize_hero_sprite routine:
initialize_hero_sprite:
lda #$50
sta hero_x
sta hero_y
lda #$00
sta hero_moving
sta hero_anim_frame
sta frame_counter
lda #SPRITE_DOWN
sta hero_direction
jsr update_hero_sprite
rts
Conclusion
Whew. I covered a lot of ground today. I probably should have made this two posts instead of one, but I want to hurry up and get to collision detection so I can put up the next demo video. :)
You may have noticed by now that I use hero_direction a lot to index into lookup tables. This is because everything changes based on the hero’s direction, and lookup tables are a great alternative to long sections of compare/branch code. Often when I find myself writing a lot of branching code I’ll see if I can come up with some scheme to turn the test value into a table index.
See you next time!

