FMF:What Is a Menu Slice
A Menu Slice is simply a box, which can be connected to other boxes, and can react to external input in a sensible fashion. The following snapshot of the OHRRPGCE FMF's menu system is annotated with some Slices and brief descriptions of their varying purposes:
What About the Menu Engine?[edit]
Let's say you took the spirit of the GPL and copied the OHRRPGCE FMF's source code to run your own game. You still wanted the menu system, so how would you keep that? Basically, all modules provide the following interface. (ohrrpgce.game.Engine -technically an abstract class)
- paintScene();
- handleKeys(keyStates);
- updateScene(elapsedTime);
- communicate(stackFrame);
- reset();
- runIdle();
- canExit();
The key three are handleKeys(), which responds to user input, updateScene(), which updates the menu each tick, and paintScene(), which actually shows the menu. Also, reset() is somewhat important -it's called to initialize the menu each time the user hits the "Esc" key to bring it up.
The Menu Engine deals with Menu Slices in a similar fashion to how GAME deals with NPCs. Think of the cursor as your hero, and the Slices as NPCs, which you can "walk up to" and hit Enter to "talk to". Slices follow stricter layout rules than NPCs, and have more power to interact with each other, but the metaphor is a good starting point to understanding the Menu Engine.
Why Is it So Complicated?[edit]
The code for Menu Slices is just under 1,000 lines long. Many developers would consider this bloat. Actually, Menu Slices follow from the Zen of Python: "Simple is better than complex; Complex is better than complicated." In other words, simplifying Menu Slice would complicate the rest of your code. Future releases of the OHRRPGCE FMF will continue to trim the code base, but MenuSlice.java will remain a fairly heft class.
How do I Build a Menu System?[edit]
Although a LUMP-based format could, in theory, be used to set up the menu, we chose to use pure java to do it for now. The code to initialize a menu looks something like this:
/*1*/ MetaMenu.buildMenu(width, height, rpg, adaptGen); /*2*/ MetaMenu.topLeftMI.doLayout(); /*3*/ MetaMenu.topLeftMI.moveTo();
You could describe these three commands quite concisely: 1) "Build a menu of size (width, height) based on a certain RPG." --This creates all Menu Slices and connects them together. 2) "Layout the menu, starting from the top-left most component". --Layouts do not automatically update, so after connecting everything, you must call doLayout() to recursively set all components' x, y, width, and height values. 3) "Activate the top-left most menu component". --This cascades control of the menu recursively to the inner-most active child of the top-left-most Menu Slice. Think of it as moving the little "hand" icon to point to the first Menu Slice of interest (e.g., the "Items" menu.)
Moving on, in updateScene(), we simply update the current transition. (Transitions will be covered later.) In paintScene(), we just call:
MetaMenu.topLeftMI.paintMenuSlice(-1);
...which cascades a paint command to all Menu Slices. Finally, in handleKeys(), we do the following:
if ((keyStates&InputAdapter.KEY_CANCEL)!=0) { MetaMenu.topLeftMI.cancel(); } else if ((keyStates&InputAdapter.KEY_ACCEPT)!=0) { MetaMenu.topLeftMI.accept(); }
...and so forth.
You should have noticed that the Menu Engine only controls very top-level stuff about the menu -things like "send this input to whatever component should have it." Everything else is pre-configured in MetaMenu.java, which means you can simply create your own version of this file and not have to care about the infrastructure. We'll do this in the coming tutorials.
Next: | Building our First Custom Menu |