Flik: Sphere Central!
Docs!
Sphere Docs
flik_menu --- how to use Flik's menu object
The flik_menu.js tutorial!
flik_menu at first is like sphere's system menu, but slightly scarier in certain ways.
(It allows you to do more though.)
EvaluateScript("flik_menu.js");

/**
 * This is an example of a main menu.
 */
function MainMenu()
{
  var menu = DefaultMenu(16, 16);
  var descriptions = ["Start a new game", "Load a previous game", "Exit the game"];

  var NumSaves = 0;

  menu.addText("Start", function() { menu.done = true; StartGame(); });

  menu.addText("Load",  function() { menu.done = true; LoadGame(); });
  menu.items[menu.items.length - 1].isSelectable = function() { return NumSaves > 0; }

  menu.addText("Exit",  function() { menu.done = true; Exit(); });

  menu.preRender = function() {
    menu.getFont().drawText(16, GetScreenHeight() - 32, descriptions[menu.selection]);
  }

  menu.execute();
}
The above menu creates a simple Start/Load/Exit style main menu. It has descriptions of what each menu item does at the bottom of the screen. It also has "Load" grayed out, because NumSaves is zero.
EvaluateSystemScript("time.js");
EvaluateScript("flik_menu.js");

function Debug(text) {
  var x = GetScreenWidth() / 2 - GetSystemFont().getStringWidth(text);
  var y = GetScreenHeight() / 2 - GetSystemFont().getHeight() / 2;
  GetSystemFont().drawText(x, y, text);
  FlipScreen();
  Delay(1000);
}

/**
 * This is an example of a players menu.
 */
function PlayersMenu()
{
  var start_time = GetTime();
  var players = ["Jim", "Bob", "Fred", "Alex"];

  var menu = DefaultMenu(16, 16);

  for (var i = 0; i < players.length; i++) {
    menu.addText(players[i], function() {
      Debug(players[menu.selection]);
    });
  }

  menu.escapeable = function() {
    if (GetTime() - start_time > 5000) {
      return true;
    }
    return false;
  }

  menu.postRender = function() {
    menu.getFont().drawText(16, menu.getHeight() + 32, GetTime() - start_time);
  }

  menu.execute();
}

The above menu calls the Debug function with the text of the item selected...
It also is not escapeable until after 5000 milliseconds,
and draws the number of milliseconds past just below the menu

[Just think, a stats menu is nothing more than both the menu's above, with the preRender
(or postRender parts changed to something like: DrawStats(48, 100, menu.selection))]


Here's an item's menu example...
See item_menu.zip
function DoesFileExist(folder, filename) {
  var filelist = GetFileList(folder);
  for (var i = 0; i < filelist.length; i++) {
    if (filelist[i] == filename)
      return true;
  }
  return false;
}

function DoesImageExist(filename) {
  return DoesFileExist("images", filename);
}

function GetTotalMoney() {
  return 100;
}

function GetItemList() {
  function Item(name, type, amount) {
    this.name = name;
    this.type = type;
    this.amount = amount;
  }

  var list = new Array();

  list.push(new Item("Herb", "item", 4));
  list.push(new Item("Shield", "armour", 5));
  list.push(new Item("Fire", "spell", 1));

  list.push(new Item("Potion", "item", 2));
  list.push(new Item("Chainmail", "armour", 5));
  list.push(new Item("Water", "spell", 88));

  list.push(new Item("Exilir", "item", 13));
  list.push(new Item("Pendant", "armour", 1));
  list.push(new Item("Earth", "spell", 3));

  list.push(new Item("Ether", "item", 4));
  list.push(new Item("Helmet", "armour", 7));
  list.push(new Item("Cure", "spell", 9));

  return list;
}

/**
 * This is an example of a reasonly complicated items menu.
 */
function ItemsMenu()
{
  var items_list = GetItemList();

  var items_menu = DefaultMenu(16, 16, 100, 200);

  var list_only = ["armour", "spell"]; // show only these types of items
  var item_indexes = new Array();

  // load some icons for item types
  var armour_icon = null;
  var spell_icon = null;

  if (DoesImageExist("armour.png")) {
    armour_icon = LoadImage("armour.png");
  }

  if (DoesImageExist("spell.png")) {
   spell_icon = LoadImage("spell.png");
  }

  // get a list of item indexes for indexing into the items_list array
  // e.g. var item = items_list[item_indexes[index]];
  for (var i = 0; i < items_list.length; i++)
  {
    for (var j = 0; j < list_only.length; j++) {
      if (items_list[i].type == list_only[j] || list_only[j] == "everything") {
        item_indexes.push(i);
        break;
      }
    }
  }

  // add the item types selected to the menu
  for (var i = 0; i < item_indexes.length; i++) {
    items_menu.addText(items_list[item_indexes[i]].name, function() {
      // this item was selected...
      var item = items_list[item_indexes[items_menu.selection]];
      item.amount -= 1;
    });

    items_menu.items[items_menu.items.length - 1].isSelectable = function() {
      // can we select this item...?
      var item = items_list[item_indexes[this.index]];
      return (item.amount > 0);
    }
  }

  // draw some stuff in the background
  // draw a pretty windowstyle here if you want...
  items_menu.preRender = function() {
    items_menu.getFont().drawText(16, 220, "$" + GetTotalMoney());
  }

  // draw the number of items next to each item in the menu
  // this is all based on what we've already drawn to the screen (or the shown_items)
  items_menu.postRender = function() {
    for (var i = 0; i < items_menu.shown_items.length; i++) {
      var item = items_list[item_indexes[items_menu.shown_items[i]]];

      // draw the amount of the item
      var x = items_menu.items[items_menu.shown_items[i]].x;
      var y = items_menu.items[items_menu.shown_items[i]].y;
      items_menu.getFont().drawText(x + 80, y, item.amount);

      // draw an icon for the item type
      switch (item.type) {
        case "armour":
          if (armour_icon != null)
            armour_icon.blit(x + 100, y);
        break;
        case "spell":
          if (spell_icon != null)
            spell_icon.blit(x + 100, y);
        break;
      }
    }
  }

  // and finally execute the menu
  items_menu.execute();
}


/**
 * This is an example of a menu that uses columns.
 */
function ColumnMenu()
{
  var items_list = GetItemList();
  var items_menu = DefaultMenu(16, 16, GetScreenWidth() - 32, 150);

  var num_columns = 3;

  // add the default keys to the menu
  items_menu.addDefaultKeys();

  // now override the default keys so this menu behaves like a column menu
  items_menu.addKey(KEY_LEFT,  function() { items_menu.selection -= 1; });
  items_menu.addKey(KEY_RIGHT, function() { items_menu.selection += 1; });
  items_menu.addKey(KEY_UP,    function() { items_menu.selection -= num_columns; });
  items_menu.addKey(KEY_DOWN,  function() { items_menu.selection += num_columns; });

  if (true) {
    var x = 0;
    var y = 0;

    for (var i = 0; i < items_list.length; ++i) {

      // add the item to the menu
      items_menu.addText(items_list[i].name, function() {
        Abort("You selected: " + items_list[items_menu.selection].name + "\n");
      });

      // position where the item should be
      items_menu.items[items_menu.items.length - 1].x = x * 75;
      items_menu.items[items_menu.items.length - 1].y = y * 15;

      x += 1;
      if (x >= num_columns) { x = 0; y += 1; }
    }
  }

  items_menu.preRender = function() {
    items_menu.getWindowStyle().drawWindow(16, 16, GetScreenWidth() - 32, 150);
  }

  items_menu.execute();
}

The function listing!

  DefaultMenu(x, y [, width, height])
  DefaultMapMenu(x, y, [, width, height])

  Menu(x, y [, width, height])

    MenuObject.getFont()
    MenuObject.getWindowStyle()
    MenuObject.getArrow()
    MenuObject.getMouse()

  Input:
    Keyboard:
      MenuObject.addKey(KEY, action [, delay])
      MenuObject.removeKey(KEY)
      MenuObject.addDefaultKeys(up, down, select, escape)
      MenuObject.handleSelection()
      MenuObject.handleKeys()

    Mouse:
      MenuObject.addMouseButton(BUTTON, action, delay)
      MenuObject.addDefaultMouseButtons()
      MenuObject.removeMouseButton(BUTTON)
      MenuObject.handleMouse(x,y,w,h)
      MenuObject.getMouseItem()

    Joystick:
      MenuObject.addJoypad(joypad_index, joypad_image)
      MenuObject.addDefaultJoypadButtons(joypad_index, select, escape)
      MenuObject.drawJoypads()
      MenuObject.getJoypadItem(joypad_index)

  Drawing:
    MenuObject.draw(x,y,w,h)
    MenuObject.preRender()
    MenuObject.postRender()
    MenuObject.go(x,y,w,h,selection)
    MenuObject.execute(x,y,w,h)
    MenuObject.whenOffScreen()

  Ways to add items to the menu:
    MenuObject.add(x, y, item,  w, h, drawMethod, highLightMethod, isSelectable, onSelection)
    MenuObject.addText(text, action, font, color, highlightcolor, pointer)
    MenuObject.addTextBox(text, action, text_width, font, color, highlightcolor, pointer)
    MenuObject.addImage(image, action, normaltint, highlighttint, pointer)
    MenuObject.addSpriteset(spriteset, action, normaltint, highlighttint, text, font, space, pointer)
    MenuObject.addTextGradient(text, action, fontcolor, activefontcolor, backgroundcolor, font, pointer)
    MenuObject.addTextWindowStyle(text, action, fontcolor, activefontcolor, windowstyle, font, pointer)
    MenuObject.defaultMouseSupport(support, image, defaultbuttons)

  Position related:
    MenuObject.getX()
    MenuObject.getY()
    MenuObject.getWidth()
    MenuObject.getHeight()
    MenuObject.getNextX()
    MenuObject.getNextY()

  Animations:
    MenuObject.slide (sx, sy, ex, ey, time)


Thats its folks, soon, I will cover *whatever* anyone wants me to..

Made By Flik!