Log In  

Hello. I'm working on a virtual pet game in pico-8 and need some help on how to make in-game menu. In the game, the menu is how you care for the pet with options like feed and cure and the options have sub menus for different options like which type of food you want. The main menu options are represented by icons but the sub menus are represented by text. The problem I'm running into is creating the menus in the first place as I can't figure out a solution to this and the options I have looked up online I can't make sense of the code.

P#105122 2022-01-15 03:28

1

Basically, you need a way to keep track of which option is currently selected, a way to show each option when they're not selected, a way to show each option when they're selected, and a way to switch options. If you're going to use mouse support, then switching options will probably mean a hit test (which is about the same as a collision test). Otherwise, switching options will mean a way to keep track of which options are connected to which other options.

If you're good at using tables, I would recommend each menu option be put in a table containing its drawing function, a function on being clicked, and an indication of whether they're currently selected, then put all the menu options in an over-arching table in the order that makes the most sense for how they'll be arranged on screen (ie. top to bottom if they're in a vertical line) along with an indication of which is currently selected by index. From there you can respond to input by moving the currently selected index, updating the options on which is currently selected, and then call the functions all neeeded. This method also has the benefit that if you have multiple menus in memory at once and a good menu drawing function to run through them, you can have submenus by just drawing multiple menus but only updating ones that are currently accessible. In the case that you want a grid instead of a line of options, you can still use a single index value, but combining that with the width of the grid to derive an x and y value with the % and \ operators. Also, since you have a specific common ways of drawing that you mentioned, prototyping the menu options might help. Basically, you just make function for each type of menu option that returns a table with the settings for that option type.

If you're not good with tables and not in a position to practice using them and read about them and such, I would instead recommend having a separate drawing/updating pair of functions for each menu and just use long if/elseif chains. It's not token or speed efficient, but it does still work.

Related, you'll also want to decide how to show which option is selected. If you have a cursor image (like a arrow) you could just have the menu option that's current selected draw the arrow next to itself as a solution to both option type. Similarly, drawing a rectangle, circle or ellipse behind the menu option works too. If you'd rather have then be highlighted, then the text ones can just change text color, but the icons might need a separate version of each icon to highlight them.

P#105170 2022-01-16 07:02
:: merwok

This topic shows generic ways to have multiple game states: https://www.lexaloffle.com/bbs/?tid=34476

P#105488 2022-01-21 22:35
1

A menu is basically just a list of actions so a simple—not necessarily best or most efficient—implementation is just to use an array of labels and functions. Ignoring nested menus for the moment, a simple menu could work like this:

-- create a menu for changing the screen color.

-- the background color of the screen
bg = 0

-- the currently selected menu item
selection = 1

colors_menu = {
   {'red', function() bg=8 end},
   {'green', function() bg=11 end},
   {'blue', function() bg=12 end},
}

Then you can write functions for drawing and updating your menus.

function draw_menu(m)
   for i=1,#m do
      if i==selection then
     -- if this item is the selection print an arrow and then the
     -- label
     print('> '..m[i][1])
      else
     -- if it's not the selection only print the label (with a
     -- couple spaces so everything lines up.
     print('  '..m[i][1])
      end
   end
end

function update_menu(m)
   -- change the currently selected/highlighted item
   if btnp(2) then
      selection -= 1
   elseif btnp(3) then
      selection += 1
   end

   -- wrap the cursor from top to bottom or bottom to top as
   -- appropriate.
   if selection > #m then
      selection = 1
   elseif selection < 1 then
      selection = #m
   end

   -- activate the current selection
   if btnp(4) then
      m[selection][2]()
   end
end

Finally, use those functions in _update and _draw.

function _update()
   update_menu(colors_menu)
end

function _draw()
   cls(bg)
   draw_menu(colors_menu)
end

Cart #simple_menu_1-0 | 2022-01-23 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
1

Nested menus can work pretty much exactly the same way. Add new menus, add a variable to keep track of which menu is currently active, and add an item to the existing menu whose action changes the currently active menu. Like so:

colors_menu = {
   {'red', function() bg=8 end},
   {'green', function() bg=11 end},
   {'blue', function() bg=1 end},
   {'nested',
    function()
       current_menu = nested_menu
       selection = 1
    end
   }
}

nested_menu = {
   {'black', function() bg=0 end},
   {'brown', function() bg=4 end},
}
current_menu = colors_menu

And then just change _update and _draw to use the current_menu.

function _update()
   update_menu(current_menu)
end

function _draw()
   cls(bg)
   draw_menu(current_menu)
end

Cart #simple_menu_2-0 | 2022-01-23 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
1

These are pretty bare-bones but you can modify the draw_menu and update_menu functions to display them where and how you want and add additional functionality like being able to close or navigate back to the previous menu as two obvious examples.

In my examples the menu/action functions don't take any parameters but, of course, they certainly can. So for your use case, I'd probably have all of the functions take the pet as an input and then the function can do whatever it needs to do: increase health, decrease hunger, or whatever.

Hope that helps.

P#105541 2022-01-23 13:33

[Please log in to post a comment]

Follow Lexaloffle:        
Generated 2022-08-18 05:28:18 | 0.008s | Q:18