The Main Menu Screen

This is the screen that is returned by SuperJumper.getStartScreen(), so it's the first screen the player will see. It renders the background and UI elements and simply waits there for us to touch any of the UI elements. Based on which element was hit, we either change the configuration (sound enabled/disabled) or transition to a new screen. Listing 9-6 shows the code.

Listing 9-6. The Main Menu Screen package com.badlogic.androidgames.jumper;

import java.util.List;

import javax.microedition.khronos.opengles.GL10;

import com.badlogic.androidgames.framework.Game; import com.badlogic.androidgames.framework.Input.TouchEvent; import; import; import com.badlogic.androidgames.framework.impl.GLScreen; import com.badlogic.androidgames.framework.math.OverlapTester; import com.badlogic.androidgames.framework.math.Rectangle; import com.badlogic.androidgames.framework.math.Vector2;

public class MainMenuScreen extends GLScreen { Camera2D guiCam; SpriteBatcher batcher; Rectangle soundBounds; Rectangle playBounds; Rectangle highscoresBounds; Rectangle helpBounds; Vector2 touchPoint;

The class derives from GLScreen so we can acess the GLGraphics instance more easily.

There are a couple of members in this class. The first one is a Camera2D instance called guiCam. We also need a SpriteBatcher to render our background and UI elements. We'll use Rectangles to determine if the user touched a UI element. Since we use a Camera2D, we also need a Vector2 instance to transform the touch coordinates to world coordinates.

public MainMenuScreen(Game game) { super(game);

guiCam = new Camera2D(glGraphics, 320, 480);

batcher = new SpriteBatcher(glGraphics, 100);

playBounds = new Rectangle(l60 - 150, 200 + 18, 300, 36);

highscoresBounds = new Rectangle(160 - 150, 200 - 18, 300, 36);

helpBounds = new Rectangle(160 - 150, 200 - 18 - 36, 300, 36);

touchPoint = new Vector2();

In the constructor we simply set up all the members. And here's a surprise. The Camera2D instance will allow us to work in our target resolution of 320x480 pixels. All we need to do is set the view frustum width and height to the proper values. The rest is done by OpenGL ES on the fly. Note, however, that the origin is still in the bottom-left corner and the y-axis is pointing upward. We'll use such a GUI camera in all screens that have UI elements so we can lay them out in pixels instead of world coordinates. Of course, we cheat a little on screens that are not 320x480 pixels wide, but we already did that in Mr. Nom, so we don't need to feel bad about it. The Rectangles we set up for each UI element are thus given in pixel coordinates.

^Override public void update(float deltaTime) {

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

int len = touchEvents.size(); for(int i = 0; i < len; i++) {

TouchEvent event = touchEvents.get(i); if(event.type == TouchEvent.TOUCH_UP) { touchPoint.set(event.x, event.y); guiCam.touchToWorld(touchPoint);

if(OverlapTester.pointInRectangle(playBounds, touchPoint)) { Assets.playSound(Assets.clickSound); game.setScreen(new GameScreen(game)); return;

if(OverlapTester.pointInRectangle(highscoresBounds, touchPoint)) { Assets.playSound(Assets.clickSound); game.setScreen(new HighscoresScreen(game)); return;

if(OverlapTester.pointInRectangle(helpBounds, touchPoint)) { Assets.playSound(Assets.clickSound); game.setScreen(new HelpScreen(game)); return;

if(OverlapTester.pointInRectangle(soundBounds, touchPoint)) { Assets.playSound(Assets.clickSound); Settings.soundEnabled = {Settings.soundEnabled; if(Settings. soundEnabled);


Next is the update() method. We loop through the TouchEvents returned by our Input instance and check for touch-up events. In case we have such an event we first translate the touch coordinates to world coordinates. Since the camera is set up in a way so that we work in our target resolution, this transformation boils down to simply flipping the y-coordinate on a 320x480 pixel screen. On larger or smaller screens we just transform the touch coordinates to the target resolution. Once we have our world touch point, we can check it against the rectangles of the UI elements. If PLAY, HIGHSCORES, or HELP was hit, we transition to the respective screen. In case the sound button was pressed we change the setting and either resume or pause the music. Also note that we play the click sound in case a UI element was pressed via the Assets.playSound() method.

^Override public void present(float deltaTime) { GL10 gl = glGraphics.getGL(); gl.glClear(GL10. GL_COLOR_BUFFER_BIT); guiCam.setViewportAndMatrices();

gl.glEnable(GL10. GL_TEXTURE_2D);


batcher.drawSprite(160, 240, 320, 480, Assets.backgroundRegion); batcher.endBatch();


gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); batcher.beginBatch(Assets.items);

batcher.drawSprite(160, 480 - 10 - 71, 274, 142, Assets.logo); batcher.drawSprite(160, 200, 300, 110, Assets.mainMenu); batcher.drawSprite(32, 32, 64, 64, Settings.soundEnabled?Assets.soundOn:Assets.soundOff);



The present() method shouldn't really need any explanation at this point. We clear the screen, set up the projection matrices via the camera, and render the background and UI elements. Since the UI elements have transparent backgrounds, we enable blending temporarily to render them. The background does not need blending, so we don't use it to conserve some GPU cycles. Again, note that the UI elements are rendered in a coordinate system with the origin in the lower left of the screen and the y-axis pointing upward.

@Override public void pause() {;

@Override public void resume() { }

@Override public void dispose() { }

The last method that actually does something is the pause() method. Here we make sure that the settings are saved to the SD card since the user can change the sound settings on this screen.

Was this article helpful?

0 0

Post a comment