Script:Flik menu.js

From Spherical
Revision as of 01:29, 8 June 2013 by Apollolux (talk | contribs) (created from http://web.archive.org/web/20120301232624/http://www.spheredev.org/wiki/Creating_a_menu_using_flik_menu.js)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

This tutorial/guide describes how to make simple menus, using Flikky's flik_menu.js script.

Guide

Getting flik_menu.js

Download the menu object from Flikky's page (25 KB ZIP archive). flik_menu.js is what you need, so copy that into your game's scripts/ directory.

The basics

Time to create a menu in Sphere. To do this you can download my menu object from my files page, and add the line:

RequireScript("flik_menu.js");

to one of your scripts.

Now in that script you can now create a menu object. First off, a simple menu, using only text.

var MyMenu = new Menu(0,0);

MyMenu.addText("New Game", New_Game);
MyMenu.addText("Load Game", Load_Game);
MyMenu.addText("Exit Game", Exit_Game);

MyMenu.execute();

Fairly simple stuff. Now lets add some descriptions to our choices.

var font = GetSystemFont();

menu_descriptions = new Array();
menu_descriptions[0] = "Start a new game";
menu_descriptions[1] = "Load a previously saved game";
menu_descriptions[2] = "Exit the game like the coward you are";

var MyMenu = new Menu(0,64); // move the menu down screen a bit ^^
MyMenu.preRender = function() { // whenever you refer the the menu's selection attribute, always handleSelection first, so it doesn't crash...
  MyMenu.handleSelection();
  font.drawText(16, 32, menu_descriptions[MyMenu.selection]);
};

MyMenu.addText("New Game", New_Game);
MyMenu.addText("Load Game", Load_Game);
MyMenu.addImage(LoadImage("exit_game.jpg"), Exit_Game);

MyMenu.execute();

So now you've made a menu, where it shows useful help alongside the menu, and has an image for one of the menu items. The text alongside the menu is created by just putting it in the MyMenu.preRender function.

Mouse support

So now lets add mouse support to the menu.

MyMenu.mouseSupport = true;
MyMenu.addDefaultMouseButtons();
MyMenu.mouse = LoadImage("mouse.png");

Images in your menus

Another, simpler way of adding an image to the menu, is using MyMenu.addImage(image, action [, normaltint, highlighttint, pointer]),

MyMenu.addImage(LoadImage("woot.png"), ImageWoot);

That's a Sphere Image object, so remember to load it before putting it in the menu.

Grouping your item code

It is also possible, for each item's action to point to the same function.

function MenuChoice(i)
{
  switch (i)
  {
    case 1: ChoiceOne();
    case 2: ChoiceTwo();
    case 3: ChoiceThree();
    case 4: ChoiceFour();
  }
}
MyMenu.addText("Choice I", function(){ MenuChoice(MyMenu.selection); });

Closing your menu

Now we can make the menu escapeable, by doing:

MyMenu.escapeable = function(){ return true; };
MyMenu.escape_function = function()
{
  // whatever
}

Shortcut menu keys

To add shortcut keys, or whatever, to the menu, you can do:

function PAUSE_FUNCTION()
{
  var font = GetSystemFont();
  
  while (AreKeysLeft())
    GetKey();
  
  var done = false;
  do
  {
    font.drawText(70, 70, "Game Paused!");
    if (IsKeyPressed(KEY_ENTER))
      done = true;
    FlipScreen();
  } while (!done);
}
MyMenu.addKey(KEY_P, PAUSE_FUNCTION);

Custom window style

What more could you want? A pretty window style around the menu?

MyMenu.preRender = function() {
  var window = GetSystemWindowStyle();
  window.drawWindow(MyMenu.x, MyMenu.y, MyMenu.getWidth(), MyMenu.getHeight());
};

That preRender function just draws a windowstyle around the items. Since the items can be at any (x, y) point, the function needs to calculate the values.

Running the menu in your own loop

Want to make a menu that doesn't stop your games running process?

var font = GetSystemFont();
// stuff...
while (!MyMenu.done)
{
  font.drawText(Math.random()*20, Math.random()*20, "Behind the menu...");
  MyMenu.go();
  font.drawText(Math.random()*20, Math.random()*20, "Infront of the menu...");
}

Actually, you could do that using the MyMenu.preRender, and MyMenu.postRender methods.

Different approaches

Heh. I'm too used to eval'ing actions into the menu... Any advice?

Yeah, if you want to eval something into the menu, you can do:

MyMenu.addText("whatever", function(){ eval("code") });
// This is the same as changing the .onSelection method like so:
// MyMenu.items[index].onSelection = function(){ eval("code"); }
// where index is the item you want to change number'.
How about mouse support?

Well, simply provide a mouse image.

function Mouse_Right_Was_Clicked()
{
  // whatever
}
MyMenu.mouseSupport = true;
MyMenu.mouse = LoadImage("mouse.png");
MyMenu.addDefaultMouseButtons();
MyMenu.addMouseButton(MOUSE_RIGHT, Mouse_Right_Was_Clicked, 0);

Reference

Menu reference (basic)

Menu_Object.add(
  x, y,
  item,
  width, height,
  drawMethod, highLightMethod,
  isSelectable, onSelection )

Adds item, whatever object item is, to the menu.items list.

You define the x and y of where it will be drawn.
width, height are provided so that the mouse support works, and new items can refer to the last item's location.
drawMethod is a function that tells the menu how to render the 'item'.
highLightMethod is a function that is called if the 'item' is selected. The drawMethod is not called if the item is selected. Only the highLightMethod is called.
isSelectable is a function that returns true or false as to whether you can select the item. e.g. if the item, was a ShopItem, with the property of ShopItem.price, it would check to see if you had the correct amount of money to buy the item, and return true if you did, else return false.
onSelection is a function that happens when you press KEY_ENTER (by default), and does not internally mean the menu is ended. Only if the onSelection method says Menu_Object.done = true; will the menu actually end.
Menu_Object.addKey(KEY, action)

Adds a key (look in sphere/docs/keys.txt for list of keys) to the menu, and performs the action function, if the key is pressed.

Menu_Object.removeKey(KEY)

Removes the key from the menu's list of keys to check for.

Menu_Object.addMouseButton(BUTTON, action)

Same as addKey, but for the mouse. BUTTON should be MOUSE_LEFT or MOUSE_RIGHT or MOUSE_MIDDLE.

Menu_Object.go(selection)

Draws the menu and handles input, but does not take control of the game, i.e. the game doesn't stop for the menu.

selection is the choice that you want the Menu_Object.selection to become, if its not defined though, it will default to Menu_Object.selection.
Menu_Object.execute()

Same as Menu_Object.go, but takes control of the game.

Menu_Object.addDefaultKeys()

Adds the default key setup, this is KEY_UP, KEY_DOWN, KEY_ESCAPE and KEY_ENTER. KEY_UP takes 1 away from the Menu_Object.selection and KEY_DOWN adds 1 to the Menu_Object.selection.

Menu_Object.addDefaultMouseButtons()

Adds the MOUSE_LEFT to do the same thing as the default KEY_ENTER does.

Menu_Object.mouseSupport;

Menu_Object.mouseSupport is true or false depending on whether you want to use the mouse or not. Default is false.

Menu_Object.mouse;

Menu_Object.mouse is an image object. That defaults to the system arrow.

This: Menu_Object.mouse = LoadImage("whatever.png");, changes the image that the menu uses.
Menu_Object.escapeable()

A function that returns true or false depending on if you can escape from the menu or not, i.e. press KEY_ESCAPE.

The default is Menu_Object.escapeable = function(){ return false; }
Menu_Object.escape_function()

The function that is called when you escape the menu.

Menu_Object.handleSelection()

A function that is called to handle the selection, e.g. If the current selection is greater than the total number of selections, you can reset the selection value to 0.

Or move all the x and y values of the Menu_Object.items list to make moving menu's. e.g. A menu where the items move around in a circle.
Menu_Object.draw()

This handles the drawing process of the menu items.

Menu_Object.preRender()

You can make the menu draw a window style here if you wish.

Menu_Object.postRender()

After the drawing of the menu items you can render it using this function.

Menu_Object.whenOffScreen()

Called when the current item is offscreen (not within the drawing box of the menu). Default used for providing automatic scrolling of menu items.

Menu reference (extra)

Menu_Object.addText(
  name,
  action
  [, font,
  color,
  highlightcolor,
  pointer] )

Adds name using font and color to the menu.

font, color, highlightcolor and pointer can all be omitted from the calling function. e.g. Menu_Object.addText("woo", function(){ Abort("Woo was selected."); });
Menu_Object.addImage(
  image,
  action
  [, normaltint, highlighttint, pointer] )

Adds image object using normaltint to the menu.

font, normaltint, highlighttint and pointer can all be omitted from the calling function.
e.g. Menu_Object.addImage(LoadImage("wee.png"), function(){ Abort("Wee was selected."); });
e.g. Menu_Object.addImage(LoadImage("cool.jpg"), function(){ Abort("Cool was selected."); }, CreateColor(255,255,255), CreateColor(0,255,0); LoadImage("mypointer.png"));
Menu_Object.addSpriteset(
  filename,
  action
  [, normaltint, highlighttint,
  text, font, space,
  pointer] )

Adds filename spriteset using normaltint to the menu.

normaltint, highlighttint, text, font, space and pointer can all be omitted from the calling function.
e.g. Menu_Object.addSpriteset("aegis.rss", function(){ ExitMessage("Woo..."); }, undefined,undefined, "Aegis sprite", undefined, 30, undefined);
Menu_Object.getX()

Returns the coordinate of the menu that is the most to the left.

Menu_Object.getY()

Returns the coordinate of the menu that is the most to the top.

Menu_Object.getWidth()

Returns the 'dynamic' width of the menu, static width would just be Menu_Object.width.

Menu_Object.getHeight()

Returns the 'dynamic' height of the menu, static width would just be Menu_Object.height.

Menu_Object.configureRowsForKeys(rows)

Designed to modify the keys and input keys so that the menu behaves as if it was in columns. (Doesn't work 100% correctly.)

FAQ

I want to create a shop, any ideas how I could do this?

Sure, all you need is to show a description of the items on sell, the items, and allow the person to buy it if they have enough money.

So, create an array of shop_items_names, an array of shop_items_descs and an array of shop_items_price. Or in a shop item object:

var font = GetSystemFont();
var shop_items = new Array();

function shop_item(name, cost, desc)
{
  this.name = name;
  this.cost = cost;
  this.desc = desc;
}

var shop_background = LoadImage("shopbg.png");
ShopMenu.preRender = function()
{
  shop_background.blit(0, 0);
  ShopMenu.handleSelection();
  var selection = ShopMenu.selection;
  var desc = shop_items[selection].desc;
  var cost = shop_items[selection].cost;
  font.drawText(0, 0, desc);
  font.drawText(64, 32, "$" + cost);
}

function BuyItem()
{
  ShopMenu.handleSelection();
  var selection = ShopMenu.selection;
  if(money - shop_items[selection].cost >= 0)
    inventory[shop_items[selection].name] += 1;
  else
    font.drawText(0,0, "Not enough money!");
}

shop_items[0] = new shop_item(
  "herb",
  4,
  "Neat herb to cure wounds..." );
shop_items[1] = new shop_item(
  "candy",
  3,
  "Candy that increases energy..." );

for(var i = 0; i < shop_items.length; ++i)
  ShopMenu.addText(shop_items[i].name, BuyItem);

ShopMenu.execute();

By Flikky (from the Sphere CHM, adapted and updated for the wiki.)