You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
185 lines
4.6 KiB
185 lines
4.6 KiB
package mightypork.rogue.world;
|
|
|
|
|
|
import mightypork.gamecore.core.App;
|
|
import mightypork.gamecore.render.GraphicsModule;
|
|
import mightypork.rogue.world.entity.Entity;
|
|
import mightypork.rogue.world.level.Level;
|
|
import mightypork.rogue.world.level.render.TileRenderContext;
|
|
import mightypork.utils.math.algo.Coord;
|
|
import mightypork.utils.math.color.GradH;
|
|
import mightypork.utils.math.color.GradV;
|
|
import mightypork.utils.math.color.pal.RGB;
|
|
import mightypork.utils.math.constraints.num.Num;
|
|
import mightypork.utils.math.constraints.rect.Rect;
|
|
import mightypork.utils.math.constraints.rect.RectConst;
|
|
import mightypork.utils.math.constraints.rect.proxy.RectProxy;
|
|
import mightypork.utils.math.constraints.vect.Vect;
|
|
import mightypork.utils.math.constraints.vect.VectConst;
|
|
|
|
|
|
/**
|
|
* World rendering untility
|
|
*
|
|
* @author Ondřej Hruška (MightyPork)
|
|
*/
|
|
public class WorldRenderer extends RectProxy {
|
|
|
|
private static final boolean USE_BATCH_RENDERING = true;
|
|
|
|
private final Num tileSize;
|
|
|
|
// can be changed
|
|
private RectConst mapRect;
|
|
private Level activeLevel;
|
|
|
|
private final Rect rightShadow;
|
|
private final Rect leftShadow;
|
|
private final Rect topShadow;
|
|
private final Rect bottomShadow;
|
|
|
|
private TileRenderContext trc;
|
|
|
|
|
|
public WorldRenderer(Rect viewport, Num tileSize) {
|
|
super(viewport);
|
|
|
|
this.tileSize = tileSize;
|
|
|
|
final Num grX = width().perc(30);
|
|
leftShadow = leftEdge().growRight(grX);
|
|
rightShadow = rightEdge().growLeft(grX);
|
|
|
|
final Num grY = height().perc(20);
|
|
topShadow = topEdge().growDown(grY);
|
|
bottomShadow = bottomEdge().growUp(grY);
|
|
}
|
|
|
|
|
|
private void prepareRenderContextIfNeeded()
|
|
{
|
|
final Level level = WorldProvider.get().getCurrentLevel();
|
|
|
|
if (activeLevel == level) return;
|
|
|
|
activeLevel = level;
|
|
|
|
mapRect = Rect.make(0, 0, level.getWidth(), level.getHeight());
|
|
|
|
trc = new TileRenderContext(activeLevel, mapRect);
|
|
}
|
|
|
|
|
|
private VectConst getOffset()
|
|
{
|
|
return Vect.make(WorldProvider.get().getPlayer().getVisualPos().neg().sub(0.5, 0.5)).freeze();
|
|
}
|
|
|
|
|
|
public void render()
|
|
{
|
|
prepareRenderContextIfNeeded();
|
|
|
|
final GraphicsModule gfx = App.gfx();
|
|
|
|
gfx.pushGeometry();
|
|
gfx.setColor(RGB.WHITE);
|
|
gfx.translate(center());
|
|
gfx.scaleXY(tileSize.value());
|
|
gfx.translate(getOffset());
|
|
|
|
// tiles to render
|
|
|
|
final Coord pos = WorldProvider.get().getPlayer().getCoord();
|
|
final double w = width().value();
|
|
final double h = height().value();
|
|
|
|
final double ts = tileSize.value();
|
|
|
|
final int xtilesh = (int) (w / (ts * 2)) + 1;
|
|
final int ytilesh = (int) (h / (ts * 2)) + 1;
|
|
|
|
final int x1 = pos.x - xtilesh;
|
|
final int y1 = pos.y - ytilesh;
|
|
final int x2 = pos.x + xtilesh;
|
|
final int y2 = pos.y + ytilesh;
|
|
|
|
// === TILES ===
|
|
|
|
// batch rendering of the tiles
|
|
// TODO
|
|
// if (USE_BATCH_RENDERING) {
|
|
// gfx.enterBatchTexturedQuadMode(Res.getTexture("tiles"));
|
|
// }
|
|
for (trc.pos.x = x1; trc.pos.x <= x2; trc.pos.x++) {
|
|
for (trc.pos.y = y1; trc.pos.y <= y2; trc.pos.y++) {
|
|
trc.renderTile();
|
|
}
|
|
}
|
|
// TODO
|
|
// if (USE_BATCH_RENDERING) {
|
|
// gfx.leaveBatchTexturedQuadMode();
|
|
// }
|
|
|
|
// === ITEMS ON TILES ===
|
|
|
|
for (trc.pos.x = x1; trc.pos.x <= x2; trc.pos.x++) {
|
|
for (trc.pos.y = y1; trc.pos.y <= y2; trc.pos.y++) {
|
|
trc.renderItems();
|
|
}
|
|
}
|
|
|
|
// === ENTITIES ===
|
|
|
|
for (final Entity e : activeLevel.getEntities()) {
|
|
|
|
// avoid entities out of view rect
|
|
final Vect entPos = e.pos.getVisualPos();
|
|
final int x = (int) Math.round(entPos.x());
|
|
final int y = (int) Math.round(entPos.y());
|
|
|
|
if (x < x1 - ts || x > x2 + ts) continue;
|
|
if (y < y1 - ts || y > y2 + ts) continue;
|
|
|
|
e.render(trc);
|
|
}
|
|
|
|
// === unexplored fog ===
|
|
|
|
// batch rendering of the tiles
|
|
// TODO
|
|
// if (USE_BATCH_RENDERING) {
|
|
// gfx.setColor(RGB.WHITE, Const.RENDER_UFOG ? 1 : 0.6);
|
|
// gfx.enterBatchTexturedQuadMode(Res.getTexture("tiles"));
|
|
// }
|
|
// TODO use Const.RENDER_UFOG
|
|
for (trc.pos.x = x1; trc.pos.x <= x2; trc.pos.x++) {
|
|
for (trc.pos.y = y1; trc.pos.y <= y2; trc.pos.y++) {
|
|
trc.renderUFog();
|
|
}
|
|
}
|
|
// TODO
|
|
// if (USE_BATCH_RENDERING) {
|
|
// gfx.leaveBatchTexturedQuadMode();
|
|
// }
|
|
|
|
// === OVERLAY SHADOW ===
|
|
|
|
gfx.popGeometry();
|
|
|
|
gfx.quad(leftShadow, new GradH(RGB.BLACK, RGB.NONE));
|
|
gfx.quad(rightShadow, new GradH(RGB.NONE, RGB.BLACK));
|
|
|
|
gfx.quad(topShadow, new GradV(RGB.BLACK, RGB.NONE));
|
|
gfx.quad(bottomShadow, new GradV(RGB.NONE, RGB.BLACK));
|
|
}
|
|
|
|
|
|
public Vect getClickedTile(Vect clickPos)
|
|
{
|
|
final int ts = (int) tileSize.value();
|
|
final Vect v = clickPos.sub(center().add(getOffset().mul(ts)));
|
|
return Vect.make(v.x() / ts, v.y() / ts);
|
|
}
|
|
|
|
}
|
|
|