/* * Copyright © 2012 Nokia Corporation. All rights reserved. * Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation. * Oracle and Java are trademarks or registered trademarks of Oracle and/or its * affiliates. Other product and company names mentioned herein may be trademarks * or trade names of their respective owners. * See LICENSE.TXT for license information. */ package com.nokia.example.spacemission; import java.util.Timer; import java.util.TimerTask; import javax.microedition.lcdui.*; import javax.microedition.lcdui.game.GameCanvas; public class GameCanvasView extends GameCanvas implements GameStatusListener, Softkey.Listener { private static final int LEFT_SOFTKEY = -6; private static final int RIGHT_SOFTKEY = -7; private final static int DRAG_THRESHOLD = 10; private GameMIDlet midlet; private GameThread gameThread; private Game3DManager game3DManager; private GameSoundManager soundManager; private Image instructionsImage; private Image pausedImage; private Image wellDoneImage; private Image badLuckImage; private Image weaponImage; private Image firedImage; private Softkey playKey; private Softkey pauseKey; private Softkey newGameKey; private Softkey exitKey; private Timer firingTimer; private boolean firstLoad; private boolean paused; private boolean gameOverWellDone; private boolean gameOverBadLuck; private boolean weaponFired; private boolean pointerDragged; private int score; private int startX = -1; private int startY = -1; public GameCanvasView(GameMIDlet midlet, GameSoundManager soundManager, Image frameworkInstructions, Image frameworkPaused, Image frameworkWellDone, Image frameworkBadLuck, Image gameWeapon, Image firedImage) { super(false); this.setFullScreenMode(true); this.soundManager = soundManager; this.createCanvas(midlet, frameworkInstructions, frameworkPaused, frameworkWellDone, frameworkBadLuck, gameWeapon, firedImage); } /** * Create canvas */ private void createCanvas(GameMIDlet midlet, Image frameworkInstructions, Image frameworkPaused, Image frameworkWellDone, Image frameworkBadLuck, Image gameWeapon, Image firedImage) { this.pointerDragged = false; this.paused = true; this.firstLoad = true; this.weaponFired = false; this.gameOverBadLuck = false; this.gameOverWellDone = false; this.instructionsImage = frameworkInstructions; this.pausedImage = frameworkPaused; this.wellDoneImage = frameworkWellDone; this.badLuckImage = frameworkBadLuck; this.weaponImage = gameWeapon; this.firedImage = firedImage; this.midlet = midlet; this.gameThread = new GameThread(); this.game3DManager = new Game3DManager(getWidth(), getHeight()); this.game3DManager.setGameStatusListener(this); this.firingTimer = new Timer(); playKey = new Softkey("/framework/play.png", Softkey.PLAY, this, this); pauseKey = new Softkey("/framework/pause.png", Softkey.PAUSE, this, this); newGameKey = new Softkey("/framework/new_game.png", Softkey.NEW_GAME, this, this); exitKey = new Softkey("/framework/exit.png", Softkey.EXIT, this, this); playKey.setVisible(true); pauseKey.setVisible(false); newGameKey.setVisible(false); exitKey.setVisible(true); } /** * Render the canvas * @param g Graphics object */ public void paint(Graphics g) { this.game3DManager.paint(g); drawScore(g); drawWeapon(g); if (firstLoad) { //play the midi file here soundManager.playMIDISound(0); drawGreyOut(g); g.drawImage(instructionsImage, getWidth() / 2, getHeight() / 2, Graphics.HCENTER | Graphics.VCENTER); } else if (paused) { drawGreyOut(g); g.drawImage(pausedImage, getWidth() / 2, getHeight() / 2, Graphics.HCENTER | Graphics.VCENTER); } else if (gameOverWellDone) { drawGreyOut(g); g.drawImage(wellDoneImage, getWidth() / 2, getHeight() / 2, Graphics.HCENTER | Graphics.VCENTER); } else if (gameOverBadLuck) { drawGreyOut(g); g.drawImage(badLuckImage, getWidth() / 2, getHeight() / 2, Graphics.HCENTER | Graphics.VCENTER); } drawSoftkeys(g); } /** * Render the weapon * @param g */ private void drawWeapon(Graphics g) { if (weaponFired) { g.drawImage(firedImage, getWidth() / 2, getHeight() - weaponImage.getHeight() / 2 - Softkey.SOFTKEY_HEIGHT, Graphics.BOTTOM | Graphics.HCENTER); } g.drawImage(weaponImage, getWidth() / 2, getHeight() - Softkey.SOFTKEY_HEIGHT, Graphics.BOTTOM | Graphics.HCENTER); } /** * Render the grey out * @param g */ private void drawGreyOut(Graphics g) { int[] buf = new int[getWidth()]; for (int i = 0; i < getWidth(); i++) { buf[i] = 0x88ffffff; } g.drawRGB(buf, 0, 0, 0, 0, getWidth(), getHeight(), true); } /** * Render the scores * @param g */ private void drawScore(Graphics g) { Font font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_SMALL); g.setFont(font); int width = font.stringWidth("Score: "); g.setColor(27, 179, 23); g.drawRect(5, 5, width + 30, 20); g.setColor(101, 101, 101); g.fillRect(6, 6, width + 29, 19); g.setColor(27, 179, 23); g.drawString("Score: " + score, 7, 7, Graphics.TOP | Graphics.LEFT); } /** * Render the softkeys * @param g */ private void drawSoftkeys(Graphics g) { g.setColor(0x656565); g.fillRect(0, getHeight() - Softkey.SOFTKEY_HEIGHT, getWidth(), getHeight()); playKey.paint(g); pauseKey.paint(g); newGameKey.paint(g); exitKey.paint(g); int centerX = getWidth() / 2 - 1; g.drawLine(centerX, getHeight() - Softkey.SOFTKEY_HEIGHT + 5, centerX, getHeight() - 5); } /** * Check game keys for controlling movement and firing */ private void checkKeys() { if (!pointerDragged && (!gameOverWellDone || !gameOverBadLuck)) { boolean leftPressed = false; boolean rightPressed = false; boolean upPressed = false; boolean downPressed = false; int keyState = getKeyStates(); if ((keyState & FIRE_PRESSED) != 0) { fire(); } if ((keyState & GameCanvas.LEFT_PRESSED) != 0) { leftPressed = true; } if ((keyState & GameCanvas.RIGHT_PRESSED) != 0) { rightPressed = true; } if ((keyState & GameCanvas.UP_PRESSED) != 0) { upPressed = true; } if ((keyState & GameCanvas.DOWN_PRESSED) != 0) { downPressed = true; } game3DManager.setKeysPressed(leftPressed, rightPressed, upPressed, downPressed); } } /** * Update the game state */ protected void updateGame() { score = this.game3DManager.updateGame(); } /** * Render the canvas */ protected void render() { Graphics g = getGraphics(); paint(g); flushGraphics(); } /** * Stop the game loop */ public void stopGame() { this.gameThread.requestStop(); this.gameThread = null; } /** * Start/Continue playing */ public void playGame() { soundManager.stopMIDISound(0); this.paused = false; this.firstLoad = false; this.gameThread.requestPlay(); pauseKey.setVisible(true); playKey.setVisible(false); newGameKey.setVisible(false); exitKey.setVisible(false); } /** * Pause game loop */ public void pauseGame() { this.paused = true; updateGame(); this.gameThread.requestPause(); pauseKey.setVisible(false); playKey.setVisible(true); exitKey.setVisible(true); } /** * Game loop */ class GameThread extends Thread { private boolean pause = true; private boolean stop = false; private boolean started = false; public void requestPlay() { this.pause = false; if (!started) { this.start(); this.started = true; } } public void requestPause() { this.pause = true; } public void requestStop() { this.stop = true; } public void run() { long time = 0; long delay = 10; while (!stop) { time = System.currentTimeMillis(); if (!pause) { checkKeys(); updateGame(); render(); } time = delay - (System.currentTimeMillis() - time); try { Thread.sleep((time < 0 ? 0 : time)); } catch (InterruptedException e) { } } } } /** * Game over * @param reason */ public void gameOver(int reason) { if (reason == GameStatusListener.GAME_COMPLETED) { gameOverWellDone = true; gameThread.requestStop(); } else if (reason == GameStatusListener.PLAYER_DIED) { gameOverBadLuck = true; gameThread.requestStop(); } pauseKey.setVisible(false); newGameKey.setVisible(true); exitKey.setVisible(true); } /** * Prepare things for new game */ public void reset() { this.gameThread = null; this.game3DManager = null; System.gc(); this.createCanvas(midlet, instructionsImage, pausedImage, wellDoneImage, badLuckImage, weaponImage, firedImage); this.paused = false; } /** * Shoot freezing ammo */ public void fire() { weaponFired = true; game3DManager.setFirePressed(); firingTimer.schedule(new TimerTask() { public void run() { weaponFired = false; if (paused) { render(); } } }, 100); //play the first game sound here soundManager.playGameSound(0); } /** * Handle softkey clicked events * @param type */ public void clicked(int type) { switch (type) { case Softkey.PLAY: playGame(); break; case Softkey.PAUSE: pauseGame(); break; case Softkey.NEW_GAME: reset(); break; case Softkey.EXIT: midlet.notifyDestroyed(); break; default: System.out.println("Unknown softkey type"); } } /** * Map softkeys * @param key */ protected void keyPressed(int key) { switch(key) { case LEFT_SOFTKEY: if(playKey.isVisible()) { playGame(); } else if(pauseKey.isVisible()) { pauseGame(); } else if(newGameKey.isVisible()) { reset(); } render(); break; case RIGHT_SOFTKEY: if(exitKey.isVisible()) { midlet.notifyDestroyed(); } break; } } /** * Handle pressed events * @param x * @param y */ protected void pointerPressed(int x, int y) { if (!paused) { firingTimer.schedule(new TimerTask() { public void run() { if (!pointerDragged) { fire(); } } }, 100); } startX = x; startY = y; playKey.pointerPressed(x, y); pauseKey.pointerPressed(x, y); newGameKey.pointerPressed(x, y); exitKey.pointerPressed(x, y); render(); } /** * Handle dragged events * @param x * @param y */ protected void pointerDragged(int x, int y) { pointerDragged = true; if (!paused) { int dX = startX - x; int dY = startY - y; boolean leftPressed = false; boolean rightPressed = false; boolean upPressed = false; boolean downPressed = false; // Control movement by dragging if (Math.abs(dX) > Math.abs(dY)) { if (dX > DRAG_THRESHOLD) { leftPressed = true; } else if (dX < -DRAG_THRESHOLD) { rightPressed = true; } } else { if (dY > DRAG_THRESHOLD) { upPressed = true; } else if (dY < -DRAG_THRESHOLD) { downPressed = true; } } game3DManager.setKeysPressed(leftPressed, rightPressed, upPressed, downPressed); } } /** * Handle released events * @param x * @param y */ protected void pointerReleased(int x, int y) { playKey.pointerReleased(x, y); pauseKey.pointerReleased(x, y); newGameKey.pointerReleased(x, y); exitKey.pointerReleased(x, y); pointerDragged = false; render(); } protected void sizeChanged(int width, int height) { int y = height - Softkey.SOFTKEY_HEIGHT; playKey.setPosition(0, y); pauseKey.setPosition(0, y); newGameKey.setPosition(0, y); exitKey.setPosition(width / 2, y); } }