Our HUD now displays a title, but there's no background. What we really need is a menu so that we can choose our destiny! Let's start by adding an interesting background and then, since buttons and their associated actions form the backbone of menus, we'll make some buttons.
If you're not much of an artist, you can take the easy way out which is what we are going to do here. We're simply going to have our asteroid model rotate slowly in front of a generic space field. I created a really simple space field in Gimp and named it SpaceField.png
. Import it as usual and then create the scene by following these steps:
Startup
. The scene will open for editing.IntroAI
.IntroAI
AI will already be open, so click Add Handler and select onInit.local hAsteroid = this.getObject ( ) -- Get the frame render time local nFrameTime = application.getLastFrameTime ( ) -- Rotate the asteroid in local space so it will rotate forever object.rotateTo ( hAsteroid, 10, 0, 10, object.kLocalSpace, nFrameTime * 0.6 )
All we need to do is get a handle to the asteroid, compute the last frame time, and then rotate the asteroid based on the frame time. If you recall that when we computed the ship movement we did the same frame time computation so that the animations would be smooth regardless of the rendering speed. The rotation uses kLocalSpace
so that the rotation will continue indefinitely.
This should give us everything that we need for the background of our menu. Now let's add some buttons.
Buttons rely on actions in order to function, otherwise they would only be labels. Actions are the way by which HUD can trigger actual commands and send messages to the rest of the game. In the case of the Start and Quit buttons, we will send events to the MainAI
AI, so let's modify MainAI
to handle those events by following these steps:
MainAI
and name them StartGame
and Quit
. These are simple one line events. The following is the code for StartGame
:this.GameState ( )
Remember that at the beginning of the chapter, we set up our game states and that the actual game runs in the GameState
state. Since we start in the InitialState
state, we just need to use the this
object and the state name to load the GameState
state.
Quit
handler is similarly easy, as shown in the following line of code:application.quit ( )
This is the command to quit the application, so we put it to use. Unfortunately, these aren't the only things we need to change. Recall that InitialState
was designed to handle starting the game, but now we need a way to display the menu. This is done with the newTemplateInstance
command.
InitialState
state's onEnter
handler and hence we change the InitialState
to be the initial state; do this by right-clicking on it and select Set as Initial State.InitialState
state's onEnter
handler and add the following code:if( application.setCurrentUserScene ( "Startup" ) ~= nil ) then hud.newTemplateInstance ( application.getCurrentUser ( ), "InitialMenu", "InitialMenu" ) else log.error ( "Unable to load initial scene" ) end
The newTemplateInstance
command takes in the user, the HUD we want to use, and what name we want to refer to it as in our code. You can see that we keep the names the sameāit makes things easier. That will take care of loading the introduction screen and menu, but how do we transition to the actual game?
InitialState
we now need to dispose of our menu and then load the GameState
state, so in the onLeave
handler of InitialState
, we are going to enter the following code:hud.destroyTemplateInstance ( application.getCurrentUser ( ), "InitialMenu" ) this.StartGame ( )
The first command destroys the HUD, otherwise it will stay on the screen in the next scene. Next, we are calling the StartGame
function which is where we moved our startup code. Why do we now run the startup code in InitialState
? Because, we could be entering GameState
several times during a game if the player is opening the in-game menu, so we don't want the game to restart each time.
StartGame
code from the GameState
state's onEnter
event handler.Designing the state carefully
Be careful when designing your states and think about what each state should encompass. Initializing the state of your game, for example, would be executed each time you moved to and from other states, such as menus, unless the game initialization is handled as a separate state.
Now that we have the needed event handlers, let's create the HUD actions that will call those events using the following steps:
StartGame
and click OK.SendEventToUser
that allows us to send events to user AIs such as MainAI. You can find information about the other command types at http://www.stonetrip.com/developer/doc/api/hud#Command.QuitGame
and follow the same previous steps, but set the event to onQuit
. Now we have everything we need to create some buttons.50.00
and 45.00
for the position and 40.00
and 11.00
for the size.5
. Change the BackColor option to 0, 0, 0, and 255 and the BorderColor color's Alpha option to 0. All these settings are shown in the following screenshot:The black background will actually be replaced with our startup scene, so it is hard to get a feel for what it will actually look like, but it's a start. Now, we need the Quit button to finish off this menu, so let's take a shortcut and copy btnStart.
Right-click on btnStart and select Copy. You can either paste the button into Components directly, or you can create a new component and then paste only certain sets of information into the new component. You can see what paste options exist by clicking on the Component menu. You'll see that you can paste General, Appearance, Events, and Type, but for our purposes it will be easier to paste as a component, so right-click on Components and choose Paste and paste the btnStart button. You'll have to rename it, so set the name as btnQuit. Double-click on btnQuit and make the following changes:
Now, our InitialMenu looks complete. Of course, if we are making a full-featured game we would probably have menu items for options, instructions, and high scores, but now the concept is the same no matter how many menu items there are.
Make sure you save the HUD and then in the General workspace, drop the InitialMenu HUD item to the Resources tab of the Game Editor window. Run the game. You should see the startup scene with the title and buttons for starting and quitting the game. What's more, both buttons actually work!
We have one more menu to add, however, so don't celebrate yet. We need an in-game menu that will pause the game and give us the option to quit or restart the game. We just need the settings now that we know how to set up the HUD. Follow these steps to create your pause menu:
Restart
with the code this.InitialState ( )
, since all we have to do on restart is return to the initial state.InGameMenu
.SendEventToUser
MainAI
onStartGame
Button
50
and 65
40
and 11
RoundedRectangle
0
, 0
, 0
, and 255
0
Resume Game
Center
ResumeGame
50
and 51
Restart Game
RestartGame
50
and 37
Quit
QuitGame
You may have noticed that we are reusing the onStartGame
event for the ResumeGame action. This works because we put the actual code for starting a new game in InitialState
. Now, we need to fix the MenuState
state so that it will pause the game and load the menu. In the onEnter
handler of MenuState
, enter the following code:
local hUser = application.getCurrentUser ( ) local hScene = application.getCurrentUserScene ( ) scene.setPaused ( hScene, true ) hud.newTemplateInstance ( hUser, "InGameMenu", "InGameMenu" )
First, we get a handle to the current user and the scene and then use those to pause the game and load the HUD that we just created. When exiting MenuState
, we basically use onLeave
to reverse what we did in onEnter
, as shown in the following code:
local hUser = application.getCurrentUser ( ) local hSCene = application.getCurrentUserScene ( ) scene.setPaused ( hScene, false ) hud.destroyTemplateInstance ( hUser, "InGameMenu" )
Again, we get the current user, the scene, unpause the scene, and then destroy the menu HUD. Of course, we don't actually have anything on the screen that will allow us to enter the in-game menu; but in the next section, we will add an overlay that will give us access to our in-game menu.
3.14.134.17