package loon.action.map.tmx.renderers;
import loon.LObject;
import loon.LSystem;
import loon.LTexture;
import loon.LTextures;
import loon.action.map.Field2D;
import loon.action.map.tmx.TMXImageLayer;
import loon.action.map.tmx.TMXMap;
import loon.action.map.tmx.TMXMapLayer;
import loon.action.map.tmx.TMXTileLayer;
import loon.action.map.tmx.TMXTileSet;
import loon.action.map.tmx.tiles.TMXAnimationFrame;
import loon.action.map.tmx.tiles.TMXTile;
import loon.action.sprite.ISprite;
import loon.canvas.LColor;
import loon.geom.RectBox;
import loon.opengl.GLEx;
import loon.utils.ObjectMap;
import loon.utils.TimeUtils;
public abstract class TMXMapRenderer extends LObject<ISprite> implements
ISprite {
protected int lastHashCode = 1;
protected static class TileAnimator {
private TMXTile tile;
private int currentFrameIndex;
private float elapsedDuration;
public TileAnimator(TMXTile tile) {
this.tile = tile;
elapsedDuration = 0;
currentFrameIndex = 0;
}
public void update(long delta) {
elapsedDuration += TimeUtils.convert(delta,
TimeUtils.getDefaultTimeUnit(), TimeUtils.Unit.MILLIS);
if (elapsedDuration >= tile.getFrames().get(currentFrameIndex)
.getDuration()) {
currentFrameIndex = (currentFrameIndex + 1)
% tile.getFrames().size;
elapsedDuration = 0;
}
}
public TMXAnimationFrame getCurrentFrame() {
return tile.getFrames().get(currentFrameIndex);
}
}
protected abstract void renderTileLayer(GLEx gl, TMXTileLayer tileLayer);
protected abstract void renderImageLayer(GLEx gl, TMXImageLayer imageLayer);
protected TMXMap map;
protected ObjectMap<String, LTexture> textureMap;
protected ObjectMap<TMXTile, TileAnimator> tileAnimators;
protected boolean visible;
protected float scaleX = 1f;
protected float scaleY = 1f;
protected LColor baseColor = new LColor(LColor.white);
public TMXMapRenderer(TMXMap map) {
this.textureMap = new ObjectMap<String, LTexture>();
this.tileAnimators = new ObjectMap<TMXTile, TileAnimator>();
this.visible = true;
this.map = map;
for (TMXTileSet tileSet : map.getTileSets()) {
String path = tileSet.getImage().getSource();
if (!textureMap.containsKey(path)) {
textureMap.put(path, LTextures.loadTexture(path));
}
for (TMXTile tile : tileSet.getTiles()) {
if (tile.isAnimated()) {
TileAnimator animator = new TileAnimator(tile);
tileAnimators.put(tile, animator);
}
}
}
for (TMXImageLayer imageLayer : map.getImageLayers()) {
String path = imageLayer.getImage().getSource();
if (!textureMap.containsKey(path)) {
textureMap.put(path, LTextures.loadTexture(path));
}
}
}
public static TMXMapRenderer create(TMXMap map) {
switch (map.getOrientation()) {
case ISOMETRIC:
return new TMXIsometricMapRenderer(map);
case ORTHOGONAL:
return new TMXOrthogonalMapRenderer(map);
default:
break;
}
throw LSystem.runThrow(
"A TmxMapRenderer has not yet been implemented for "
+ map.getOrientation() + " orientation");
}
public void update(long delta) {
for (TileAnimator animator : tileAnimators.values()) {
animator.update(delta);
}
}
protected void renderBackgroundColor(GLEx gl) {
gl.fillRect(_location.x, _location.y,
map.getWidth() * map.getTileWidth(),
map.getHeight() * map.getTileHeight(), map.getBackgroundColor());
}
public void setLocationToTilePosX(int x) {
setX(x / map.getTileWidth());
}
public void setLocationToTilePosY(int y) {
setY(y / map.getTileHeight());
}
public void setColor(LColor c) {
baseColor.setColor(c);
}
public LColor getColor() {
return baseColor;
}
@Override
public float getWidth() {
return map.getWidth() * map.getTileWidth();
}
@Override
public float getHeight() {
return map.getHeight() * map.getTileHeight();
}
public void renderImageLayers(GLEx gl, int... layerIDs) {
if (layerIDs == null || layerIDs.length == 0) {
for (TMXImageLayer imageLayer : map.getImageLayers())
renderImageLayer(gl, imageLayer);
} else {
for (int layerIndex : layerIDs) {
if (layerIndex < map.getNumImageLayers()) {
renderImageLayer(gl, map.getImageLayer(layerIndex));
}
}
}
}
public void renderTileLayers(GLEx gl, int... layerIDs) {
if (layerIDs == null || layerIDs.length == 0) {
for (TMXTileLayer tileLayer : map.getTileLayers()) {
renderTileLayer(gl, tileLayer);
}
} else {
for (int layerIndex : layerIDs) {
if (layerIndex > map.getNumTileLayers()) {
renderTileLayer(gl, map.getTileLayer(layerIndex));
}
}
}
}
public TMXMap getMap() {
return map;
}
@Override
public void setVisible(boolean visible) {
this.visible = visible;
}
@Override
public boolean isVisible() {
return visible;
}
@Override
public void createUI(GLEx g, float offsetX, float offsetY) {
float tmp = g.alpha();
float tmpAlpha = baseColor.a;
int color = g.color();
g.setAlpha(_alpha);
baseColor.a = _alpha;
g.setColor(baseColor);
renderBackgroundColor(g);
float ox = getX();
float oy = getY();
setLocation(ox + offsetX, oy + offsetY);
for (TMXMapLayer mapLayer : map.getLayers()) {
if (mapLayer instanceof TMXTileLayer) {
renderTileLayer(g, (TMXTileLayer) mapLayer);
}
if (mapLayer instanceof TMXImageLayer) {
renderImageLayer(g, (TMXImageLayer) mapLayer);
}
}
setLocation(ox, oy);
baseColor.a = tmpAlpha;
g.setColor(color);
g.setAlpha(tmp);
}
@Override
public void createUI(GLEx g) {
float tmp = g.alpha();
float tmpAlpha = baseColor.a;
int color = g.color();
g.setAlpha(_alpha);
baseColor.a = _alpha;
g.setColor(baseColor);
renderBackgroundColor(g);
for (TMXMapLayer mapLayer : map.getLayers()) {
if (mapLayer instanceof TMXTileLayer) {
renderTileLayer(g, (TMXTileLayer) mapLayer);
}
if (mapLayer instanceof TMXImageLayer) {
renderImageLayer(g, (TMXImageLayer) mapLayer);
}
}
baseColor.a = tmpAlpha;
g.setColor(color);
g.setAlpha(tmp);
}
@Override
public RectBox getCollisionBox() {
return getCollisionArea();
}
@Override
public LTexture getBitmap() {
return null;
}
@Override
public Field2D getField2D() {
return null;
}
@Override
public float getScaleX() {
return scaleX;
}
@Override
public float getScaleY() {
return scaleY;
}
@Override
public void setScale(float sx, float sy) {
this.scaleX = sx;
this.scaleY = sy;
}
@Override
public boolean isBounded() {
return false;
}
@Override
public boolean isContainer() {
return true;
}
@Override
public boolean inContains(float x, float y, float w, float h) {
return getCollisionArea().contains(x, y, w, h);
}
@Override
public RectBox getRectBox() {
return getCollisionArea();
}
@Override
public int hashCode() {
int result = map.getTileSets().size;
result = LSystem.unite(result, _location.x);
result = LSystem.unite(result, _location.y);
result = LSystem.unite(result, map.getTileHeight());
result = LSystem.unite(result, map.getTileWidth());
result = LSystem.unite(result, map.getTileHeight());
result = LSystem.unite(result, scaleX);
result = LSystem.unite(result, scaleY);
result = LSystem.unite(result, _rotation);
return result;
}
@Override
public void close() {
visible = false;
if (textureMap != null) {
textureMap.clear();
}
if (tileAnimators != null) {
tileAnimators.clear();
}
for (LTexture texture : textureMap.values()) {
texture.close();
}
lastHashCode = 1;
setState(State.DISPOSED);
}
}