parent
30857951e0
commit
0860836f85
@ -1,4 +1,4 @@ |
||||
package mightypork.rogue.screens.ingame; |
||||
package mightypork.rogue.screens.gamescreen; |
||||
|
||||
|
||||
import mightypork.gamecore.gui.AlignX; |
@ -1,4 +1,4 @@ |
||||
package mightypork.rogue.screens.ingame; |
||||
package mightypork.rogue.screens.gamescreen; |
||||
|
||||
|
||||
import mightypork.gamecore.gui.AlignX; |
@ -1,4 +1,4 @@ |
||||
package mightypork.rogue.screens.ingame; |
||||
package mightypork.rogue.screens.gamescreen; |
||||
|
||||
|
||||
import mightypork.gamecore.control.events.MouseMotionEvent; |
@ -1,4 +1,4 @@ |
||||
package mightypork.rogue.screens.ingame; |
||||
package mightypork.rogue.screens.gamescreen; |
||||
|
||||
|
||||
import mightypork.gamecore.control.AppAccess; |
@ -0,0 +1,115 @@ |
||||
package mightypork.rogue.screens.gamescreen; |
||||
|
||||
|
||||
import mightypork.rogue.world.PlayerControl; |
||||
import mightypork.rogue.world.World; |
||||
import mightypork.rogue.world.WorldPos; |
||||
import mightypork.rogue.world.entity.Entity; |
||||
import mightypork.rogue.world.entity.models.EntityMoveListener; |
||||
import mightypork.rogue.world.level.Level; |
||||
import mightypork.util.constraints.vect.Vect; |
||||
import mightypork.util.math.Polar; |
||||
import mightypork.util.math.Calc.Deg; |
||||
import mightypork.gamecore.control.events.KeyEvent; |
||||
import mightypork.gamecore.control.events.MouseButtonEvent; |
||||
import mightypork.gamecore.input.InputSystem; |
||||
import mightypork.gamecore.input.Keys; |
||||
|
||||
|
||||
public class WRBasicControls extends WorldRenderComponent implements KeyEvent.Listener, MouseButtonEvent.Listener, EntityMoveListener { |
||||
|
||||
private final PlayerControl pc; |
||||
|
||||
|
||||
public WRBasicControls(World world) { |
||||
super(world); |
||||
pc = world.getPlayerControl(); |
||||
pc.addMoveListener(this); |
||||
} |
||||
|
||||
|
||||
private void handleHeldKey() |
||||
{ |
||||
if (InputSystem.isKeyDown(Keys.LEFT)) { |
||||
pc.walkWest(); |
||||
} else if (InputSystem.isKeyDown(Keys.RIGHT)) { |
||||
pc.walkEast(); |
||||
} else if (InputSystem.isKeyDown(Keys.UP)) { |
||||
pc.walkNorth(); |
||||
} else if (InputSystem.isKeyDown(Keys.DOWN)) { |
||||
pc.walkSouth(); |
||||
} |
||||
|
||||
if(InputSystem.isMouseButtonDown(0)) { |
||||
walkByMouse(InputSystem.getMousePos()); |
||||
} |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void onStepFinished(Entity entity, World world, Level level) |
||||
{ |
||||
handleHeldKey(); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void onPathFinished(Entity entity, World world, Level level) |
||||
{ |
||||
handleHeldKey(); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void onPathInterrupted(Entity entity, World world, Level level) |
||||
{ |
||||
handleHeldKey(); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void receive(MouseButtonEvent event) |
||||
{ |
||||
if (!event.isDown()) return; |
||||
|
||||
walkByMouse(event.getPos()); |
||||
} |
||||
|
||||
|
||||
private void walkByMouse(Vect mouse) |
||||
{ |
||||
|
||||
WorldPos clicked = toWorldPos(mouse); |
||||
WorldPos plpos = pc.getPos(); |
||||
|
||||
Polar p = Polar.fromCoord(clicked.x - plpos.x, clicked.y - plpos.y); |
||||
|
||||
int dir = Deg.round90(p.getAngleDeg()) / 90; |
||||
|
||||
switch (dir) { |
||||
case 0: |
||||
pc.walkEast(); |
||||
return; |
||||
|
||||
case 1: |
||||
pc.walkSouth(); |
||||
return; |
||||
|
||||
case 2: |
||||
pc.walkWest(); |
||||
return; |
||||
|
||||
case 3: |
||||
pc.walkNorth(); |
||||
return; |
||||
} |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void receive(KeyEvent event) |
||||
{ |
||||
handleHeldKey(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,77 @@ |
||||
package mightypork.rogue.screens.gamescreen; |
||||
|
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.util.Random; |
||||
|
||||
import mightypork.gamecore.gui.components.InputComponent; |
||||
import mightypork.gamecore.gui.screens.Screen; |
||||
import mightypork.gamecore.gui.screens.ScreenLayer; |
||||
import mightypork.rogue.Paths; |
||||
import mightypork.rogue.world.MapGenerator; |
||||
import mightypork.rogue.world.World; |
||||
import mightypork.util.constraints.num.Num; |
||||
import mightypork.util.ion.Ion; |
||||
|
||||
|
||||
public class WorldLayer extends ScreenLayer { |
||||
|
||||
private World world; |
||||
private InputComponent worldView; |
||||
|
||||
|
||||
public WorldLayer(Screen screen) { |
||||
super(screen); |
||||
|
||||
// FIXME just temporary test here
|
||||
|
||||
final Random rand = new Random(); |
||||
final File f = new File(Paths.WORKDIR, "test-world.ion"); |
||||
|
||||
// SAVE
|
||||
|
||||
world = MapGenerator.createWorld(rand.nextLong()); |
||||
updated.add(world); |
||||
|
||||
try { |
||||
Ion.toFile(f, world); |
||||
} catch (final IOException e) { |
||||
e.printStackTrace(); |
||||
System.exit(1); // fail
|
||||
return; |
||||
} |
||||
|
||||
// LOAD
|
||||
|
||||
// final World w;
|
||||
//
|
||||
// try {
|
||||
// world = Ion.fromFile(f, World.class);
|
||||
// } catch (IOException e) {
|
||||
// e.printStackTrace();
|
||||
// System.exit(1);
|
||||
// return;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// render component
|
||||
|
||||
worldView = new WRBasicControls(world); |
||||
|
||||
// size of lower navbar
|
||||
final Num lownav = root.width().min(root.height()).max(700).perc(7); |
||||
worldView.setRect(root.shrinkBottom(lownav)); |
||||
|
||||
root.add(worldView); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public int getPriority() |
||||
{ |
||||
return -1; // stay down
|
||||
} |
||||
|
||||
} |
@ -0,0 +1,44 @@ |
||||
package mightypork.rogue.screens.gamescreen; |
||||
|
||||
|
||||
import mightypork.gamecore.gui.components.InputComponent; |
||||
import mightypork.rogue.world.World; |
||||
import mightypork.rogue.world.WorldPos; |
||||
import mightypork.rogue.world.WorldRenderer; |
||||
import mightypork.util.constraints.vect.Vect; |
||||
|
||||
|
||||
public class WorldRenderComponent extends InputComponent { |
||||
|
||||
protected final WorldRenderer worldRenderer; |
||||
protected final World world; |
||||
|
||||
|
||||
public WorldRenderComponent(World world) { |
||||
this.world = world; |
||||
this.worldRenderer = new WorldRenderer(world, this, 8, 6, 72); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
protected void renderComponent() |
||||
{ |
||||
worldRenderer.render(); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void updateLayout() |
||||
{ |
||||
worldRenderer.poll(); // update sizing
|
||||
} |
||||
|
||||
|
||||
/** |
||||
* Get tile coord at a screen position |
||||
*/ |
||||
public WorldPos toWorldPos(Vect pos) |
||||
{ |
||||
return worldRenderer.getClickedTile(pos); |
||||
} |
||||
} |
@ -1,157 +0,0 @@ |
||||
package mightypork.rogue.screens.ingame; |
||||
|
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.util.Random; |
||||
|
||||
import mightypork.gamecore.gui.screens.Screen; |
||||
import mightypork.gamecore.gui.screens.ScreenLayer; |
||||
import mightypork.gamecore.input.InputSystem; |
||||
import mightypork.gamecore.input.KeyStroke; |
||||
import mightypork.gamecore.input.Keys; |
||||
import mightypork.rogue.Paths; |
||||
import mightypork.rogue.world.MapGenerator; |
||||
import mightypork.rogue.world.PlayerControl; |
||||
import mightypork.rogue.world.World; |
||||
import mightypork.rogue.world.entity.Entity; |
||||
import mightypork.rogue.world.entity.models.EntityMoveListener; |
||||
import mightypork.rogue.world.level.Level; |
||||
import mightypork.util.constraints.num.Num; |
||||
import mightypork.util.ion.Ion; |
||||
|
||||
|
||||
public class WorldLayer extends ScreenLayer { |
||||
|
||||
public WorldLayer(Screen screen) |
||||
{ |
||||
super(screen); |
||||
|
||||
// FIXME just temporary test here
|
||||
|
||||
final Random rand = new Random(); |
||||
final File f = new File(Paths.WORKDIR, "test-world.ion"); |
||||
final World w = MapGenerator.createWorld(rand.nextLong()); |
||||
|
||||
try { |
||||
Ion.toFile(f, w); |
||||
} catch (final IOException e) { |
||||
e.printStackTrace(); |
||||
System.exit(1); |
||||
return; |
||||
} |
||||
|
||||
// final World w;
|
||||
//
|
||||
// try {
|
||||
// w = Ion.fromFile(f, World.class);
|
||||
// } catch (IOException e) {
|
||||
// e.printStackTrace();
|
||||
// System.exit(1);
|
||||
// return;
|
||||
// }
|
||||
|
||||
final Num minWH = root.width().min(root.height()).max(700); // avoid too small shrinking
|
||||
|
||||
final WorldRenderer wr = new WorldRenderer(w); |
||||
wr.setRect(root.shrinkBottom(minWH.perc(7))); |
||||
root.add(wr); |
||||
|
||||
final PlayerControl c = w.getPlayerControl(); |
||||
|
||||
bindKey(new KeyStroke(true, Keys.LEFT), new Runnable() { |
||||
|
||||
@Override |
||||
public void run() |
||||
{ |
||||
c.walkWest(); |
||||
} |
||||
}); |
||||
|
||||
bindKey(new KeyStroke(true, Keys.RIGHT), new Runnable() { |
||||
|
||||
@Override |
||||
public void run() |
||||
{ |
||||
c.walkEast(); |
||||
} |
||||
}); |
||||
|
||||
bindKey(new KeyStroke(true, Keys.UP), new Runnable() { |
||||
|
||||
@Override |
||||
public void run() |
||||
{ |
||||
c.walkNorth(); |
||||
} |
||||
}); |
||||
|
||||
bindKey(new KeyStroke(true, Keys.DOWN), new Runnable() { |
||||
|
||||
@Override |
||||
public void run() |
||||
{ |
||||
c.walkSouth(); |
||||
} |
||||
}); |
||||
|
||||
bindKey(new KeyStroke(Keys.L_CONTROL, Keys.S), new Runnable() { |
||||
|
||||
@Override |
||||
public void run() |
||||
{ |
||||
try { |
||||
Ion.toFile(f, w); |
||||
} catch (final IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
}); |
||||
|
||||
c.addMoveListener(new EntityMoveListener() { |
||||
|
||||
private void tryGo(Entity entity) |
||||
{ |
||||
if (InputSystem.isKeyDown(Keys.LEFT)) { |
||||
c.walkWest(); |
||||
} else if (InputSystem.isKeyDown(Keys.RIGHT)) { |
||||
c.walkEast(); |
||||
} else if (InputSystem.isKeyDown(Keys.UP)) { |
||||
c.walkNorth(); |
||||
} else if (InputSystem.isKeyDown(Keys.DOWN)) { |
||||
c.walkSouth(); |
||||
} |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void onStepFinished(Entity entity, World world, Level level) |
||||
{ |
||||
entity.cancelPath(); // halt
|
||||
tryGo(entity); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void onPathFinished(Entity entity, World world, Level level) |
||||
{ |
||||
entity.cancelPath(); // halt
|
||||
tryGo(entity); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void onPathAborted(Entity entity, World world, Level level) |
||||
{ |
||||
} |
||||
}); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public int getPriority() |
||||
{ |
||||
return -1; |
||||
} |
||||
|
||||
} |
@ -1,67 +0,0 @@ |
||||
package mightypork.rogue.screens.ingame; |
||||
|
||||
|
||||
import mightypork.gamecore.control.events.MouseButtonEvent; |
||||
import mightypork.gamecore.gui.components.InputComponent; |
||||
import mightypork.gamecore.render.Render; |
||||
import mightypork.rogue.world.World; |
||||
import mightypork.util.constraints.num.Num; |
||||
import mightypork.util.constraints.rect.Rect; |
||||
import mightypork.util.control.timing.Updateable; |
||||
import mightypork.util.math.color.RGB; |
||||
|
||||
|
||||
public class WorldRenderer extends InputComponent implements Updateable { |
||||
|
||||
private final World world; |
||||
private final Rect rightShadow; |
||||
private final Rect leftShadow; |
||||
private final Rect topShadow; |
||||
private final Rect bottomShadow; |
||||
|
||||
|
||||
public WorldRenderer(World world) |
||||
{ |
||||
this.world = world; |
||||
|
||||
final Num h = height(); |
||||
final Num w = width(); |
||||
final Num minWH = w.min(h).max(700); |
||||
|
||||
final Num grX = w.perc(30); |
||||
final Num grY = h.perc(20); |
||||
|
||||
leftShadow = leftEdge().growRight(grX); |
||||
rightShadow = rightEdge().growLeft(grX); |
||||
topShadow = topEdge().growDown(grY); |
||||
bottomShadow = bottomEdge().growUp(grY); //.moveY(minWH.perc(-6))
|
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void receive(MouseButtonEvent event) |
||||
{ |
||||
System.out.println("world clciked, yo"); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
protected void renderComponent() |
||||
{ |
||||
world.render(this, 8, 7, 100); |
||||
|
||||
Render.quadGradH(leftShadow, RGB.BLACK, RGB.NONE); |
||||
Render.quadGradH(rightShadow, RGB.NONE, RGB.BLACK); |
||||
|
||||
Render.quadGradV(topShadow, RGB.BLACK, RGB.NONE); |
||||
Render.quadGradV(bottomShadow, RGB.NONE, RGB.BLACK); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void update(double delta) |
||||
{ |
||||
world.update(delta); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,181 @@ |
||||
package mightypork.rogue.world; |
||||
|
||||
|
||||
import mightypork.gamecore.render.Render; |
||||
import mightypork.rogue.Res; |
||||
import mightypork.rogue.world.entity.Entity; |
||||
import mightypork.rogue.world.level.Level; |
||||
import mightypork.rogue.world.level.render.TileRenderContext; |
||||
import mightypork.util.constraints.Pollable; |
||||
import mightypork.util.constraints.num.Num; |
||||
import mightypork.util.constraints.num.caching.NumCache; |
||||
import mightypork.util.constraints.rect.Rect; |
||||
import mightypork.util.constraints.rect.RectConst; |
||||
import mightypork.util.constraints.rect.caching.RectCache; |
||||
import mightypork.util.constraints.rect.proxy.RectProxy; |
||||
import mightypork.util.constraints.vect.Vect; |
||||
import mightypork.util.constraints.vect.caching.VectCache; |
||||
import mightypork.util.math.color.RGB; |
||||
|
||||
|
||||
/** |
||||
* World rendering untility |
||||
* |
||||
* @author MightyPork |
||||
*/ |
||||
public class WorldRenderer extends RectProxy implements Pollable { |
||||
|
||||
private static final boolean USE_BATCH_RENDERING = true; |
||||
|
||||
private final VectCache vpCenter; |
||||
private final NumCache tileSize; |
||||
|
||||
private final World world; |
||||
private final Entity player; |
||||
|
||||
// can be changed
|
||||
private RectCache mapRect; |
||||
private Level activeLevel; |
||||
|
||||
private final Rect rightShadow; |
||||
private final Rect leftShadow; |
||||
private final Rect topShadow; |
||||
private final Rect bottomShadow; |
||||
|
||||
|
||||
public WorldRenderer(World world, Rect viewport, int xTiles, int yTiles, int minTileSize) { |
||||
super(viewport); |
||||
|
||||
this.world = world; |
||||
this.player = world.playerEntity; |
||||
|
||||
tileSize = width().div(xTiles).min(height().div(yTiles)).max(minTileSize).cached(); |
||||
|
||||
final Num th = tileSize.half(); |
||||
vpCenter = center().sub(th, th).cached(); |
||||
|
||||
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); |
||||
|
||||
setupMapRect(); |
||||
} |
||||
|
||||
|
||||
private void setupMapRect() |
||||
{ |
||||
Level level = world.getCurrentLevel(); |
||||
|
||||
if (activeLevel == level) return; |
||||
activeLevel = level; |
||||
|
||||
mapRect = Rect.make(vpCenter, tileSize.mul(level.getWidth()), tileSize.mul(level.getHeight())).cached(); |
||||
} |
||||
|
||||
|
||||
private RectConst getCurrentDrawRect() |
||||
{ |
||||
|
||||
WorldPos pos = player.getPosition(); |
||||
final double playerX = pos.getVisualX(); |
||||
final double playerY = pos.getVisualY(); |
||||
|
||||
double ts = tileSize.value(); |
||||
|
||||
final RectConst drawRect = mapRect.move(-ts * playerX, -ts * playerY).freeze(); |
||||
|
||||
return drawRect; |
||||
} |
||||
|
||||
|
||||
public void render() |
||||
{ |
||||
setupMapRect(); |
||||
|
||||
final TileRenderContext rc = new TileRenderContext(activeLevel, getCurrentDrawRect()); |
||||
|
||||
// tiles to render
|
||||
final WorldPos pos = player.getPosition(); |
||||
final double w = width().value(); |
||||
final double h = height().value(); |
||||
final double ts = tileSize.value(); |
||||
final double tsh = ts / 2; |
||||
|
||||
final int x1 = (int) Math.floor(pos.x - (w / tsh)); |
||||
final int y1 = (int) Math.floor(pos.y - (h / tsh)); |
||||
final int x2 = (int) Math.ceil(pos.x + (w / tsh)); |
||||
final int y2 = (int) Math.ceil(pos.y + (h / tsh)); |
||||
|
||||
// === TILES ===
|
||||
|
||||
// batch rendering of the tiles
|
||||
if (USE_BATCH_RENDERING) { |
||||
Render.enterBatchTexturedQuadMode(Res.getTexture("tiles16")); |
||||
} |
||||
|
||||
for (rc.y = y1; rc.y <= y2; rc.y++) { |
||||
for (rc.x = x1; rc.x <= x2; rc.x++) { |
||||
rc.renderTile(); |
||||
} |
||||
} |
||||
|
||||
if (USE_BATCH_RENDERING) { |
||||
Render.leaveBatchTexturedQuadMode(); |
||||
} |
||||
|
||||
// === ITEMS ON TILES ===
|
||||
|
||||
for (rc.y = y1; rc.y <= y2; rc.y++) { |
||||
for (rc.x = x1; rc.x <= x2; rc.x++) { |
||||
rc.renderItems(); |
||||
} |
||||
} |
||||
|
||||
// === ENTITIES ===
|
||||
|
||||
for (final Entity e : activeLevel.getEntities()) { |
||||
|
||||
// avoid entities out of view rect
|
||||
int x = (int) Math.round(e.getPosition().getVisualX()); |
||||
int y = (int) Math.round(e.getPosition().getVisualY()); |
||||
|
||||
if (x < x1 - ts || x > x2 + ts) continue; |
||||
if (y < y1 - ts || y > y2 + ts) continue; |
||||
|
||||
e.render(rc); |
||||
} |
||||
|
||||
// === OVERLAY SHADOW ===
|
||||
|
||||
Render.quadGradH(leftShadow, RGB.BLACK, RGB.NONE); |
||||
Render.quadGradH(rightShadow, RGB.NONE, RGB.BLACK); |
||||
|
||||
Render.quadGradV(topShadow, RGB.BLACK, RGB.NONE); |
||||
Render.quadGradV(bottomShadow, RGB.NONE, RGB.BLACK); |
||||
} |
||||
|
||||
|
||||
public WorldPos getClickedTile(Vect clickPos) |
||||
{ |
||||
RectConst drawRect = getCurrentDrawRect(); |
||||
Vect v = clickPos.sub(drawRect.origin()); |
||||
int ts = (int)tileSize.value(); |
||||
return new WorldPos(v.xi() / ts, v.yi() / ts); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void poll() |
||||
{ |
||||
// in order of dependency
|
||||
vpCenter.poll(); |
||||
tileSize.poll(); |
||||
|
||||
mapRect.poll(); |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue