/* * Copyright © 2011 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.battletank.game; import com.nokia.example.battletank.Main; import com.nokia.example.battletank.game.dialog.GameOverDialog; import com.nokia.example.battletank.game.dialog.LevelCompleteDialog; import com.nokia.example.battletank.game.entities.Entity; import com.nokia.example.battletank.game.entities.Enemy; import com.nokia.example.battletank.game.entities.Bonus; import com.nokia.example.battletank.game.entities.ExplosionsManager; import com.nokia.example.battletank.game.entities.BulletManager; import com.nokia.example.battletank.game.entities.TreeManager; import com.nokia.example.battletank.game.entities.Bullet; import com.nokia.example.battletank.game.entities.Base; import com.nokia.example.battletank.game.entities.BonusManager; import com.nokia.example.battletank.game.entities.EnemyManager; import com.nokia.example.battletank.game.entities.Tank; import com.nokia.example.battletank.game.entities.Player; import com.nokia.example.battletank.game.audio.AudioManager; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import javax.microedition.lcdui.AlertType; import javax.microedition.lcdui.Graphics; import javax.microedition.lcdui.game.LayerManager; public class Game { private static final int POINTS_PER_LIFE = 100; private Resources resources; private final int soundPadding; public boolean soundsEnabled = true; private int levelNumber = 0; private int lives; private int score = 0; private int highScore = 0; private int enemiesInReserve; private Level level; private Player player; private EnemyManager enemyManager; private Base base; private Hud hud; private GameOverDialog gameOverDialog; private LevelCompleteDialog levelCompleteDialog; private LayerManager layerManager; private int viewportLeft; private int viewportTop; private int viewportWidth; private int viewportHeight; private BulletManager bulletManager; private ExplosionsManager explosionManager; private BonusManager bonusManager; private TreeManager treeManager; public Game(int w, int h) { resources = new Resources(w, h); soundPadding = resources.gridSizeInPixels * 20; setViewportSize(w, h); hud = new Hud(resources, w, h); gameOverDialog = new GameOverDialog(resources); levelCompleteDialog = new LevelCompleteDialog(resources); } public void render(Graphics g) { level.refresh(); bulletManager.refresh(); explosionManager.refresh(); bonusManager.refresh(); base.refresh(); player.refresh(); enemyManager.refresh(); refreshViewport(); clearScreen(g); layerManager.paint(g, 0, 0); gameOverDialog.paint(g, viewportWidth, viewportHeight); levelCompleteDialog.paint(g, viewportWidth, viewportHeight); hud.paint(g, viewportWidth, viewportHeight); } private void clearScreen(Graphics g) { g.setColor(0x00000000); g.fillRect(0, 0, viewportWidth, viewportHeight); } public void update(int keyStates) { bulletManager.update(); bonusManager.update(); base.update(); player.update(keyStates); enemyManager.update(); AudioManager.playEffects(); } public void leftSoftkeyPressed() throws ProtectedContentException, IOException { if(isLevelComplete()) { nextLevel(); } else if(isGameOver()) { newGame(); } } public void newGame() throws ProtectedContentException, IOException { gameOverDialog.hide(); levelCompleteDialog.hide(); levelNumber = 1; lives = 3; score = 0; loadLevel(); } public void nextLevel() throws ProtectedContentException, IOException { levelCompleteDialog.hide(); levelNumber++; lives++; loadLevel(); } private void spawnTank(Tank tank) { if(tank == player) { if(lives == 0) { showGameOverDialog(); return; } player.spawn(); lives--; hud.lives = lives; } else { if(enemiesInReserve == 0) return; ((Enemy) tank).spawn(Levels.getEnemyType(levelNumber, enemiesInReserve)); enemiesInReserve--; } } private void loadLevel() throws ProtectedContentException, IOException { this.enemiesInReserve = Levels.getTotalEnemies(levelNumber); level = Level.load(levelNumber, resources); createBase(); createPlayer(); createEnemies(); createManagers(); hud.score = score; hud.enemies = getNumberOfEnemies(); hud.leftButton = Hud.NONE; startPlaying(); } private int getNumberOfEnemies() { return enemiesInReserve + enemyManager.numberOfAlive(); } private void createBase() { base = new Base(level, resources); } private void createPlayer() { player = new Player(level, resources, createTankListener()); } private void createEnemies() { enemyManager = new EnemyManager(level, Levels.getConcurrentEnemies(levelNumber), resources, createTankListener()); } private Tank.Listener createTankListener() { return new Tank.Listener() { public void destroyed(Tank tank) { spawnTank(tank); } public boolean collidesWithAnything(Tank tank, int x, int y, int w, int h) { if(level.collides(x, y, w, h) || base.collidesWith(x, y, w, h)) return true; if(tank != player && player.collidesWith(x, y, w, h)) return true; if(enemyManager.collidesWith(tank, x, y, w, h)) return true; return false; } public boolean isInWater(Tank tank) { return level.isInWater(tank); } public void fireABullet(Tank tank) { bulletManager.fire(tank); AudioManager.bufferEffect(AudioManager.CANNON, getVolume(tank)/2); } }; } private Bullet.Listener createBulletListener() { return new Bullet.Listener() { public boolean collide(Bullet bullet) { boolean collided = false; if(level.collideAndDestroy(bullet)) { collided = true; } else if(base.collidesWith(bullet)) { destroyBase(); collided = true; } else if(player.collidesWith(bullet)) { destroyPlayer(); collided = true; } else { Enemy enemy = enemyManager.collidesWith(bullet); if(enemy != null) { collided = true; if(bullet.firedBy == player) destroyEnemy(enemy); } } if(collided) { explosionManager.show(bullet); AudioManager.bufferEffect(AudioManager.EXPLOSION_SMALL, getVolume(bullet)); } return collided; } }; } private Bonus.Listener createBonusListener() { return new Bonus.Listener() { public boolean collidesWithPlayer(Bonus bonus) { if(player.isAlive() && player.collidesWith(bonus)) { switch(bonus.getType()) { case Bonus.AMMO: player.superAmmo(); break; case Bonus.CLOCK: enemyManager.freezeEnemies(); break; case Bonus.GRENADE: Enemy[] enemies = enemyManager.all(); for(int i = 0; i < enemies.length; i++) { destroyEnemy(enemies[i]); } break; case Bonus.LIFE: lives++; hud.lives = lives; break; case Bonus.SHOVEL: base.protect(); break; case Bonus.STAR: player.superTank(); break; } return true; } return false; } }; } private void destroyBase() { if(base.destroy()) { explosionManager.show(base); AudioManager.bufferEffect(AudioManager.EXPLOSION_LARGE, getVolume(base)); showGameOverDialog(); } } private void destroyPlayer() { if(player.destroy()) { explosionManager.show(player); AudioManager.bufferEffect(AudioManager.EXPLOSION_LARGE, 0); } } private void destroyEnemy(Enemy enemy) { if(enemy.destroy()) { explosionManager.show(enemy); AudioManager.bufferEffect(AudioManager.EXPLOSION_LARGE, getVolume(enemy)); hud.enemies = getNumberOfEnemies(); if(!isGameOver()) { score += enemy.getPoints(); if(hud.enemies == 0) { score += lives*POINTS_PER_LIFE; showLevelCompleteDialog(); } hud.score = score; } } } private void startPlaying() { spawnTank(player); Enemy[] enemies = enemyManager.all(); for (int i = 0; i < enemies.length; i++) { spawnTank(enemies[i]); } } public boolean isGameOver() { return gameOverDialog.isVisible(); } public boolean isLevelComplete() { return levelCompleteDialog.isVisible(); } private void showGameOverDialog() { levelCompleteDialog.hide(); hud.leftButton = Hud.NEWGAME; bonusManager.stopSpawning(); if(!gameOverDialog.isVisible()) { highScore = Math.max(score, highScore); gameOverDialog.highScore = highScore; gameOverDialog.show(score, levelNumber); } } private void showLevelCompleteDialog() { bonusManager.stopSpawning(); hud.leftButton = Hud.CONTINUE; if(!levelCompleteDialog.isVisible()) levelCompleteDialog.show(score, levelNumber); } private void createManagers() { final int numberOfTanks = 1 + level.getEnemySpawnPointsLength(); bulletManager = new BulletManager(2*numberOfTanks, resources, createBulletListener()); explosionManager = new ExplosionsManager(2*numberOfTanks, resources); bonusManager = new BonusManager(level, resources, createBonusListener()); treeManager = new TreeManager(level, resources); layerManager = new LayerManager(); treeManager.appendTo(layerManager); treeManager.refresh(); bonusManager.appendTo(layerManager); explosionManager.appendTo(layerManager); layerManager.append(base.getSprite()); layerManager.append(player.getSprite()); enemyManager.appendTo(layerManager); bulletManager.appendTo(layerManager); layerManager.append(level.getWallLayer()); layerManager.append(level.getGroundLayer()); } public final void setViewportSize(int w, int h) { viewportWidth = w; viewportHeight = h; } private void refreshViewport() { setViewportCenter(player.getCenterX(), player.getCenterY()); } private void setViewportCenter(int x, int y) { final int maxLeft = level.widthInPixels - viewportWidth; viewportLeft = maxLeft > 0 ? Math.max(Math.min(x - viewportWidth/2, maxLeft), 0) : maxLeft/2; final int maxTop = level.heightInPixels - viewportHeight; viewportTop = maxTop > 0 ? Math.max(Math.min(y - viewportHeight/2, maxTop), 0) : maxTop/2; layerManager.setViewWindow(viewportLeft, viewportTop, maxLeft > 0 ? viewportWidth : level.widthInPixels - viewportLeft, maxTop > 0 ? viewportHeight : level.heightInPixels - viewportTop); } public int getVolume(Entity e) { int x = e.getCenterX(); int dx = viewportLeft - x; if(dx < 0) { dx = x - viewportLeft - viewportWidth; if(dx < 0) dx = 0; } int y = e.getCenterY(); int dy = viewportTop - y; if(dy < 0) { dy = y - viewportTop - viewportHeight; if(dy < 0) dy = 0; } if(dx > soundPadding || dy > soundPadding) return 0; return 100 - 100*(dx^2 + dy^2)/(2*soundPadding^2); } public byte[] getState() { ByteArrayOutputStream bout = null; try { bout = new ByteArrayOutputStream(); DataOutputStream dout = new DataOutputStream(bout); dout.writeBoolean(Main.isTrial()); dout.writeInt(levelNumber); dout.writeInt(lives); dout.writeInt(score); dout.writeInt(highScore); dout.writeInt(enemiesInReserve); level.writeTo(dout); player.writeTo(dout); enemyManager.writeTo(dout); base.writeTo(dout); bonusManager.writeTo(dout); treeManager.writeTo(dout); dout.writeBoolean(isGameOver()); dout.writeBoolean(isLevelComplete()); dout.writeBoolean(soundsEnabled); return bout.toByteArray(); } catch (IOException e) { } finally { try { if(bout != null) bout.close(); } catch (IOException e) { } } return new byte[0]; } public boolean load(byte[] record) { if(record == null) return false; try { DataInputStream din = new DataInputStream(new ByteArrayInputStream(record)); Main.setTrial(din.readBoolean()); levelNumber = din.readInt(); lives = din.readInt(); score = din.readInt(); highScore = din.readInt(); enemiesInReserve = din.readInt(); level = Level.readFrom(din, resources); createPlayer(); player.readFrom(din); createEnemies(); enemyManager.readFrom(din); createBase(); base.readFrom(din); createManagers(); bonusManager.readFrom(din); treeManager.readFrom(din); treeManager.refresh(); if(din.readBoolean()) showGameOverDialog(); if(din.readBoolean()) showLevelCompleteDialog(); soundsEnabled = din.readBoolean(); hud.lives = lives; hud.score = score; hud.enemies = getNumberOfEnemies(); return true; } catch (IOException e) { } return false; } }