package pathgame.rendering; import me.hammerle.snuviengine.api.FontRenderer; import me.hammerle.snuviengine.api.Renderer; import me.hammerle.snuviengine.api.Texture; import me.hammerle.snuviengine.api.TextureRenderer; import pathgame.gameplay.Keys; import pathgame.gameplay.Player; import pathgame.tilemap.Tile; import pathgame.tilemap.TileMap; import pathgame.tilemap.TileRenderType; import pathgame.tilemap.TileType; public class TileMapRenderer { private final static float ERROR = 1.0f / 512.0F; private final static float T_ERROR = 1.0f / 4096.0F; private final Texture tileTexture = new Texture("resources/tiles.png"); private final TextureRenderer textureRenderer = new TextureRenderer(20 * 20 * 2); // default to 20x20 map private final TextureRenderer waterOverlayRenderer = new TextureRenderer(20 * 20 * 2); // default to 20x20 map private final TextureRenderer waveRenderer = new TextureRenderer(20 * 20 * 2); // default to 20x20 map private final TextureRenderer swampWaterOverlayRenderer = new TextureRenderer(20 * 20 * 2); // default to 20x20 map private final TextureRenderer grassOverlayRenderer = new TextureRenderer(20 * 20 * 2); // default to 20x20 map private float scale = 1.0f; private final static String[] OVERLAY = new String[]{ "#55FF551", "#55FF552", "#55FF553", "#FFFF554", "#FFFF555", "#FFAA006", "#FFAA007", "#FFAA008", "#FF55559" }; private static String[] getWavePath() { String[] path = new String[60]; for(int i = 0; i < path.length; i++) { path[i] = "resources/waves/wave" + (i + 1) + ".png"; } return path; } private final Texture.Animation waves = tileTexture.addAnimation((int) (8 * TileRenderer.TILE_SIZE), (int) (2 * TileRenderer.TILE_SIZE), getWavePath()); private int counter = 0; public void setScale(float scale) { this.scale = scale; } public float getScale() { return scale; } public float getWidth(TileMap map) { return map.getWidth() * TileRenderer.TILE_SIZE * scale; } public float getHeight(TileMap map) { return map.getHeight() * TileRenderer.TILE_SIZE * scale; } private float toTexture(int x) { return x * TileRenderer.TILE_SIZE / TileTexture.TEXTURE_SIZE; } private void addTile(TextureRenderer tr, int x, int y, float tMinX, float tMinY, float tMaxX, float tMaxY) { tr.addRectangle( x * TileRenderer.TILE_SIZE - ERROR, y * TileRenderer.TILE_SIZE - ERROR, (x + 1) * TileRenderer.TILE_SIZE + ERROR, (y + 1) * TileRenderer.TILE_SIZE + ERROR, tMinX + T_ERROR, tMinY + T_ERROR, tMaxX - T_ERROR, tMaxY - T_ERROR); } private void addTileOverlay(TextureRenderer tr, int x, int y, int ox, int oy) { addTile(tr, x, y, toTexture(ox), toTexture(oy), toTexture(ox + 1), toTexture(oy + 1)); } private boolean isInRange(TileMap map, int x, int y) { return x >= 0 && y >= 0 && x < map.getWidth() && y < map.getHeight(); } private boolean isShallowWater(TileMap map, int x, int y) { return isInRange(map, x, y) && map.getTile(x, y).getType() == TileType.SHALLOW_WATER; } private boolean isSwamp(TileMap map, int x, int y) { return isInRange(map, x, y) && map.getTile(x, y).getRenderType() == TileRenderType.SWAMP; } private boolean isSwampOrWaterOrBorder(TileMap map, int x, int y) { if(!isInRange(map, x, y)) { return true; } TileRenderType type = map.getTile(x, y).getRenderType(); return type == TileRenderType.SWAMP || type == TileRenderType.WATER; } private void addWaterSwampOverlay(TileMap map, int x, int y) { boolean n = isSwamp(map, x, y - 1); boolean e = isSwamp(map, x + 1, y); boolean s = isSwamp(map, x, y + 1); boolean w = isSwamp(map, x - 1, y); if(!n && !w && isSwamp(map, x - 1, y - 1)) { addTileOverlay(swampWaterOverlayRenderer, x, y, 7, 13); } if(!n && !e && isSwamp(map, x + 1, y - 1)) { addTileOverlay(swampWaterOverlayRenderer, x, y, 6, 13); } if(!s && !w && isSwamp(map, x - 1, y + 1)) { addTileOverlay(swampWaterOverlayRenderer, x, y, 5, 13); } if(!s && !e && isSwamp(map, x + 1, y + 1)) { addTileOverlay(swampWaterOverlayRenderer, x, y, 4, 13); } int index = 0; index += n ? 0 : 8; index += e ? 0 : 4; index += s ? 0 : 2; index += w ? 0 : 1; if(index == 15) { return; } addTileOverlay(swampWaterOverlayRenderer, x, y, index, 15); } private void addDeepWaterOverlay(TileMap map, int x, int y) { boolean n = isShallowWater(map, x, y - 1); boolean e = isShallowWater(map, x + 1, y); boolean s = isShallowWater(map, x, y + 1); boolean w = isShallowWater(map, x - 1, y); if(!n && !w && isShallowWater(map, x - 1, y - 1)) { addTileOverlay(waterOverlayRenderer, x, y, 11, 13); } if(!n && !e && isShallowWater(map, x + 1, y - 1)) { addTileOverlay(waterOverlayRenderer, x, y, 10, 13); } if(!s && !w && isShallowWater(map, x - 1, y + 1)) { addTileOverlay(waterOverlayRenderer, x, y, 9, 13); } if(!s && !e && isShallowWater(map, x + 1, y + 1)) { addTileOverlay(waterOverlayRenderer, x, y, 8, 13); } int index = 0; index += n ? 0 : 8; index += e ? 0 : 4; index += s ? 0 : 2; index += w ? 0 : 1; if(index == 15) { return; } addTileOverlay(waterOverlayRenderer, x, y, index, 12); } private void addGrassOverlay(TileMap map, int x, int y) { boolean n = isSwampOrWaterOrBorder(map, x, y - 1); boolean e = isSwampOrWaterOrBorder(map, x + 1, y); boolean s = isSwampOrWaterOrBorder(map, x, y + 1); boolean w = isSwampOrWaterOrBorder(map, x - 1, y); if(n && w && !isSwampOrWaterOrBorder(map, x - 1, y - 1)) { addTileOverlay(grassOverlayRenderer, x, y, 3, 13); } if(n && e && !isSwampOrWaterOrBorder(map, x + 1, y - 1)) { addTileOverlay(grassOverlayRenderer, x, y, 2, 13); } if(s && w && !isSwampOrWaterOrBorder(map, x - 1, y + 1)) { addTileOverlay(grassOverlayRenderer, x, y, 1, 13); } if(s && e && !isSwampOrWaterOrBorder(map, x + 1, y + 1)) { addTileOverlay(grassOverlayRenderer, x, y, 0, 13); } int index = 0; index += !n ? 0 : 8; index += !e ? 0 : 4; index += !s ? 0 : 2; index += !w ? 0 : 1; if(index == 15) { return; } addTileOverlay(grassOverlayRenderer, x, y, index, 14); } private void updateData(TileMap map) { textureRenderer.clear(); waterOverlayRenderer.clear(); waveRenderer.clear(); swampWaterOverlayRenderer.clear(); grassOverlayRenderer.clear(); for(int x = 0; x < map.getWidth(); x++) { for(int y = 0; y < map.getHeight(); y++) { Tile t = map.getTile(x, y); TileTexture tt = TileRenderer.getTileTexture(map, t, x, y); if(tt == null) { continue; } if(t.getRenderType() == TileRenderType.WATER) { if(t.getType() == TileType.DEEP_WATER) { addDeepWaterOverlay(map, x, y); } addWaterSwampOverlay(map, x, y); addGrassOverlay(map, x, y); addTileOverlay(waveRenderer, x, y, 8, 2); } else if(t.getRenderType() == TileRenderType.SWAMP) { addGrassOverlay(map, x, y); } addTile(textureRenderer, x, y, tt.getMinX(), tt.getMinY(), tt.getMaxX(), tt.getMaxY()); } } textureRenderer.build(); waterOverlayRenderer.build(); waveRenderer.build(); swampWaterOverlayRenderer.build(); grassOverlayRenderer.build(); } public void tick() { counter++; if(counter >= 1) { tileTexture.bind(); waves.nextFrame(); counter = 0; } } public void renderTick(TileMap map, Renderer r, Player p, boolean forceUpdate, float offX, float offY, Keys keys) { r.setTextureEnabled(true); r.setColorEnabled(false); r.setMixColorEnabled(false); tileTexture.bind(); if(forceUpdate || map.isDirty()) { updateData(map); map.clean(); } float viewScale = r.getViewScale(); offX = (int) (offX * viewScale) / viewScale; offY = (int) (offY * viewScale) / viewScale; r.translateTo(offX, offY); r.scale(scale, scale); r.updateMatrix(); textureRenderer.draw(); waterOverlayRenderer.draw(); waveRenderer.draw(); swampWaterOverlayRenderer.draw(); grassOverlayRenderer.draw(); if(keys.overlay.isDown()) { r.translateTo(0.0f, 0.0f); r.updateMatrix(); r.setTextureEnabled(false); r.getColorRenderer().drawRectangle(0, 0, r.getViewWidth(), r.getViewHeight(), 0x44000000); r.setTextureEnabled(true); r.setColorEnabled(true); r.translateTo(offX, offY); r.scale(scale * 2.0f, scale * 2.0f); r.updateMatrix(); FontRenderer fr = r.getFontRenderer(); float midX = (TileRenderer.TILE_SIZE - fr.getCharWidth() * 2) * 0.5f * 0.5f; float midY = (TileRenderer.TILE_SIZE - (fr.getCharHeight() - 1) * 2) * 0.5f * 0.5f; for(int x = 0; x < map.getWidth(); x++) { for(int y = 0; y < map.getHeight(); y++) { Tile t = map.getTile(x, y); float tx = midX + TileRenderer.TILE_SIZE * x * 0.5f; float ty = midY + TileRenderer.TILE_SIZE * y * 0.5f; if(t.isBlockingMovement(p)) { fr.drawString(tx, ty, true, "#AA0000-"); } else { fr.drawString(tx, ty, true, OVERLAY[map.getTile(x, y).getEnergyCost(p) - 1]); } } } } } }