The Main Menu Screen

The main menu screen is pretty dumb. It just renders the logo, the main menu options, and the sound setting in the form of a toggle button. All it does is react to touches on either the main menu options or the sound setting toggle button. To implement this behaviour we need to know two things: where on the screen we render the images and what the touch areas are that will either trigger a screen transition or toggle the sound setting. Figure 6-2 shows where we'll render the different images on the screen. From that we can directly derive the touch areas.

Figure 6-2. The main menu screen. The coordinates specify where we'll render the different images, and the outlines show the touch areas.

The x-coordinates of the logo and main menu option images are calculated so that they are centered on the x-axis.

Next, let's implement the Screen. Listing 6-5 shows the code. Listing 6-5. MainMenuScreen.java, the Main Menu Screen package com.badlogic.androidgames.mrnom;

import java.util.List;

import com.badlogic.androidgames.framework.Game; import com.badlogic.androidgames.framework.Graphics; import com.badlogic.androidgames.framework.Input.TouchEvent; import com.badlogic.androidgames.framework.Screen;

public class MainMenuScreen extends Screen { public MainMenuScreen(Game game) { super(game);

We let the class derive from Screen again and implement an adequate constructor for it. ^Override public void update(float deltaTime) { Graphics g = game.getGraphics();

List<TouchEvent> touchEvents = game.getInput().getTouchEvents(); game.getInput().getKeyEvents();

int len = touchEvents.size();

TouchEvent event = touchEvents.get(i); if(event.type == TouchEvent.TOUCH_UP) {

if(inBounds(event, 0, g.getHeight() - 64, 64, 64)) { Settings.soundEnabled = {Settings.soundEnabled; if(Settings.soundEnabled) Assets.click.play(l);

if(inBounds(event, 64, 220, 192, 42) ) { game.setScreen(new GameScreen(game)); if(Settings.soundEnabled) Assets.click.play(l); return;

if(inBounds(event, 64, 220 + 42, 192, 42) ) { game.setScreen(new HighscoreScreen(game)); if(Settings.soundEnabled) Assets.click.play(l); return;

if(inBounds(event, 64, 220 + 84, 192, 42) ) { game.setScreen(new HelpScreen(game)); if(Settings.soundEnabled) Assets.click.play(l); return;

Next we have the update() method, in which we'll do all our touch event checking. We first fetch the TouchEvents and KeyEvents from the Input instance the Game provides to us. Note that we do not use the KeyEvents, but we fetch them anyway in order to clear the internal buffer (yes, that's a tad bit nasty, but let's make it a habit). We then loop over all the TouchEvents until we find one with the type TouchEvent.TOUCH_UP. (We could alternatively look for TouchEvent.TOUCH_DOWN events, but in most UIs the up event is used to indicate that a UI component was pressed).

Once we have a fitting event, we check whether it either hit the sound toggle button or one of the menu entries. To make that code a little cleaner, I wrote a method called inBounds(), which takes a touch event, x- and y-coordinates, and a width and height. The method checks whether the touch event is inside the rectangle defined by those parameters, and returns either true or false.

If the sound toggle button is hit, we simply invert the Settings.soundEnabled boolean value. In case any of the main menu entries are hit, we transition to the appropriate screen by instancing it and setting it via Game.setScreen(). We can immediately return in that case, as the MainMenuScreen doesn't have anything to do anymore. We also play the click sounds if either the toggle button or a main menu entry is hit and sound is enabled.

Remember that all the touch events will be reported relative to our target resolution of 320! 480 pixels, thanks to the scaling magic we perform in the touch event handlers discussed in Chapter 5:

private boolean inBounds(TouchEvent event, int x, int y, int width, int height) { if(event.x > x && event.x < x + width - 1 && event.y > y && event.y < y + height - 1) return true;

else return false;

The inBounds() method works as just discussed: put in a TouchEvent and a rectangle, and it tells you whether the touch event's coordinates are inside that rectangle.

@Override public void present(float deltaTime) { Graphics g = game.getGraphics();

g.drawPixmap(Assets.background, 0, 0); g.drawPixmap(Assets.logo, 32, 20); g.drawPixmap(Assets.mainMenu, 64, 220); if(Settings.soundEnabled)

g.drawPixmap(Assets.buttons, 0, 416, 0, 0, 64, 64);

else g.drawPixmap(Assets.buttons, 0, 416, 64, 0, 64, 64);

The present() method is probably the one you've been waiting for most, but I'm afraid it isn't all that exciting. Out little game framework makes it really simple to render our main menu screen. All we do is render the background at (0,0), which will basically erase our framebuffer, so no call to Graphics.clear() is needed. Next we draw the logo and main menu entries at the coordinates shown in Figure 6-2. We end that method by drawing the sound toggle button based on the current setting. As you can see, we use the same Pixmap, but only draw the appropriate portion of it (the sound toggle button; see Figure 6-1). Now that was easy.

@Override public void pause() {

Settings.save(game.getFileIO());

The final piece we need to discuss is the pause() method. Since we can change one of the settings on that screen, we have to make sure that it gets persisted to the external storage. With our Settings class that's pretty easy!

@Override public void resume() { }

@Override public void dispose() { }

The resume() and dispose() methods don't have anything to do in this Screen.

0 0

Post a comment