package com.arretadogames.pilot.world; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import android.graphics.Color; import android.util.SparseArray; import com.arretadogames.pilot.R; import com.arretadogames.pilot.entities.Entity; import com.arretadogames.pilot.entities.EntityBuilder; import com.arretadogames.pilot.entities.EntityType; import com.arretadogames.pilot.entities.PlayableCharacter; import com.arretadogames.pilot.entities.PlayableItem; import com.arretadogames.pilot.entities.Player; import com.arretadogames.pilot.entities.PlayerNumber; import com.arretadogames.pilot.entities.Steppable; import com.arretadogames.pilot.entities.effects.EffectDescriptor; import com.arretadogames.pilot.entities.effects.EffectManager; import com.arretadogames.pilot.levels.LevelDescriptor; import com.arretadogames.pilot.physics.PhysicalWorld; import com.arretadogames.pilot.render.AnimationManager; import com.arretadogames.pilot.render.GameCamera; import com.arretadogames.pilot.render.PhysicsRect; import com.arretadogames.pilot.render.opengl.GLCanvas; import com.arretadogames.pilot.screens.FinishRaceScreen; import com.arretadogames.pilot.screens.GameScreen; import com.arretadogames.pilot.screens.GameWorldUI; import com.arretadogames.pilot.screens.InputEventHandler; import com.arretadogames.pilot.ui.GameButtonListener; import com.arretadogames.pilot.ui.GameHUDButton; import com.arretadogames.pilot.util.Profiler; import com.arretadogames.pilot.util.Profiler.ProfileType; import com.arretadogames.pilot.weathers.Storm; import com.arretadogames.pilot.weathers.Weather; /** * GameWorld class represents the World in our Game */ public class GameWorld extends GameScreen implements GameHUDButton, GameButtonListener { private int backgroundId; private GameWorldUI ui; private PhysicalWorld pWorld; private Collection<Entity> worldEntities; private Collection<Steppable> steppables; private HashMap<PlayerNumber, Player> players; private HashMap<PlayerNumber, PlayableCharacter> selectedCharacters; private HashMap<PlayerNumber, List<PlayableItem>> selectedItems; private GameCamera gameCamera; private FinishRaceScreen finishRaceScreen; private float flagPos; private float totalElapsedSeconds; private boolean isInitialized; private LevelDescriptor level; private boolean activatePlayer1Item; private boolean activatePlayer2Item; private Weather weather; private RaceStartManager raceStartManager; public GameWorld() { backgroundId = R.drawable.mountains_repeatable; pWorld = PhysicalWorld.getInstance(); totalElapsedSeconds = 0; weather = new Storm(); isInitialized = false; } @Override public void onLoading() { gameCamera = new GameCamera(this, backgroundId); finishRaceScreen = new FinishRaceScreen(); initialize(); } @Override public void onUnloading() { totalElapsedSeconds = 0; isInitialized = false; pWorld.removeAll(); flagPos = 0; players.clear(); steppables.clear(); worldEntities.clear(); gameCamera = null; finishWorld = false; System.gc(); } public void initialize() { if (isInitialized || selectedCharacters == null || level == null || selectedItems == null) return; EffectManager.getInstance().reset(); AnimationManager.getInstance().loadXml(); load(level); isInitialized = true; activatePlayer1Item = false; activatePlayer2Item = false; setPlayersAsCurrentEntitiesToWatch(); ui = new GameWorldUI(this); raceStartManager = new RaceStartManager(this, ui); } private void load(LevelDescriptor ld) { if (!ld.isLoaded()) ld.load(); createEntities(ld); PhysicalWorld.getInstance().sleepAllEntities(); } private void createEntities(LevelDescriptor ld) { EntityBuilder builder = new EntityBuilder(ld); builder.buildEntities(); builder.addPlayer(PlayerNumber.ONE, selectedCharacters.get(PlayerNumber.ONE)); builder.addPlayer(PlayerNumber.TWO, selectedCharacters.get(PlayerNumber.TWO)); worldEntities = builder.getAllEntities(); steppables = new ArrayList<Steppable>(); players = new HashMap<PlayerNumber, Player>(); for (Entity entity : worldEntities) { if (entity instanceof Steppable) { steppables.add((Steppable)entity); } if (entity.getType().equals(EntityType.PLAYER)) { // If is a player Player p = (Player) entity; players.put(p.getNumber(), p); } else if (entity.getType().equals(EntityType.FINALFLAG)) { flagPos = entity.getPosX(); } } // Add Arrows PhysicsRect phrect = new PhysicsRect(0.4f, 0.8f); Player p1 = players.get(PlayerNumber.ONE); Player p2 = players.get(PlayerNumber.TWO); EffectDescriptor descriptor = new EffectDescriptor(); descriptor.type = "Arrow"; descriptor.position = p1.body.getPosition(); descriptor.pRect = phrect; descriptor.yOffset = 1; descriptor.duration = 5; descriptor.color = Color.BLUE; EffectManager.getInstance().addEffect(descriptor); descriptor = descriptor.clone(); descriptor.position = p2.body.getPosition(); descriptor.color = Color.RED; EffectManager.getInstance().addEffect(descriptor); } @Override public void render(GLCanvas canvas, float timeElapsed) { Profiler.initTick(ProfileType.RENDER); weather.drawBackground(canvas); if (!ui.isPauseHidden()) { gameCamera.render(canvas, 0); // Draw a fixed frame - Dont move anything } else { gameCamera.render(canvas, timeElapsed); } Profiler.profileFromLastTick(ProfileType.RENDER, "Camera Render Time"); Profiler.initTick(ProfileType.RENDER); if (finishWorld) { finishRaceScreen.render(canvas, timeElapsed); } else { raceStartManager.render(canvas, timeElapsed); ui.render(canvas, timeElapsed); } Profiler.profileFromLastTick(ProfileType.RENDER, "UI Render Time"); Profiler.initTick(ProfileType.RENDER); Profiler.profileFromLastTick(ProfileType.RENDER, "Pause Screen Render Time"); } public float getTotalElapsedTime() { return totalElapsedSeconds; } @Override public void step(float timeElapsed) { if (finishWorld) return; totalElapsedSeconds += timeElapsed; if (ui.isPauseHidden()) { if (activatePlayer1Item || activatePlayer2Item) activateItems(); for (Steppable p : steppables) p.step(timeElapsed); gameCamera.step(timeElapsed); ui.step(timeElapsed); raceStartManager.step(timeElapsed); pWorld.step(timeElapsed); } removeDeadEntities(); boolean hasFinished = true; for (Player p : players.values()) { hasFinished &= (p.hasFinished() || p.isDead()); // if all have finished or dead } if (hasFinished) onLevelFinished(); } private void activateItems() { Player p; if (activatePlayer1Item) { p = getPlayers().get(PlayerNumber.ONE); p.getItem().activate(p, this); } if (activatePlayer2Item) { p = getPlayers().get(PlayerNumber.TWO); p.getItem().activate(p, this); } activatePlayer1Item = activatePlayer2Item = false; } private void removeDeadEntities(){ Iterator<Entity> it = pWorld.getDeadEntities(); while(it.hasNext()){ Entity e = it.next(); pWorld.destroyEntity(e); worldEntities.remove(e); if(e instanceof Steppable) steppables.remove((Steppable)e); for ( PlayerNumber p : players.keySet() ){ if ( players.get(p).equals(e) ){ players.get(p).kill(); break; } } } pWorld.clearDeadEntities(); } @Override public void input(InputEventHandler event) { if (!finishWorld) { ui.input(event); } else { finishRaceScreen.input(event); } } @Override public void onPause() { ui.onPause(); } public HashMap<PlayerNumber, Player> getPlayers(){ return players; } public void setPlayersAsCurrentEntitiesToWatch(){ HashMap<PlayerNumber, Player> players = getPlayers(); SparseArray<Player> toWatch = new SparseArray<Player>(); for (PlayerNumber n : players.keySet() ){ toWatch.put(n.getValue(), players.get(n)); } } public Collection<Entity> getEntities(){ return worldEntities; } private boolean finishWorld = false; public void onLevelFinished() { if (finishWorld) return; finishWorld = true; Player p1 = players.get(PlayerNumber.ONE); Player p2 = players.get(PlayerNumber.TWO); finishRaceScreen.disableGoOn(); finishRaceScreen.activate(); if(p1.getTimeFinished() <= p2.getTimeFinished()) { finishRaceScreen.setRaceWinner(PlayerNumber.ONE, p1); } else { finishRaceScreen.setRaceWinner(PlayerNumber.TWO, p2); } } public void setLevel(LevelDescriptor level) { this.level = level; } public void setSelectedCharacters(HashMap<PlayerNumber, PlayableCharacter> selectedCharacters) { this.selectedCharacters = selectedCharacters; } public void setSelectedItems(HashMap<PlayerNumber, List<PlayableItem>> selectedItems) { this.selectedItems = selectedItems; } public float getFlagPos(){ return flagPos; } @Override public void onClick(int buttonId, boolean pressed) { Player p; if (buttonId == GameWorldUI.BT_PLAYER_1_ACT) { p = getPlayers().get(PlayerNumber.ONE); if (p != null) { p.setAct(pressed); } } else if (buttonId == GameWorldUI.BT_PLAYER_1_JUMP) { p = getPlayers().get(PlayerNumber.ONE); if (p != null) { p.setJumping(pressed); } } else if (buttonId == GameWorldUI.BT_PLAYER_1_ITEM) { p = getPlayers().get(PlayerNumber.ONE); if (p != null && p.getItem() != null) { activatePlayer1Item = pressed; } } else if (buttonId == GameWorldUI.BT_PLAYER_2_ACT) { p = getPlayers().get(PlayerNumber.TWO); if (p != null) { p.setAct(pressed); } } else if (buttonId == GameWorldUI.BT_PLAYER_2_JUMP) { p = getPlayers().get(PlayerNumber.TWO); if (p != null) { p.setJumping(pressed); } } else if (buttonId == GameWorldUI.BT_PLAYER_2_ITEM) { p = getPlayers().get(PlayerNumber.TWO); if (p != null && p.getItem() != null) { activatePlayer2Item = pressed; } } } @Override public void onClick(int buttonId) { } public GameWorldUI getUI() { return ui; } public GameCamera getCamera() { return gameCamera; } }