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;
}
}