/**
* eAdventure (formerly <e-Adventure> and <e-Game>) is a research project of the
* <e-UCM> research group.
*
* Copyright 2005-2010 <e-UCM> research group.
*
* You can access a list of all the contributors to eAdventure at:
* http://e-adventure.e-ucm.es/contributors
*
* <e-UCM> is a research group of the Department of Software Engineering
* and Artificial Intelligence at the Complutense University of Madrid
* (School of Computer Science).
*
* C Profesor Jose Garcia Santesmases sn,
* 28040 Madrid (Madrid), Spain.
*
* For more info please visit: <http://e-adventure.e-ucm.es> or
* <http://www.e-ucm.es>
*
* ****************************************************************************
*
* This file is part of eAdventure, version 2.0
*
* eAdventure is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* eAdventure is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with eAdventure. If not, see <http://www.gnu.org/licenses/>.
*/
package es.eucm.ead.engine.gameobjects.debuggers;
import com.google.inject.Inject;
import es.eucm.ead.engine.assets.AssetHandler;
import es.eucm.ead.engine.factories.EventFactory;
import es.eucm.ead.engine.factories.SceneElementFactory;
import es.eucm.ead.engine.factories.TrajectoryFactory;
import es.eucm.ead.engine.game.Game;
import es.eucm.ead.engine.gameobjects.sceneelements.SceneElementGO;
import es.eucm.ead.engine.gameobjects.trajectories.TrajectoryGO;
import es.eucm.ead.engine.gameobjects.trajectories.polygon.PolygonTrajectoryGO;
import es.eucm.ead.model.assets.drawable.basics.Caption;
import es.eucm.ead.model.assets.drawable.basics.EAdShape;
import es.eucm.ead.model.assets.drawable.basics.shapes.BezierShape;
import es.eucm.ead.model.assets.drawable.basics.shapes.CircleShape;
import es.eucm.ead.model.assets.drawable.basics.shapes.LineShape;
import es.eucm.ead.model.assets.drawable.basics.shapes.RectangleShape;
import es.eucm.ead.model.assets.drawable.compounds.ComposedDrawable;
import es.eucm.ead.model.assets.drawable.compounds.EAdComposedDrawable;
import es.eucm.ead.model.elements.extra.EAdList;
import es.eucm.ead.model.elements.scenes.*;
import es.eucm.ead.model.elements.trajectories.*;
import es.eucm.ead.model.params.fills.ColorFill;
import es.eucm.ead.model.params.fills.Paint;
import es.eucm.ead.model.params.paint.EAdPaint;
import es.eucm.ead.model.params.util.Rectangle;
import es.eucm.ead.tools.pathfinding.PathFinder;
import org.poly2tri.geometry.polygon.Polygon;
import org.poly2tri.triangulation.delaunay.DelaunayTriangle;
import org.poly2tri.triangulation.point.TPoint;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
/**
*
* A debugger showing representations of the trajectories in the game
*
*/
public class TrajectoryDebuggerGO extends SceneElementGO {
private TrajectoryFactory trajectoryFactory;
private Scene currentScene;
private Trajectory currentTrajectory;
private List<EAdShape> barriers;
private List<Float> currentPath;
private String currentPathString;
private TrajectoryGO<? extends Trajectory> trajectoryGO;
private SceneElementGO currentPathGO;
@Inject
public TrajectoryDebuggerGO(AssetHandler assetHandler,
SceneElementFactory sceneElementFactory, Game game,
EventFactory eventFactory, TrajectoryFactory trajectoryFactory) {
super(assetHandler, sceneElementFactory, game, eventFactory);
this.trajectoryFactory = trajectoryFactory;
barriers = new ArrayList<EAdShape>();
}
public void setElement(SceneElement element) {
super.setElement(element);
SceneElement e = new SceneElement();
currentPathGO = sceneElementFactory.get(e);
}
public void act(float delta) {
super.act(delta);
Scene newScene = (Scene) gui.getScene().getElement();
Trajectory newTrajectory = gameState.getValue(currentScene,
Scene.VAR_TRAJECTORY_DEFINITION, null);
if (currentScene != newScene || newTrajectory != currentTrajectory) {
currentTrajectory = newTrajectory;
currentScene = newScene;
getChildren().clear();
trajectoryGO = null;
if (currentTrajectory != null && currentScene != null) {
createTrajectory();
addSceneElement(currentPathGO);
trajectoryGO = trajectoryFactory.get(currentTrajectory);
}
}
if (currentTrajectory instanceof NodeTrajectory) {
int i = 0;
for (SceneElement e : ((NodeTrajectory) currentTrajectory)
.getBarriers()) {
barriers.get(i).setPaint(
gameState.getValue(e, NodeTrajectory.VAR_BARRIER_ON,
false) ? ColorFill.YELLOW
: ColorFill.TRANSPARENT);
i++;
}
}
// Update current path
if (trajectoryGO != null) {
currentPath = trajectoryGO.getCurrentPath();
if (currentPathString == null
|| (!currentPath.toString().equals(currentPathString))) {
currentPathString = currentPath.toString();
currentPathGO.getChildren().clear();
if (currentPath.size() > 0) {
float lastX = currentPath.get(0);
float lastY = currentPath.get(1);
ComposedDrawable pathDrawable = new ComposedDrawable();
for (int i = 2; i < currentPath.size(); i += 2) {
float x = currentPath.get(i);
float y = currentPath.get(i + 1);
LineShape l = new LineShape((int) lastX, (int) lastY,
(int) x, (int) y, 3);
l.setPaint(Paint.BLACK_ON_WHITE);
pathDrawable.addDrawable(l);
lastX = x;
lastY = y;
}
currentPathGO
.addSceneElement(new SceneElement(pathDrawable));
}
}
}
}
private void createTrajectory() {
if (currentTrajectory instanceof SimpleTrajectory) {
SceneElementGO representation = getSimpleTrajectory((SimpleTrajectory) currentTrajectory);
addSceneElement(representation);
} else if (currentTrajectory instanceof NodeTrajectory) {
createNodes((NodeTrajectory) currentTrajectory);
addInfluenceAreas(((Scene) gui.getScene().getElement())
.getSceneElements());
} else if (currentTrajectory instanceof PolygonTrajectory) {
PolygonTrajectory def = (PolygonTrajectory) currentTrajectory;
PolygonTrajectoryGO trajectoryGO = (PolygonTrajectoryGO) trajectoryFactory
.get(def);
PathFinder pathFinder = trajectoryGO.getPathFinder();
// Add Polygon
Polygon p = pathFinder.getPolygon();
ComposedDrawable polygon = new ComposedDrawable();
Paint paint = new Paint(new ColorFill(0, 200, 0, 100),
ColorFill.GREEN);
for (DelaunayTriangle t : p.getTriangles()) {
BezierShape triangle = new BezierShape();
triangle.setPaint(paint);
triangle.moveTo((int) t.points[0].getX(), (int) t.points[0]
.getY());
triangle.lineTo((int) t.points[1].getX(), (int) t.points[1]
.getY());
triangle.lineTo((int) t.points[2].getX(), (int) t.points[2]
.getY());
polygon.addDrawable(triangle);
}
paint = new Paint(new ColorFill(200, 0, 0, 100), ColorFill.RED);
for (DelaunayTriangle n : pathFinder.getPolygon().getTriangles()) {
for (DelaunayTriangle t : n.neighbors) {
if (t != null && !t.isInterior()) {
BezierShape triangle = new BezierShape();
triangle.setPaint(paint);
triangle.moveTo((int) t.points[0].getX(),
(int) t.points[0].getY());
triangle.lineTo((int) t.points[1].getX(),
(int) t.points[1].getY());
triangle.lineTo((int) t.points[2].getX(),
(int) t.points[2].getY());
polygon.addDrawable(triangle);
}
}
}
SceneElement area = new SceneElement(polygon);
addSceneElement(sceneElementFactory.get(area));
ComposedDrawable centers = new ComposedDrawable();
ComposedDrawable edges = new ComposedDrawable();
ComposedDrawable graph = new ComposedDrawable();
graph.addDrawable(edges);
graph.addDrawable(centers);
CircleShape center = new CircleShape(4, ColorFill.ORANGE);
for (Entry<DelaunayTriangle, List<DelaunayTriangle>> entry : pathFinder
.getSucessorsMap().entrySet()) {
DelaunayTriangle t = entry.getKey();
List<DelaunayTriangle> sucessors = entry.getValue();
TPoint centroid = t.centroid();
centers.addDrawable(center, (int) (centroid.getX() - 2),
(int) (centroid.getY() - 2));
for (DelaunayTriangle s : sucessors) {
TPoint ncentroid = s.centroid();
LineShape line = new LineShape((int) centroid.getX(),
(int) centroid.getY(), (int) ncentroid.getX(),
(int) ncentroid.getY(), 2);
line.setPaint(ColorFill.BLACK);
edges.addDrawable(line);
}
}
SceneElement graphElement = new SceneElement(graph);
addSceneElement(sceneElementFactory.get(graphElement));
}
}
private SceneElementGO getSimpleTrajectory(SimpleTrajectory def) {
SceneElementGO root = sceneElementFactory.get(new SceneElement());
String text = "";
if (def.isOnlyHorizontal()) {
text += "/ Only horizontal";
}
if (def.isFreeWalk()) {
text += "/ Free walk ";
}
if (!"".equals(text)) {
SceneElement title = new SceneElement(new Caption(text));
title.setPosition(10, 10);
root.addSceneElement(sceneElementFactory.get(title));
}
if (def.isOnlyHorizontal() && !def.isFreeWalk()) {
LineShape line = new LineShape(def.getLeft(), 40, def.getRight(),
40, 5);
line.setPaint(new ColorFill(0, 200, 0, 100));
SceneElement lineElement = new SceneElement(line);
root.addSceneElement(sceneElementFactory.get(lineElement));
}
if (!def.isOnlyHorizontal() && !def.isFreeWalk()) {
if (def.getRight() > def.getLeft()
&& def.getTop() < def.getBottom()) {
RectangleShape area = new RectangleShape(def.getRight()
- def.getLeft(), def.getBottom() - def.getTop(),
new ColorFill(0, 200, 0, 100));
SceneElement areaElement = new SceneElement(area);
areaElement.setPosition(def.getLeft(), def.getTop());
root.addSceneElement(sceneElementFactory.get(areaElement));
}
}
return root;
}
private void addInfluenceAreas(EAdList<SceneElement> sceneElements) {
EAdPaint p = new ColorFill(0, 0, 200, 100);
for (SceneElement sceneElement : sceneElements) {
Rectangle rectangle = gameState.getValue(sceneElement,
NodeTrajectory.VAR_INFLUENCE_AREA, null);
if (rectangle != null) {
RectangleShape shape = new RectangleShape(rectangle.getWidth(),
rectangle.getHeight());
shape.setPaint(p);
SceneElement area = new SceneElement(shape);
area.putProperty(SceneElement.VAR_ENABLE, false);
area.setPosition(rectangle.getX(), rectangle.getY());
addSceneElement(sceneElementFactory.get(area));
}
}
}
private void createNodes(NodeTrajectory trajectory) {
EAdComposedDrawable map = new ComposedDrawable();
for (Side s : trajectory.getSides()) {
int x1 = s.getIdStart().getX();
int y1 = s.getIdStart().getY();
int x2 = s.getIdEnd().getX();
int y2 = s.getIdEnd().getY();
LineShape line = new LineShape(x1, y1, x2, y2, 4);
line.setPaint(ColorFill.DARK_BROWN);
map.addDrawable(line);
}
for (Node n : trajectory.getNodes()) {
CircleShape circle = new CircleShape(20);
ColorFill color = trajectory.getInitial() == n ? ColorFill.RED
: ColorFill.BLUE;
circle.setPaint(new Paint(color, ColorFill.BLACK, 2));
map.addDrawable(circle, n.getX() - 20, n.getY() - 20);
}
SceneElement mapElement = new SceneElement(map);
mapElement.setEnable(false);
for (SceneElement e : trajectory.getBarriers()) {
SceneElementDef def = e.getDefinition();
EAdShape s = (EAdShape) def.getAsset(SceneElementDef.appearance);
EAdShape barrier = s.copyShape();
barrier.setPaint(ColorFill.YELLOW);
barriers.add(barrier);
SceneElementGO go = (SceneElementGO) sceneElementFactory.get(e);
map.addDrawable(barrier, (int) go.getX(), (int) go.getY());
}
for (SceneElement e : ((Scene) gui.getScene().getElement())
.getSceneElements()) {
Rectangle r = (Rectangle) e.getProperties().get(
NodeTrajectory.VAR_INFLUENCE_AREA);
if (r != null) {
RectangleShape influenceArea = new RectangleShape(r.width,
r.height, new ColorFill(0, 0, 200, 122));
map.addDrawable(influenceArea, r.x, r.y);
}
}
addSceneElement(sceneElementFactory.get(mapElement));
}
}