Text Based Menu

A tutorial by Andrew Barber aka Chronic

Making a menu is often a time consuming thing, but what if it was made easy with just a simple array and switch statement instead of multiple objects to get confused over.

This tutorial will guide you through the process of making a text based menu, and then how to expand it to add submenus.

Getting started

Open up your Game Maker version of choice, for this i will be using Game Maker 7 but it should work in any version of Game Maker.

Add one room, object and script to a new project. Rename the object to obj_menu, and the script to scr_InitMenu. Now add one instance of the obj_menu to the top left corner (0,0) of the room you added and then close the room.

Open up obj_menu for editing and add a create event with the following script, afterwards close the object as we no longer need it at this point.

[CREATE]
{
  scr_InitMenu();
}

This will run the scr_InitMenu script which at this moment will do nothing because its empty, so lets remedy that by opening it for editing.

The scr_InitMenu script is where we will create the menu, well.. the text that it will show to the player. The code to control it will be placed into obj_menu which we will get to later.

So lets start off with a basic menu with the following options; 'Start Game', 'Options', 'Instructions', and 'Quit Game'. You can add more options if you need them, but this is all i will be using to test with.

In the script scr_InitMenu, add the following:

[scr_InitMenu]
{
  menuSelected = 1;

  menuText[0] = 4;
  menuText[1] = "Start Game"
  menuText[2] = "Options"
  menuText[3] = "Instructions"
  menuText[4] = "Quit Game"
}

At index 0, you'll notice the number 4. This is the amount of options we have for the menu so when drawing and navigating through the menu we can check this number when needed, this is very useful for loops. The menuSelected variable is so we know which option we're on when pressing enter to activate the menu option we're on.

Now we need to take care of the drawing to screen side of things, close the scr_InitMenu script and open up obj_menu for more editing.

Add a drawing event to the object so we an get the information from the array on to the screen.

[DRAW]
{
  for (i = 1; i <= menuText[0]; i+=1) {
    draw_text(x,y+(i*16)-16,menuText[i]);
  }
}

Testing the game at this point should produce something similar to this.


Text Menu

If you add more options to the array and are getting bugs with options not showing, then its most likely you have not increased index 0 to the same amount as your options.

Next we need to make it easy to tell which option we have selected. To do this lets make the current option change to red. This is done with a simple change to the loop just before drawing the text to screen.

[DRAW]
{
  for (i = 1; i <= menuText[0]; i+=1) {
    if (menuSelected = i) { draw_set_color(c_red); } else { draw_set_color(c_black); }
    draw_text(x,y+(i*16)-16,menuText[i]);
  }
}

This is it for the drawing event, the position of the menu is based on where you have placed the object in the room, in our case this is at 0,0. Move the object to the location you need it at, and also feel free to change the colors used in the menu. You could also try changing the font type and size to make your menu unique from any one else who follows this tutorial.

Note, if you change the font size you will need alter the loop so the text does not overlap when drawing the menu. To do this just change the 16 to the size of your font.

Next we need to make it so we can navigate the menu with some sort of input, we'll be using the up and down arrow keys.

Add an Press Up and Press Down events to the obj_menu object with the following scripts respectively.

[PRESS UP]
{
  menuSelected -=1;
  if (menuSelected < 1) { menuSelected = menuText[0]; }
}
[PRESS DOWN]
{
  menuSelected +=1;
  if (menuSelected > menuText[0]) { menuSelected = 1; }
}

Testing at this point you should be able to move the menu up and down using the arrow keys, it should also loop around if you keep pressing up or down.


Text Menu

Now to make the options do something, after all a menu without this is kind of pointless. So, we need another key press event, i'll be using the enter key. Add a Enter Press event to your obj_menu with the following script.

[PRESS ENTER]
{
  switch(menuSelected) {
    case 1: // Start Game
      show_message("Start Game");
    break;
    case 2: // Options
      show_message("Options");
    break;
    case 3: // Instructions
      show_message("Instructions");
    break;
    case 4: // Exit Game
      show_message("Exit Game");
    break;
  }
}

It is a good idea to add comments to your code like i have done here so you know which case is for which menu option, this way you don't need to check back to your array or remember what each option does.

To make this menu actually useful, its going to take more than a bunch of show_message() functions which echo the option you just chose. For example you could change the show_message() for the 'Exit Game' option to game_end() making the option do what it says it will do.

Thats all there is to making a text based menu, i hope you've learnt something from this and can take it a little bit futher.. speaking of which, submenus anyone?

Taking it an extra step

Adding submenu isn't much harder than we've already got, infact all we need to do is turn our array in to a 2D and alter the drawing and press enter events a little.

[scr_InitMenu]
{
  menuSelected = 1;
  menuPage = 0;

  menuText[0,0] = 4;
  menuText[0,1] = "Start Game"
  menuText[0,2] = "Options"
  menuText[0,3] = "Instructions"
  menuText[0,4] = "Quit Game"
  
  menuText[1,0] = 3
  menuText[1,1] = "World 1"
  menuText[1,2] = "World 2"
  menuText[1,3] = "Back"
}

You'll notice that the array is now 2D and we've an extra few lines. Because we are using multiple menus, or what i've called pages, we need a way to track which we are on so we can draw it appropriately. This is done by using the variable menuPage. The other lines are the same as before, index 0, or more correctly index 1,0, hold the amount of options in the menu, and the other indexes are what will be drawn on screen.

Now to fix the drawing event.

[DRAW]
{
  for (i = 1; i <= menuText[menuPage,0]; i+=1) {
    if (menuSelected = i) { draw_set_color(c_red); } else { draw_set_color(c_black); }
    draw_text(x,y+(i*16)-16,menuText[menuPage,i]);
  }
}

and the press up an down events

[PRESS UP]
{
  menuSelected -=1;
  if (menuSelected < 1) { menuSelected = menuText[menuPage,0]; }
}
[PRESS DOWN]
{
  menuSelected +=1;
  if (menuSelected > menuText[menuPage,0]) { menuSelected = 1; }
}

Because we are now dealing with a menuPage and menuSelected the press enter event needs a rewrite.

[PRESS ENTER]
{
  switch(menuPage) {
    case 0: // Main Menu
      if (menuSelected = 1) { menuPage = 1; menuSelected = 1; } // Start Game
      if (menuSelected = 2) { show_message("Options"); } // Options
      if (menuSelected = 3) { show_message("Instructions"); } // Instructions
      if (menuSelected = 4) { show_message("Exit Game"); } // Exit Game
    break;
    case 1:  // Start Game menu
      if (menuSelected = 1) { show_message("World 1"); } // World 1
      if (menuSelected = 2) { show_message("World 2"); } // World 2
      if (menuSelected = 3) { menuPage = 0; menuSelected = 1; } // Back
    break;
  }
}

This time instead of using a case for each option, its now used for what page we are on. Inside each case i've used simple if statements, this could also be changed in to another switch case if you wanted to do so, but it really makes little difference for something this simple.

Closing

I hope you've learnt a bit more from this extra step section and gained a little bit more insite in to Game Maker and GML. If you have any comments or suggestions please contact me via PM at the Game Maker Community.

  • Text Based Menu - Simple Menu
  • Text Based Menu - Submenu Menu