package com.arretadogames.pilot.entities;
import android.util.Pair;
import com.arretadogames.pilot.config.GameSettings;
import com.arretadogames.pilot.entities.scenario.Grass;
import com.arretadogames.pilot.entities.scenario.Shrub;
import com.arretadogames.pilot.entities.scenario.Tree;
import com.arretadogames.pilot.items.BoxItem;
import com.arretadogames.pilot.levels.EntityDescriptor;
import com.arretadogames.pilot.levels.HoleDescriptor;
import com.arretadogames.pilot.levels.LevelDescriptor;
import com.arretadogames.pilot.levels.PlayerDescriptor;
import com.arretadogames.pilot.levels.WaterDescriptor;
import com.arretadogames.pilot.render.AnimationManager;
import com.arretadogames.pilot.render.AnimationSwitcher;
import org.jbox2d.common.Vec2;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
public class EntityBuilder {
private boolean isBuilt;
private LevelDescriptor levelDescriptor;
private ArrayList<Entity> entities;
private HashMap<PlayerNumber, Pair<Float, Float>> playerPositions;
public EntityBuilder(LevelDescriptor levelDescriptor) {
this.levelDescriptor = levelDescriptor;
}
public boolean isBuilt() {
return isBuilt;
}
public void buildEntities() {
entities = new ArrayList<Entity>();
playerPositions = new HashMap<PlayerNumber, Pair<Float, Float>>();
List<EntityDescriptor> levelEntities = levelDescriptor.getEntities();
List<Water> waterEntities = new ArrayList<Water>();
if (entities != null){
for (EntityDescriptor entityDescriptor : levelEntities) {
Entity entity = null;
switch (entityDescriptor.getType()) {
case BOX:
entity = new Box(entityDescriptor.getX(), entityDescriptor.getY(),
entityDescriptor.getSize());
break;
case SEED:
entity = new Coin(entityDescriptor.getX(), entityDescriptor.getY(), 10);
break;
case HOLE:
HoleDescriptor descriptor = ((HoleDescriptor) entityDescriptor);
entity = new Hole(descriptor.getX(), descriptor.getX2());
break;
case PLAYER:
playerPositions.put(((PlayerDescriptor)entityDescriptor).getPlayerNumber(),
new Pair<Float,Float>(entityDescriptor.getX(), entityDescriptor.getY()));
break;
case ONEWAY_WALL:
entity = new Platform(entityDescriptor.getX(), entityDescriptor.getY());
break;
case SPIKE:
entity = new Spike(entityDescriptor.getX(), entityDescriptor.getY());
break;
case BREAKABLE:
entity = new Breakable(entityDescriptor.getX(),entityDescriptor.getY(),0.2f,1.5f,0,false);
break;
case FINALFLAG:
entity = new FinalFlag(entityDescriptor.getX(), entityDescriptor.getY());
break;
case WATER:
entity = new Water(entityDescriptor.getX(), entityDescriptor.getY(),((WaterDescriptor)entityDescriptor).getWidth(),((WaterDescriptor)entityDescriptor).getHeight(),((WaterDescriptor)entityDescriptor).getDensity());
waterEntities.add((Water)entity);
break;
case TREE:
entity = new Tree(entityDescriptor.getX(), entityDescriptor.getY());
break;
case SHRUB:
entity = new Shrub(entityDescriptor.getX(), entityDescriptor.getY());
break;
case GRASS:
entity = new Grass(entityDescriptor.getX(), entityDescriptor.getY());
break;
case BOX_ITEM:
entity = new BoxItem(entityDescriptor.getX(), entityDescriptor.getY());
break;
case TREELOG:
entity = new TreeLog(entityDescriptor.getX(), entityDescriptor.getY(),
entityDescriptor.getSize());
break;
default:
System.out.println("Entity Builder failed to assign item: " + entityDescriptor.getType().toString());
break;
}
setEntitySprite(entity);
}
}
// Add Ground
Vec2[] groundPoints = createGroundLines(waterEntities, levelDescriptor.getLevelLength());
int amountOfPoints = groundPoints.length;
// Divide the Ground in chunks to avoid rendering it all
Vec2[] vecs = new Vec2[amountOfPoints > GameSettings.GROUND_ENTITY_THRESHOLD ? GameSettings.GROUND_ENTITY_THRESHOLD : amountOfPoints];
int internalPointer = 0;
for (int i = 0 ; i < amountOfPoints ; i++) {
vecs[internalPointer] = groundPoints[i];
if (internalPointer == GameSettings.GROUND_ENTITY_THRESHOLD - 1) {
entities.add(new Ground(vecs, vecs.length));
vecs = new Vec2[GameSettings.GROUND_ENTITY_THRESHOLD];
vecs[0] = groundPoints[i];
internalPointer = 1;
} else {
internalPointer %= GameSettings.GROUND_ENTITY_THRESHOLD;
internalPointer++;
}
}
if (internalPointer != 0) {
Vec2[] lastVec = new Vec2[internalPointer];
for (int i = 0 ; i < internalPointer ; i++)
lastVec[i] = vecs[i];
entities.add(new Ground(lastVec, internalPointer));
}
isBuilt = true;
}
private void setEntitySprite(Entity entity) {
if (entity != null) {
AnimationSwitcher sprite = null;
if (entity.getType().equals(EntityType.PLAYER)) {
if (entity instanceof LoboGuara) {
sprite = AnimationManager.getInstance().getSprite("LoboGuara");
} else if (entity instanceof AraraAzul) {
sprite = AnimationManager.getInstance().getSprite("AraraAzul");
} else if (entity instanceof TatuBola) {
sprite = AnimationManager.getInstance().getSprite("TatuBola");
} else if (entity instanceof MacacoPrego) {
sprite = AnimationManager.getInstance().getSprite("MacacoPrego");
}
} else {
sprite = AnimationManager.getInstance().getSprite(entity.getType().toString());
}
entity.setSprite(sprite);
entities.add(entity);
}
}
public List<Entity> getAllEntities() {
return entities;
}
public List<Entity> getEntitiesOfType(EntityType type) {
List<Entity> filteredEntities = new ArrayList<Entity>();
for (Entity e : entities) {
if (e.getType().equals(type)) {
filteredEntities.add(e);
}
}
return filteredEntities;
}
/**
* Create ground based on given entities
*/
public Vec2[] createGroundLines(List<Water> waterEntities, float lastX) {
// Sort Based on X
Collections.sort(waterEntities, new Comparator<Water>() {
@Override
public int compare(Water lhs, Water rhs) {
return (int) (lhs.getPosX() - rhs.getPosX());
}
});
Vec2[] groundLines = new Vec2[2 + waterEntities.size() * 4];
int groundLineIndex = 0;
// Initial Pos
Vec2 pos = new Vec2(-50, 0);
groundLines[groundLineIndex++] = pos;
float waterWidth;
float waterHeight;
for (int i = 0 ; i < waterEntities.size() ; i++) {
waterWidth = waterEntities.get(i).getWidth();
waterHeight = waterEntities.get(i).getHeight();
// Ground-Water Top Left
pos = new Vec2(
waterEntities.get(i).getPosX() - waterWidth / 2, 0);
groundLines[groundLineIndex++] = pos;
// Ground-Water Bottom Left
pos = new Vec2(waterEntities.get(i).getPosX() - waterWidth / 2,
waterEntities.get(i).getPosY() - waterHeight / 2);
groundLines[groundLineIndex++] = pos;
// Ground-Water Bottom Right
pos = new Vec2(waterEntities.get(i).getPosX() + waterWidth / 2,
waterEntities.get(i).getPosY() - waterHeight / 2);
groundLines[groundLineIndex++] = pos;
// Ground-Water Top Right
pos = new Vec2(
waterEntities.get(i).getPosX() + waterWidth / 2, 0);
groundLines[groundLineIndex++] = pos;
}
pos = new Vec2(lastX + 10, 0);
groundLines[groundLineIndex++] = pos;
return groundLines;
}
public void addPlayer(PlayerNumber number, PlayableCharacter character) {
if (!isBuilt()) {
throw new IllegalStateException("The builder must have entities built before adding players");
}
float x, y;
x = playerPositions.get(number).first;
y = playerPositions.get(number).second;
Player player = null;
switch (character) {
case LOBO_GUARA:
player = new LoboGuara(x, y, number);
break;
case ARARA_AZUL:
player = new AraraAzul(x, y, number);
break;
case MACACO_PREGO:
player = new MacacoPrego(x, y, number);
break;
case TATU_BOLA:
player = new TatuBola(x, y, number);
break;
default:
break;
}
setEntitySprite(player);
}
}