[4.5.9] Make a menu screen using tables (level select screen, or anything else)

SciNEStist

Well-known member
Here is a of a method for creating a menu in your game that can be used for anything. It will allow you to toggle between items in a menu with the select button, and choose the option with a start button. It will highlight which item in the menu is chosen by drawing an 8X8 sprite around the option we have selected.

The advantages of this method is that you can make your options appear anywhere on the screen, so you are not confined to a single line going up and down or left and right. you can make a grid of options, you could make a columns of options, or even spatter your menu choices randomly around the screen. This is not a beginner tutorial, please have a general idea on how to work with nesmaker before we start.

for this example, we will make the menu a level select screen.

step 1: draw a menu screen.
The options in the menu can be placed anywhere on the screen, in any order. so no worries about lining them up in a grid, you can get creative with the placement. you can have up to hundreds of options if you wish, as long as they all fit on 1 screen. I recommend using an 8X8 screen for this, but its not needed.

you will want to set this screen to a separate gamestate than your regular gameplay screens. I would suggest a "menu" gamestate

here's an example:
menututorial.png


step 2: map out where your cursor will show up

for this, we are going to create 2 tables. one for the X position, and 1 for the Y position.

for each entry, we will be writing the coordinates down in order you want to switch between. in my example, i want an arrow to show up above the centre of each line. so I'm going to record down the x and y coords of each spot.

option 1: x=80 , y = 56
option 2: x=160 , y = 56
option 3: x=80 , y = 80
option 4: x=160 , y = 80
option 5: x=80 , y = 104
..etc

so we add them in the table like so:


menuxpos:
.db 80,160,80,160,80
menuypos:
.db 56,56,80,80,104

for my example, the completed list will look like this:

Code:
menuxpos:
    .db 80,160,80,160,80,160,80,160,120,120
menuypos:
    .db 56,56,80,80,104,104,128,128,152,176

these lines can be saved in a lot of places, but Nesmaker already has a designated spot for tables called "extra tables" found in scripts>Defined Scripts>Game>Extra Tables

go ahead and add the 4 lines to the bottom of that script.

Step 3: draw a select cursor.
Could be an arrow, or just a circle, whatever you like. For our example, we will draw it in the 2nd last tile of gameobjects, which is tile #$7E

Step 4: add a user variable

in the Project settings window under the User variables tab, we are going to add a user variable "optionselected" set it's value to 0

Step 5: add a script to draw the cursor

we can add this stuff into scripts>Defined Scripts>Game> Sprite Pre-Draw

Code:
LDA gameState
CMP #$01 ; is this the menu gamestate? (change if your gamestate is a different number)
BEQ +
    JMP +skipmenu ; if not, we are done
+
LDY optionselected;get the current value of our user variable
LDA menuxpos,y ;get the x position of the current optionselected
STA tempx
LDA menuypos,y ;get the y position of the current optionselected
STA tempy
DrawSprite tempx, tempy, #$7E, #%00000000  ;  draws our sprite in the correct x and y position.
+skipmenu

you can change the args to suit your needs, like the sprite tile # or the attribute data (in case you want to use a different palette or flip the spite horizontally or vertically)

the way this works is by using the "optionselected" variable to control which value we pull out of the tables, so if the optionselected variable is set to 5, then we pull the sixth item in our tables (sixth because we start counting at 0) and use them as our args for our Drawsprite command.

At this point if we ran your game, you will see on the menu screen the first option to be highlighted, but we havent done anything to allow you to toggle between options, and we havent done anything to make things happen when you choose an option. so here we go

Step 6: configure the select button to toggle between the menu items.

We will need to create a new script for this. In our example, we will use select to cycle between the options.

Code:
; IF YOU HAVE A SELECT SOUND, UNCOMMENT THE NEXT LINE:
;PlaySound #sfx_select

LDA optionselected ; get the current option setting
CMP #$09 ; SET THIS NUMBER TO 1 LESS THAN THE NUMBER OF MENU OPTIONS YOU HAVE ON YOUR SCREEN
BNE +
    LDA #$00
    STA optionselected ; if we are at the last option, go back to 0
    RTS
+
INC optionselected ; if we arent at the last option, increase the variable by 1
RTS

save this script as something like "menuselect.asm" into your and put it somewhere in your "GameEngineData\Routines\BASE_4_5\Game\" folder I like to make a customscripts folder, but you can place it anywhere

We now add the script to Scripts>Input Scripts, then we use the input editor to add in the control.

the options you want to select are:

Game State: menu
target: player
Controller1
Script to run: menuselect.asm
Press
select

Now if you run the game, your menu screen should allow you to keep tapping select and it will cycle through all the options, then go back to the first option when you get to the end.
If the cursor goes wild when going through these options, you have either set up your coordinate tables wrong (step 2) or you didnt set the number in the select script to 1 less than your amount of options (step 6)

But now we need to have something actually happen when you press start.

Step 7 : Make a script that does an action when pressing start

Method 1:

if you want to get a little more custom with what happens for each selection, here is a way of doing that:

Code:
LDA optionselected
CMP #$00 ;this is the first option, since tables start counting at 0
BNE +
    ;script whatever you want to happen during option 1 here, maybe play a sound, warp to a screen, change a user variable, whatever you want
    RTS
+
CMP #$01 ;this is the 2nd option, since tables start counting at 0
BNE +
    ;script whatever you want to happen during option 2 here, maybe play a sound, warp to a screen, change a user variable, whatever you want
    RTS
+
CMP #$02 ;this is the 3rd option, since tables start counting at 0
BNE +
    ;script whatever you want to happen during option 3 here, maybe play a sound, warp to a screen, change a user variable, whatever you want
    RTS
+
RTS

For something like that, you will have to add another section for each menu option you have on the screen. (i only provided space for the first 3 options. you just have to add more) But what if you only want to make a screen warp and have a lot of options? there is a more efficient way for that, and it's to use another table:

Method 2 :

First, we will need a list of screen #s to warp to. Let's go back to the example screen where I set up 10 levels.

Our table is going to be a list of the screen numbers for each level. to make out lives easier, we will use Hex values for the screens, as there is an easy trick to finding the correct screen on your map:

If you hover over your level 1 screen on your overworld map screen, it will show you "X=# Y=#" in the top left.

my level 1 screen is X=1 Y=4

so you switch it around to YX and add "#$" to the start

my screen number for level 1 is "#$41"

if level 2 is on screen X=5 Y=8, then my screen number for level 2 is "#$85"
if level 3 is on screen X=11 Y= 5, then it gets a bit trickier, 11 is B. since in hex, we count 0-15 this way : 0123456789ABCDEF. my screen for level 3 is "#$5B"

so complete a list in order, and you will have something like this (use your own values, don't just copy/paste this)
Code:
menuscreens:
    .db #$41,#$85,#$5B,#$6A,#$88,#$A6,#$4D,#$3F,#$D3,#$53

notice that I have the EXACT same amount of numbers in this table as I have options in my menu.

post your new table right under where we did our X and Y coord tables in scripts>Defined Scripts>Game>Extra Tables

Now we will use that table to warp to our chosen screens by pressing start with this script:

Code:
LDY optionselected
LDA menuscreens,y
STA tempx
WarpToScreen #$00, tempx, #$01
;change the first arg to #$01 if you want to warp to the Underworld)
RTS

For whichever method you choose, save that script as "menustart.asm" and save it to the same place you saved "menuselect.asm"

Now you add that script under Scripts>Input Scripts and we go to the Input Editor and configure our new script to work with our Start Button

Game State: menu
target: player
Controller1
Script to run: menustart.asm
Release
start

Notice how we set it to release instead of press? this can help with some glitchiness in some cases.


Once that is done, It should now warp to the screen you choose when hitting start!


Now you are done!!
please let me know If I need to clarify any steps on this tutorial. or if you have any questions.
 
Last edited:

NightMusic

Member
Here is a of a method for creating a menu in your game that can be used for anything. It will allow you to toggle between items in a menu with the select button, and choose the option with a start button. It will highlight which item in the menu is chosen by drawing an 8X8 sprite around the option we have selected.

The advantages of this method is that you can make your options appear anywhere on the screen, so you are not confined to a single line going up and down or left and right. you can make a grid of options, you could make a columns of options, or even spatter your menu choices randomly around the screen. This is not a beginner tutorial, please have a general idea on how to work with nesmaker before we start.

for this example, we will make the menu a level select screen.

step 1: draw a menu screen.
The options in the menu can be placed anywhere on the screen, in any order. so no worries about lining them up in a grid, you can get creative with the placement. you can have up to hundreds of options if you wish, as long as they all fit on 1 screen. I recommend using an 8X8 screen for this, but its not needed.

you will want to set this screen to a separate gamestate than your regular gameplay screens. I would suggest a "menu" gamestate

here's an example:
View attachment 7269


step 2: map out where your cursor will show up

for this, we are going to create 2 tables. one for the X position, and 1 for the Y position.

for each entry, we will be writing the coordinates down in order you want to switch between. in my example, i want an arrow to show up above the centre of each line. so I'm going to record down the x and y coords of each spot.

option 1: x=80 , y = 56
option 2: x=160 , y = 56
option 3: x=80 , y = 80
option 4: x=160 , y = 80
option 5: x=80 , y = 104
..etc

so we add them in the table like so:


menuxpos:
.db 80,160,80,160,80
menuypos:
.db 56,56,80,80,104

for my example, the completed list will look like this:

Code:
menuxpos:
    .db 80,160,80,160,80,160,80,160,120,120
menuypos:
    .db 56,56,80,80,104,104,128,128,152,176

these lines can be saved in a lot of places, but Nesmaker already has a designated spot for tables called "extra tables" found in scripts>Defined Scripts>Game>Extra Tables

go ahead and add the 4 lines to the bottom of that script.

Step 3: draw a select cursor.
Could be an arrow, or just a circle, whatever you like. For our example, we will draw it in the 2nd last tile of gameobjects, which is tile #$7E

Step 4: add a user variable

in the Project settings window under the User variables tab, we are going to add a user variable "optionselected" set it's value to 0

Step 5: add a script to draw the cursor

we can add this stuff into scripts>Defined Scripts>Game> Sprite Pre-Draw

Code:
LDA gameState
CMP #$01 ; is this the menu gamestate? (change if your gamestate is a different number)
BEQ +
    JMP +skipmenu ; if not, we are done
+
LDY optionselected;get the current value of our user variable
LDA menuxpos,y ;get the x position of the current optionselected
STA tempx
LDA menuypos,y ;get the y position of the current optionselected
STA tempy
DrawSprite tempx, tempy, #$7E, #%00000000  ;  draws our sprite in the correct x and y position.
+skipmenu

you can change the args to suit your needs, like the sprite tile # or the attribute data (in case you want to use a different palette or flip the spite horizontally or vertically)

the way this works is by using the "optionselected" variable to control which value we pull out of the tables, so if the optionselected variable is set to 5, then we pull the sixth item in our tables (sixth because we start counting at 0) and use them as our args for our Drawsprite command.

At this point if we ran your game, you will see on the menu screen the first option to be highlighted, but we havent done anything to allow you to toggle between options, and we havent done anything to make things happen when you choose an option. so here we go

Step 6: configure the select button to toggle between the menu items.

We will need to create a new script for this. In our example, we will use select to cycle between the options.

Code:
; IF YOU HAVE A SELECT SOUND, UNCOMMENT THE NEXT LINE:
;PlaySound #sfx_select

LDA optionselected ; get the current option setting
CMP #$09 ; SET THIS NUMBER TO 1 LESS THAN THE NUMBER OF MENU OPTIONS YOU HAVE ON YOUR SCREEN
BNE +
    LDA #$00
    STA optionselected ; if we are at the last option, go back to 0
    RTS
+
INC optionselected ; if we arent at the last option, increase the variable by 1
RTS

save this script as something like "menuselect.asm" into your and put it somewhere in your "GameEngineData\Routines\BASE_4_5\Game\" folder I like to make a customscripts folder, but you can place it anywhere

We now add the script to Scripts>Input Scripts, then we use the input editor to add in the control.

the options you want to select are:

Game State: menu
target: player
Controller1
Script to run: menuselect.asm
Press
select

Now if you run the game, your menu screen should allow you to keep tapping select and it will cycle through all the options, then go back to the first option when you get to the end.
If the cursor goes wild when going through these options, you have either set up your coordinate tables wrong (step 2) or you didnt set the number in the select script to 1 less than your amount of options (step 6)

But now we need to have something actually happen when you press start.

Step 7 : Make a script that does an action when pressing start

Method 1:

if you want to get a little more custom with what happens for each selection, here is a way of doing that:

Code:
LDA optionselected
CMP #$00 ;this is the first option, since tables start counting at 0
BNE +
    ;script whatever you want to happen during option 1 here, maybe play a sound, warp to a screen, change a user variable, whatever you want
    RTS
+
CMP #$01 ;this is the 2nd option, since tables start counting at 0
BNE +
    ;script whatever you want to happen during option 2 here, maybe play a sound, warp to a screen, change a user variable, whatever you want
    RTS
+
CMP #$02 ;this is the 3rd option, since tables start counting at 0
BNE +
    ;script whatever you want to happen during option 3 here, maybe play a sound, warp to a screen, change a user variable, whatever you want
    RTS
+
RTS

For something like that, you will have to add another section for each menu option you have on the screen. (i only provided space for the first 3 options. you just have to add more) But what if you only want to make a screen warp and have a lot of options? there is a more efficient way for that, and it's to use another table:

Method 2 :

First, we will need a list of screen #s to warp to. Let's go back to the example screen where I set up 10 levels.

Our table is going to be a list of the screen numbers for each level. to make out lives easier, we will use Hex values for the screens, as there is an easy trick to finding the correct screen on your map:

If you hover over your level 1 screen on your overworld map screen, it will show you "X=# Y=#" in the top left.

my level 1 screen is X=1 Y=4

so you switch it around to YX and add "#$" to the start

my screen number for level 1 is "#$41"

if level 2 is on screen X=5 Y=8, then my screen number for level 2 is "#$85"
if level 3 is on screen X=11 Y= 5, then it gets a bit trickier, 11 is B. since in hex, we count 0-15 this way : 0123456789ABCDEF. my screen for level 3 is "#$5B"

so complete a list in order, and you will have something like this (use your own values, don't just copy/paste this)
Code:
menuscreens:
    .db #$41,#$85,#$5B,#$6A,#$88,#$A6,#$4D,#$3F,#$D3,#$53

notice that I have the EXACT same amount of numbers in this table as I have options in my menu.

post your new table right under where we did our X and Y coord tables in scripts>Defined Scripts>Game>Extra Tables

Now we will use that table to warp to our chosen screens by pressing start with this script:

Code:
LDY optionselected
LDA menuscreens,y
STA tempx
WarpToScreen #$00, tempx, #$01
;change the first arg to #$01 if you want to warp to the Underworld)
RTS

For whichever method you choose, save that script as "menustart.asm" and save it to the same place you saved "menuselect.asm"

Now you add that script under Scripts>Input Scripts and we go to the Input Editor and configure our new script to work with our Start Button

Game State: menu
target: player
Controller1
Script to run: menustart.asm
Release
start

Notice how we set it to release instead of press? this can help with some glitchiness in some cases.


Once that is done, It should now warp to the screen you choose when hitting start!


Now you are done!!
please let me know If I need to clarify any steps on this tutorial. or if you have any questions.
I love this tutorial.
 
Top Bottom