Proper way to make game menus?

9 posts

Flag Post

Hi all, I’ve searched on google in vain for a bit, so I’m here to ask you all now:

Is there a “proper” way to handle the menu system for flash games? Right now I have a “gui_mc” which has different frames labeled “Loading”, “Title”, “Play”, “Gameover”, and so on. I place this movieclip on the stage first, then use “gotoAndStop();” whenever the user clicks a button to navigate the different menus of my game. It just seems rather clunky, and I’d rather create a menu purely in actionscript.

Any tutorials around the internet, or maybe a book you all could recommend? As I said, I’ve had no such luck with google.

Thanks!

 
Flag Post

Here’s the way I’ve done it. I have each screen be a different class, usually extending MovieClip. the title screen is a class, the options screen is a class, the main play screen is a class, you get the picture. The Main class, meanwhile, is the conductor of this orchestra. There is another class that handles custom events, which I call navigation events. It’s basically a repository of public, static strings describing the various events. Everyone has access to it, because it’s all static.

Let’s take an example. When the game starts, Main creates a new TitleScreen and adds it to the stage. It also puts event listeners on the title screen. That title screen has created its own buttons and everything inside itself and all is well. Then the player clicks on the ‘new game’ button. This dispatches a TITLETONEWGAME event (it’s a custom navigation event in the navigation events class), which Main is listening for. When that happens, Main calls its TitleToNewGame function, which removes the title screen and creates a new GameScreen, and puts the appropriate event listeners on it. If the player then clicks on a ‘back to title’ icon in the game, that icon would dispatch a GAMETOTITLE custom event that Main listens to, etc… you get the gist.

This way the various screens don’t know the other screens even exist, and Main only knows about the various screens and has absolutely no clue what is going on inside them. If you have specific questions about the implementation process feel free to ask, but the programming forum is usually better for coding questions.

Edit: The various classes extend MovieClip because that’s what they did in the tutorial I used when I first started. On the other hand, the whole thing would likely work exactly as well and be less wasteful if I extended Sprite instead.

 
Flag Post

Thanks for the response!

This sounds like a fantastic solution, because then I could handle all of the game functionality and the HUD and such inside of the PlayScreen class or whatever. The only thing tripping me up is I’ve never had to make a custom even handler before, but I’m sure I could find a tutorial or two on that.

 
Flag Post

I’m glad you like this solution. I did not come up with it though, but learned it in this excellent tutorial which is extremely well-written and covers the basics of AS3 programming. The event handler thing is really trivial (and explained there), here’s what I use:

package  
{

	/**
	 * The screen navigator, handles screen change and other messages.
	 * @author Ace_Blue
	 */
	import flash.events.Event;
	public class NavigationEvent extends Event 
	{
		public static const TITLETONEWGAME:String = "TitleToNewgame";
		public static const FRAMEHASMOVED:String = "A frame panel has moved";
		public static const PLAYERHASMOVED:String = "The player has moved";
		public static const ITEMCONSUMED:String = "An item has been consumed from the inventory";
		
		public function NavigationEvent( type:String )
		{
			super( type );
		}
	}
}

Here is what happens, for instance, when the player clicks on the ‘new game’ button on the title screen (the button has an event listener on it that listens for a MouseEvent.CLICK and calls btnNewGameClick when that happens):

		private function btnNewGameClick(mouseEvent:MouseEvent):void 
		{
			dispatchEvent(new NavigationEvent(NavigationEvent.TITLETONEWGAME));
		}

Of course Main has an event listener on titlescreen that waits for a NavigationEvent.TITLETONEWGAME and calls the proper function:

		private function MakeTitle():void
		{
			titlescreen = new TitleScreen();
			this.addChild(titlescreen);
			titlescreen.addEventListener(NavigationEvent.TITLETONEWGAME, TitleToNewGame);
		}
		
		private function TitleToNewGame(navi:NavigationEvent):void 
		{
			Kill(titlescreen);
			MakeNewGame();
		}

Kill is just a function that takes a screen and removeChilds it before setting it to null. This way I do both operations in one call.

 
Flag Post

Just throwing it out there, another way . Probably not perfect, but at least it’s easy and quick to implement a new screen.

 
Flag Post

Thanks for the reply’s guys i was actually going to post a question like this.
Its like you know it before i think it.
So I may as well ask my question here.

What if you want to navigate between the menus, but you don’t want to use the mouse at all? The menu I’m working on is divided into frames on a movieclip, and what id like to do is use the WSAD or the directions to navigate and spacebar to select.

 
Flag Post
Originally posted by FlashGrenade:

Thanks for the reply’s guys i was actually going to post a question like this.
Its like you know it before i think it.
So I may as well ask my question here.

What if you want to navigate between the menus, but you don’t want to use the mouse at all? The menu I’m working on is divided into frames on a movieclip, and what id like to do is use the WSAD or the directions to navigate and spacebar to select.

Perhaps use an integer selectedbutton, to denote the place of the currently selected button in the buttons array, use the arrow keys/WASD to increase/decrease selectedbutton, thus cycling through the buttons(and don’t forget to wrap it back around once you reach the end), and use space to activate the selected button’s function.

 
Flag Post

i whipped this class up yesterday, take a look see if it checks out.

I also built a controller class to allow switching between controlling the player and controlling the menu.


	public class Menu extends MovieClip{
		//var vertCounter = 10;
		//this is for if we wish to use up and down for our menu selection
	public function Menu(stageRef:Stage) {
		
		}//constructor function
	
		
	/*	Since we are using movieclips for or menu and we are NOT using a mouse,
	 menu navigations must be done using the left and right keys.
	 you might be able to use the up and down keys for your navigation if you want
	 but it is not vital.
	 */	
	 
	
	public function moveLEFT():void {
			this.prevFrame();	
			if (this.getCurrentFrame() == 1) { 
				this.currentFrame = this.getTotalFrames();
				}	
		}//end function moveLEFT()
		
	public function moveRIGHT():void {
			this.nextFrame();
			if (this.getCurrentFrame() == this.getTotalFrames()) { 
				this.currentFrame = 1;
				}
			
		}//end function moveRIGHT()
				
	public function moveUP():void {
			//this.targetObject = t;
			
		}//end function moveUP()
		
	public function moveDOWN():void {
			//this.targetObject = t;
		
		}//end function moveDOWN()	
		
	public function removeSelf():void {

			if (stageRef.contains(this)) {
				trace("################I am trying to run remove command");
			}//The following three lines might be conceived as a bit of an overkill
			if (this.numChildren!=0) {
				this.removeChild(this.getChildAt(0));
			}
			stageRef.removeChild(this);
		}//function removeSelf()
		
	public function getCurrentFrame():int{
			if(this.numChildren != 0){
				return (this.getChildAt(0) as MovieClip).currentFrame;
			} else {
				return 0;
			}
		}//function getCurrentFrame()
		
		public function getTotalFrames():int{
			if(this.numChildren != 0){
				return (this.getChildAt(0) as MovieClip).totalFrames;
			} else {
				return 0;
			}
		}//function getTotalFrames()	
		
		//this function will be called when some pushes the attack or jump buttons
		
	public function EnterSelection():int{
			var d:int = this.getCurrentFrame();
			return d;
			this.removeSelf();
			}
		}//function getCurrentFrame()	
		
		public function removeSelf():void {
			if (stageRef.contains(this)) {
			}//The following three lines might be conceived as a bit of an overkill
			if (this.numChildren!=0) {
				this.removeChild(this.getChildAt(0));
			}
			stageRef.removeChild(this);
		}//function removeSelf()
		
	}//class
}//package



 
Flag Post

I’m not sure if this is of any help whatsoever, but this is a class I wrote up aaaaages ago which dealt with the display and creation of menu elements, so the actual text or images of the menu.

package  
{
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.text.TextField;
	import flash.events.MouseEvent;
	import flash.utils.Dictionary;
	/**
	 * ...
	 * @author Sp Games
	 */
	public class MenuClass extends Sprite
	{
		private var _menuHolder:Dictionary = new Dictionary();
		
		public function MenuClass() 
		{
			
		}
		
		public function draw_menu(s:Stage):void {
			
			for each(var i:* in _menuHolder) {
				s.addChild(i);				
			}
			
		}
		
		/*public function create_menu_element_sprite(s:String, x:int, y:int):void {

			var temp:Sprite = tempS;
			temp.x = x - temp.width / 2;
			temp.y = y - temp.height / 2;
			_menuHolder[func.count_keys(_menuHolder)] = temp;
		}*/ not implemented
		
		public function create_menu_element_text(s:String, x:int, y:int):void {
			var tempS:TextField = new TextField();
			tempS.textColor = 0xffffff;
			tempS.text = s;
			tempS.x = x - tempS.width / 2;
			tempS.y = y - tempS.height / 2;
			_menuHolder[func.count_keys(_menuHolder)] = tempS;
		}
		
		public function clear_menu(s:Stage):void {
			
			for each(var i:* in _menuHolder){
				s.removeChild(i);
			}
			for each (var j:int in _menuHolder) {
				delete _menuHolder[j];
			}
			
			
			
		}

		public function get_array_element(i:int):Object {
			return _menuHolder[i];
		}
		public function get_dictionary():Dictionary {
		
			return _menuHolder;
		}
		
	}

}

Yeah, it’s not perfect, but essentially it makes development of a menu much easier to work with as you only need to create a new menu, and everything gets placed into a dictionary, and then to draw the menu, you just called draw_menu on your menu object.

Yeah…