Implementing a main menu screen


(Ethan) #1

I’m looking to implement a minimalistic menu screen that is just a flat black with a few buttons on it. I’m looking to achieve something like this and plan to have the game fade in from the black menu screen when it starts. So I have a few questions regarding this.

How can I create a solid black background without referencing an image I already have made? I would prefer to just create an image of a given color on the spot.

What should the main menu be? A World? An Entity?

And how can I make the menu fade out as the game starts?


(Jonathan Stoler) #2

You can set the default background color in a few ways:

FP.screen.color = 0x000000;

or, in your Main class (or whatever you decided to name it):

[SWF(width="YOURWIDTH", height="YOURHEIGHT", backgroundColor="#000000")]

or you can set it in the metadata of the swf itself (your IDE should be able to do this)

Or, you could just create a giant Image for your background:

var bg:Image = Image.createRect(FP.width, FP.height, 0x000000);
add(bg);

I think your main menu should be a World. There are only a few times where I would recommend making it an Entity instead, and your situation doesn’t sound anything like any of those.

In terms of making it fade out, you can create another full-screen Image on top of the rest of your Entities and use a Tween to fade it out:

var fade:Image = Image.createRect(FP.width, FP.height, 0x000000);
fade.alpha = 0;
add(fade);

var fadeTween:VarTween = new VarTween();
fadeTween.complete = function():void{
	FP.world = new GameWorld;
}

Then, when you’re ready to load the game world:

fadeTween.tween(fade, "alpha", 0, FADE_TIME);

You might also want to do the opposite (have a tween from alpha 0 to 1) at the beginning of GameWorld depending on your game.

Another thing to look into is punk.transition, which allows you to create smooth transitions between Worlds. One of the default transitions is a fading transition.


(Ethan) #3

Thank you for being so thorough! I played around with that stuff for a bit and I now have a main menu screen I’m pretty happy with.

I haven’t got to the fade-in/out using tweens yet but I have an idea for what I’ll do. I’m thinking what I’ll do is fade out the buttons so that the screen is just the black background, switch worlds, and then fade out a black screen from the 2nd game world to make it appear like it faded from the main menu world.


(Nate ) #4

It sounds like you already got help with this but I will keep this short and sweet. When I want to make a new screen I just create a new world for it. For myself, I try to not think of worlds as worlds but instead, I think of them as screens. So you have all of your game entities in one folder and all of your worlds in another, then you just call the world you want from your main initialization, and in that world add the entities you want. When you want to change worlds you just use FP.world = new WorldName from wherever you want in your game.

So for a menu, your main initialization function would start your menu world, which would be a world populated with all of your HUD elements (entities). One of which would be a Start button, or something of that nature, which upon clicking holds some mouse input code that will then use FP.world = new GameWorld, thereby starting the game or level one or whatever you want really!


(Ethan) #5

Yeah, I had made a new folder in my project for Worlds once I added a start screen. I like your idea of having a separate folder for HUD elements as well.

On the subject of buttons, would this approach be fine? I was thinking I could create a class, Button, which extends entity and returns a boolean that states whether or not it has been clicked. Then my menu “world” can call it in it’s update function and respond when it returns true.


(Ethan) #6

Hmm, well that attempt to make a button failed. Basically I want to make a Button class that I can add in the StartScreen “world” and use it to trigger a change to another game state “world”. I have the Button class working when I tell it what to do in it’s own update() function, but that seems sloppy because I’d have to create a new class almost identical to it for each other Button I add.


(Nate ) #7

You could either have a different button class for each button. Or you could have one button class which is more modular. I am doing this off the top of my head, have your button class take some parameters and parse them in your button class to produce different buttons via the button class update method.

So like, your button class could simply be an image of a blank button. Then inside the button you could change the text of the button as well as change the link to the button based on a value that is passed as a parameter, so then in your world you would add the button like this, add(new button(“Start”, 1)) then in the update method of the button class just say, if(buttonValue == 1){FP.world = new GameWorld;}


(Ethan) #8

Ah, ok that makes sense. I was trying to think of a way to pass it tasks (changing world, play music, etc…) from the world class and then it being run by the button. My issue was, I wanted to pass a function through the Button constructor and you can’t really do that (as far as I know). But your right, I could have all the different tasks options contained inside the Button class itself and assign them to an variable such as an int or string. I’ll try that out.


(Nate ) #9

Okay I made a demo program with simple button adding. Here is the source:

With this, you are able to add buttons via the world simply by adding a new button and passing what you want the button to say, what type the button is and the x and y value of the button! This should make setting up a menu system very simple and it will all be done with one button class.

Hope this helps!


(Zachary Lewis) #10

Why not?

Button

public class Button extends Entity
{
  protected var onButtonClick:Function;

  public function Button(clickHandler:Function)
  {
    onButtonClick = clickHandler;
  }

  override public function update():void
  {
    if (Input.mousePressed)
    {
      if (collidePoint(x, y, Input.mouseX, Input.mouseY))
      {
        onButtonClick();
      }
    }
  }
}

MenuWorld

public class MenuWorld extends World
{
  /** Starts a new game. */
  protected function startGame():void
  {
    FP.world = new GameWorld();
  }

  /** Shows the credits. */
  protected function viewCredits():void
  {
    FP.world = new CreditsWorld();
  }

  /** Toggles the background color. */
  protected function toggleColors():void
  {
    FP.screen.color = FP.screen.color == 0xff000000 ? 0xffffffff : 0xff000000;
  }

  override public function begin():void
  {
    add(new Button(startGame));
    add(new Button(viewCredits));
    add(new Button(toggleColors));
  }
}

(Ethan) #11

It turns out my implementation of that failed because of syntax T.T

I got caught up on not knowing how to pass the function into the contructor. It didn’t like

startButton = new Button(text, 10, 10, 0, launchGame());

because of the brackets after launchGame.


(Ethan) #12

Thanks! I checked it out and it actually looks almost identical to the implementation I came up with based on your advice.


(Nate ) #13

No problem! I am sure the way you were trying to do it by passing functions also works, as well as a plethora of other possibilities, but I feel like by passing functions you would have a lot of functions and it could get cluttered. For the way I set this up, you just add a conditional to the one click function in order to add more button type actions.

Overall I think it works well, but like I said I am sure there are many other ways to accomplish this!