Rogue: Savage Rats, a retro-themed dungeon crawler
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.
 
 
rogue-savage-rats/src/mightypork/rogue/world/WorldRenderer.java

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);
}
}