I wasn’t planning to post an update so soon, but this morning when I came into work I was told that my classes were cancelled for the day. This happens occasionally at the end of the school year and generally means that I have a full day at my desk to do whatever I want. I was up late last night writing my last post, so NES programming was on my mind when I woke up in the morning.

Sequences

Today’s mission was to get Sequences up and running. A Sequence is a series of monster images at the top of the screen that indicates to the player what they should whack next. I want the Sequence engine done before I start work on monsters. It doesn’t make sense to do the monsters first. The Sequence engine is like the backbone of the game.

Here’s what I needed for Sequences:

  • An init routine that selects a starting Sequence based on Level/Sublevel.
  • A routine to draw a sequence to the screen
  • A routine to close an individual Slot and advance the engine to the next monster in the Sequence. This includes some helper routines to update graphics.
  • A routine to select a (random) new Sequence after all Slots in the current Sequence are closed.

Graphics

I decided to start by drawing a 16×16 metatile to represent a closed slot. I had time, so I took my time and ended up redrawing a lot of the dummy graphics for the Sequence Indicator:

Ramses Game - Sequence Indicator Graphics

new graphics for the Sequence Indicator.

I went for a metal look to start because it is the easiest for me to draw. For the final game I want to have several tilesets for different Level themes. I’ve always sucked at art, so I was quite surprised and happy that my tiles ended up looking so good (to my eyes anyway). I’m especially proud of my keyhole.

Loading Sequences

Loading a Sequence was pretty straight forward to code. I have a table of pointers to tables of pointers to tables of pointers: Levels->Sublevels->Sequences. Once I get down to the Sequences, I choose one randomly. My random number generator is extremely basic: I merely increment a variable once per frame. So far it does the job.

Each sequence is a series of bytes representing a monster ID. Since Sequences can be of variable size (4, 5 or 6 monsters), I have a terminator ($FF) to signal to the engine when the Sequence ends. Loading a sequence copies this series of bytes (including the terminator) to an array in RAM and sets an index variable to 0.

Drawing the sequence was pretty straight-forward too. I cleverly designed the game board so that each Slot location corresponds to a 16×16 square in the bottom-right quadrant of an attribute block. This means that the only thing that differs between the 6 Slots as far as drawing is concerned is the low byte of the target PPU address. Code is so much cleaner when everything lines up like this.

Closing Slots

Since there are no monsters yet, I have the game close a Slot every time a hole is whacked. On the game logic level, all I have to do is increment the sequence index variable and check for the terminator.

Graphically it is no more complicated than drawing a monster image into a Slot. At least it shouldn’t have been, but I got greedy and added a 3-frame animation. It took me all day to finish as I had never done background animation before today, but it was good to get my hands dirty and figure it out. I learned a lot. As a final touch, I added a door-slam sound effect at the end of the animation, which incidentally forced me to code pitch envelopes for the noise channel into my sound engine. Here’s the latest video:

Conclusion

There are still some things I want to add the the Sequence engine. I want to animate the Slots opening when a new Sequence is displayed. I also need to add in some mechanism to advance Levels/Sublevels after a specified number of Sequences are cleared. What I mean is if the player is on Level 1-1, and they knock off, say 8 Sequences, it sends them to level 1-2, which would have a different set of Sequences for the engine to choose from. These features can wait for another day though, as I’m all Nintendo’d out for today.

(BTW, Google is the ultimate word-usage authority: it’s “Nintendo’d out”, not “Nintendoed out”)

In Ramses Game, monsters pop out of holes and the player needs to whack them. There are only 8 buttons on the NES controller, really 7 if you reserve Start for pausing the game. This means that if I want more than 7 holes, I need to assign the holes to combinations of buttons rather than individual buttons.

To me the most obvious way to do this is to look for combinations like up+A, down+A, left+A, right+A. Even if I reserve the Start button for pausing, that still leaves me with 12 combinations (4 each for A, B and Select). 12 holes is plenty for this kind of game, and actually due to screen space limitations I’ve decided to limit myself to 10 holes.

Detecting button combinations on the NES is a little bit tricky. I don’t want to allow the player to hold down B and spam the dpad to hit many holes very quickly. Also, if the player presses up+left at the same time while pressing B, I don’t want two holes to be hit simulataneously. On the other hand, it would be unreasonable to expect the player to hit two buttons at once in the exact same frame. Nobody is that fast. So I have to allow some leeway. With that in mind, here is how my Button Combo routine works.

Button Combo Routine

Output

My button combo routine takes what the user has pressed and outputs a value 0-12. The output possibilities are laid out like this:

  • 0: no combination was pressed.
  • 1-4: B+dpad was pressed (in order: up, down, left, right)
  • 5-8: A+dpad
  • 9-12: Select+dpad

Each of these values is mapped to a hole, and I use the outputted value to index into hole-related tables. For example, here is a table that I use to determine if a valid hole was whacked:

valid_holes:
    .byte 0             ;unused (no combo)
    .byte 1, 1, 1, 1    ;B (up, down, left, right order)
    .byte 1, 1, 1, 1    ;A
    .byte 1, 1, 0, 0    ;Select
    .byte 0, 0, 0       ;unused (select+left, select+right unused)

I have tables for attribute table PPU addresses and the like as well.

Input

When I read the controller every frame, I store two sets of data in RAM. One is the current button states (pressed or not pressed), which I store in a variable called joypad1. The other is off-to-on transitions, ie what was unpressed last frame but is pressed this frame. Off-to-on transitions are stored in a variable called joypad1_pressed.

Each variable is one byte, basically a bitflag with each bit corresponding to a button. My controller reading routine stores button information in this order:

joypad1 and joypad1_pressed bits:

76543210
||||||||
|||||||+- right
||||||+-- left
|||||+--- down
||||+---- up
|||+----- start
||+------ select
|+------- B
+-------- A

Logic

The first thing I do in my button combo routine is to check if A, B or select is pressed. If not, obviously we can’t have a combo, so skip to the end.

;---------------------------------------------------
; check for dpad+button combos
.proc check_combos
    lda joypad1
    and #%11100000      ;isolate A, B, select
    beq @somewhere_near_the_end
    ;....snip

If a button is pressed, I want to grab its combo value and store it in RAM:

.proc check_combos
    lda joypad1
    and #%11100000      ;isolate A, B, select
    beq @clear_btn_val  ;if not pressed, clear btn_val
    lda joypad1_pressed
    and #%11100000      ;if off_to_on, we need to set the flag, else skip to dpad check
    beq @check_dpad
@set_btn_val:
    asl                 ;shift the A button bit to the CF
    bcc @B
    lda #$05            ;if A bit is set, store 5 in btn_flag  (5, 6, 7, 8 = A combo)
    bne @store
@B:
    asl                 ;shift the B button bit to the CF
    bcc @Select
    lda #$01            ;else if B bit is set, store 1 in btn_flag (1, 2, 3, 4 = B combo)
    bne @store
@Select:
    lda #$09            ;else Select bit must be set, so store 9 in btn_flag (9, 10, 11, 12 = Select combo)
@store:
    sta btn_val         ;add dpad value to this to get index
@check_dpad:
    ;.....snip

@clear_btn_val:
    lda #$00
    sta btn_val
@end:
    rts
.endproc
    

Notice that I check if the button is newly pressed or if it was held from last frame. This check is for a special case. Say the user is holding A. Then say a monster they want to smack appears in the up+B hole. The player will press up+B, but there is a chance that there will be several frames of A+B as the player slides their thumb from A to B. I want to catch the newest button press (B), not the older one (A). So I check joypad1_pressed. If a button is newly pressed this frame, I set btn_val. If not, I skip straight to the dpad (btn_val having been set in a previous frame).

To say it another way, I only alter the value of btn_val in two cases: when a new button is pressed, or when no buttons are pressed. This is important for another case too, which I will get to in a moment.

Note that if on the off-chance that B, A or Select are newly pressed simultaneous in the same frame, A takes precedence over B, which takes precedence over Select. Not going to happen often, and when it does it’s not a big deal – the player will know they mashed both buttons.

Finally we check the dpad to complete the combo:

@check_dpad:
    lda btn_val
    beq @end            ;if A, B, Select not pressed, no combo
    lda joypad1
    and #%00001111      ;isolate dpad
    beq @end            ;if no arrows pressed, no combo
    tay
    lda dpad_add, y     ;else, grab arrow value from table (up = 0, down=1, left=2, right=3)
    clc
    adc btn_val         ;add arrow value to button value.  Results in a number 1-12
    sta joypad1_combo
    jsr do_button_combo
@clear_btn_val:
    lda #$00
    sta btn_val
@end:
    rts

First thing I check is if btn_val is 0. But if we made it this far, shouldn’t this be non-zero? The player is definitely holding down either A, B or Select afterall. Yes they are, but btn_val could still be zero. After a button combo is registered, I process the combo via do_button_combo and then I clear btn_val. This check for btn_val == 0 covers the case that a button combination was recently processed (say last frame), but the player hasn’t released the buttons yet. It took me some bug-hunting before I realized I needed this check. Button Combinations are tricky, aren’t they?

The rest is pretty straightforward. I check the dpad. If no arrow is pressed, there is no combo so I return. If an arrow is pressed, I grab its value from a table and add it to btn_val to get the final combo value. The reason for the dpad_add table is to protect against cases of multiple arrows being pressed at the same time. If up+left is pressed, for example, I resolve it to up. If left+right is pressed, I resolve it to left. If you’re curious, my table looks like this:

;this table maps each possible d-pad combination to a single d-pad direction
;   0 = up, 1 = down, 2  = left, 3 = right
dpad_add:
    .byte 0     ;unused (will never be read)
    .byte 3     ;r -> right
    .byte 2     ;l -> left
    .byte 2     ;r+l -> left
    .byte 1     ;d -> down
    .byte 1     ;d+r -> down
    .byte 1     ;d+l -> down
    .byte 1     ;d+r+l -> down
    .byte 0     ;u -> up
    .byte 0     ;u+r -> up
    .byte 0     ;u+l -> up
    .byte 0     ;u+r+l -> up
    .byte 0     ;u+d -> up
    .byte 0     ;u+d+r -> up
    .byte 0     ;u+d+l -> up
    .byte 0     ;u+d+r+l -> up

Having this in table form makes it easy to modify in the future if I need to tweak some of the values (poor right arrow gets overruled a lot, doesn’t he?). If you want to know more about this technique, I have written about protecting against odd dpad combinations using tables before.

That’s it. It’s a little complicated but it works. I haven’t optimized this routine, so it’s possible that I could improve it somehow. I’d rather move forward though, since this works fine the way it is.

Incidentally, the player is allowed to hold a dpad arrow and spam A/B/Select. Doing so is of such limited use that I don’t see it being abusive. If testing reveals otherwise though, I’ll rewrite the routine to protect against that.

Full Routine

Here’s the full routine in case anyone wants to copy/paste it into their game. If you do, I will feel really happy if you mention me in the credits somewhere. :)

;---------------------------------------------------
; check for dpad+button combos
.proc check_combos
    lda joypad1
    and #%11100000      ;isolate A, B, select
    beq @clear_btn_val  ;if not pressed, clear btn_val
    lda joypad1_pressed
    and #%11100000      ;if off_to_on, we need to set the flag, else skip to dpad check
    beq @check_dpad
@set_btn_val:
    asl                 ;shift the A button bit to the CF
    bcc @B
    lda #$05            ;if A bit is set, store 5 in btn_flag  (5, 6, 7, 8 = A combo)
    bne @store
@B:
    asl                 ;shift the B button bit to the CF
    bcc @Select
    lda #$01            ;else if B bit is set, store 1 in btn_flag (1, 2, 3, 4 = B combo)
    bne @store
@Select:
    lda #$09            ;else Select bit must be set, so store 9 in btn_flag (9, 10, 11, 12 = Select combo)
@store:
    sta btn_val         ;add dpad value to this to get index
@check_dpad:
    lda btn_val
    beq @end            ;if A, B, Select not pressed, no combo
    lda joypad1
    and #%00001111      ;isolate dpad
    beq @end            ;if no arrows pressed, no combo
    tay
    lda dpad_add, y     ;else, grab arrow value from table (up = 0, down=1, left=2, right=3)
    clc
    adc btn_val         ;add arrow value to button value.  Results in a number 1-12
    sta joypad1_combo
    jsr do_button_combo
@clear_btn_val:
    lda #$00
    sta btn_val
@end:
    rts
.endproc

;this table maps each possible d-pad combination to a single d-pad direction
;   0 = up, 1 = down, 2  = left, 3 = right
dpad_add:
    .byte 0     ;unused
    .byte 3     ;r -> right
    .byte 2     ;l -> left
    .byte 2     ;r+l ->left
    .byte 1     ;d -> down
    .byte 1     ;d+r -> down
    .byte 1     ;d+l -> down
    .byte 1     ;d+r+l -> down
    .byte 0     ;u -> up
    .byte 0     ;u+r -> up
    .byte 0     ;u+l -> up
    .byte 0     ;u+r+l -> up
    .byte 0     ;u+d -> up
    .byte 0     ;u+d+r -> up
    .byte 0     ;u+d+l -> up
    .byte 0     ;u+d+r+l -> up

Conclusion

So button combinations are done with, and if you watched the video embedded in the last post you will see that they work quite well! This game is really coming along.

I mentioned in my previous post that I have started a new project. I learned a lot about code organization since the last time I worked on Explorer and I wanted to start fresh. This project isn’t as ambitious as Explorer is, so I should be able to complete it more quickly and build my nesdev skills.

Ramses Game

The new game is tentatively titled Ramses Game. It’s a single screen action/puzzle game with a cutscene-driven storyline. I’m using ca65 to assemble and the UNROM mapper.

Story

The story of the game goes like this:

Ramses (the hero) was kidnapped from his home by space pirates and sold at a slave auction in the Artajian system to a cruel master named Bonehammer. Now he finds himself on a monster-infested planet, trapped in a strange prison with a bomb strapped to his chest. He sees a hammer in the corner of the room. Curious, he picks up the hammer and the game for his life begins…

Gameplay

I got the idea to make Ramses Game while I was playing Dragon Quest V on the DS. There is a mini-game in DQV called Slime Smack, which is basically a touch-pen version of Whack-a-mole game with slimes:

Ramses Game has a very similar concept. The flow of gameplay looks like this:

There are a series of HOLES. CREATURES come out of the holes. You whack them in the SEQUENCE indicated before the TIMER runs out.

Successfully whacking all CREATURES in a SEQUENCE will add time to the TIMER and bring up a new SEQUENCE. Successfully completing a series of SEQUENCES (7-10?) will advance you to the next AREA.

If the TIMER ever reaches zero, you lose a LIFE. If you lose all your LIVES, game over.

Ramses Game will differ from Slime Smack some key areas though:

  1. You use an NES controller instead of a touch-pen. This is why I was working on up+B, down+A button combinations.
  2. A much larger variety of monsters with different abilities. I have a design document full of monster ideas that will make the game more fun and challenging.
  3. Multiple area themes, with matching monsters.
  4. Possibly bosses at the end of each area.
  5. Difficulty curve: at the beginning of the game there are eight holes and sequences of four monsters. By the end there will be ten holes and sequences of six monsters.
  6. Cutscene-driven storyline to give the game more depth and color.

Progress

I’ve made quite a bit of progress in the few days I’ve been working on it. I have a placeholder gameboard that displays. I have input-reading routines that successfully detect button combinations. When you whack a hole on the gameboard, you get a visual and audio cue. I made some dummy monster images that display up in the sequence indicator. Everything is coming along nicely. Here is a video of current gameplay:

I’ll post some code snippets next post.