Refactored world renderer & world controls.
This commit is contained in:
@@ -3,6 +3,7 @@ package mightypork.gamecore.control.events;
|
||||
|
||||
import mightypork.util.constraints.rect.proxy.RectBound;
|
||||
import mightypork.util.constraints.vect.Vect;
|
||||
import mightypork.util.constraints.vect.VectConst;
|
||||
import mightypork.util.control.eventbus.events.Event;
|
||||
|
||||
|
||||
@@ -19,7 +20,7 @@ public class MouseButtonEvent implements Event<MouseButtonEvent.Listener> {
|
||||
|
||||
private final int button;
|
||||
private final int wheeld;
|
||||
private final Vect pos;
|
||||
private final VectConst pos;
|
||||
private final boolean down;
|
||||
|
||||
|
||||
@@ -35,7 +36,7 @@ public class MouseButtonEvent implements Event<MouseButtonEvent.Listener> {
|
||||
{
|
||||
this.button = button;
|
||||
this.down = down;
|
||||
this.pos = pos;
|
||||
this.pos = pos.freeze();
|
||||
this.wheeld = wheeld;
|
||||
}
|
||||
|
||||
@@ -79,7 +80,7 @@ public class MouseButtonEvent implements Event<MouseButtonEvent.Listener> {
|
||||
/**
|
||||
* @return mouse position when the event occurred
|
||||
*/
|
||||
public Vect getPos()
|
||||
public VectConst getPos()
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
|
||||
@@ -2,11 +2,27 @@ package mightypork.gamecore.gui.components;
|
||||
|
||||
|
||||
import mightypork.gamecore.control.events.MouseButtonEvent;
|
||||
import mightypork.util.control.Action;
|
||||
import mightypork.util.control.ActionTrigger;
|
||||
|
||||
|
||||
public abstract class ClickableComponent extends InputComponent {
|
||||
public abstract class ClickableComponent extends InputComponent implements ActionTrigger, MouseButtonEvent.Listener {
|
||||
|
||||
private boolean btnDownOver;
|
||||
private Action action;
|
||||
|
||||
|
||||
@Override
|
||||
public void setAction(Action action)
|
||||
{
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
|
||||
protected void triggerAction()
|
||||
{
|
||||
if (action != null && isEnabled()) action.run();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,23 +1,13 @@
|
||||
package mightypork.gamecore.gui.components;
|
||||
|
||||
|
||||
import mightypork.gamecore.control.events.MouseButtonEvent;
|
||||
import mightypork.util.control.Action;
|
||||
import mightypork.util.control.ActionTrigger;
|
||||
import mightypork.util.control.Enableable;
|
||||
import mightypork.util.control.eventbus.clients.ToggleableClient;
|
||||
|
||||
|
||||
public abstract class InputComponent extends VisualComponent implements Enableable, ActionTrigger, MouseButtonEvent.Listener {
|
||||
public abstract class InputComponent extends VisualComponent implements Enableable, ToggleableClient {
|
||||
|
||||
private boolean enabled;
|
||||
private Action action;
|
||||
|
||||
|
||||
@Override
|
||||
public void setAction(Action action)
|
||||
{
|
||||
this.action = action;
|
||||
}
|
||||
private boolean enabled = true;
|
||||
|
||||
|
||||
@Override
|
||||
@@ -34,8 +24,9 @@ public abstract class InputComponent extends VisualComponent implements Enableab
|
||||
}
|
||||
|
||||
|
||||
protected void triggerAction()
|
||||
@Override
|
||||
public boolean isListening()
|
||||
{
|
||||
if (action != null) action.run();
|
||||
return isEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,4 +210,10 @@ public class InputSystem extends RootBusNode implements Updateable, KeyBinder {
|
||||
{
|
||||
return Keyboard.isKeyDown(key);
|
||||
}
|
||||
|
||||
|
||||
public static boolean isMouseButtonDown(int button)
|
||||
{
|
||||
return Mouse.isButtonDown(button);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import mightypork.rogue.events.ActionRequest.RequestType;
|
||||
import mightypork.rogue.screens.CrossfadeOverlay;
|
||||
import mightypork.rogue.screens.CrossfadeRequest;
|
||||
import mightypork.rogue.screens.FpsOverlay;
|
||||
import mightypork.rogue.screens.ingame.ScreenGame;
|
||||
import mightypork.rogue.screens.gamescreen.ScreenGame;
|
||||
import mightypork.rogue.screens.main_menu.ScreenMainMenu;
|
||||
import mightypork.rogue.screens.test_bouncyboxes.ScreenTestBouncy;
|
||||
import mightypork.rogue.screens.test_cat_sound.ScreenTestCat;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package mightypork.rogue.screens.ingame;
|
||||
package mightypork.rogue.screens.gamescreen;
|
||||
|
||||
|
||||
import mightypork.gamecore.gui.AlignX;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package mightypork.rogue.screens.ingame;
|
||||
package mightypork.rogue.screens.gamescreen;
|
||||
|
||||
|
||||
import mightypork.gamecore.gui.AlignX;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package mightypork.rogue.screens.ingame;
|
||||
package mightypork.rogue.screens.gamescreen;
|
||||
|
||||
|
||||
import mightypork.gamecore.control.events.MouseMotionEvent;
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,10 +14,6 @@ public class PathStep implements IonBinary {
|
||||
public static final PathStep SOUTH = new PathStep(0, 1);
|
||||
public static final PathStep EAST = new PathStep(1, 0);
|
||||
public static final PathStep WEST = new PathStep(-1, 0);
|
||||
public static final PathStep NORTH_EAST = new PathStep(1, -1);
|
||||
public static final PathStep NORTH_WEST = new PathStep(-1, -1);
|
||||
public static final PathStep SOUTH_EAST = new PathStep(1, 1);
|
||||
public static final PathStep SOUTH_WEST = new PathStep(-1, 1);
|
||||
public static final PathStep NONE = new PathStep(0, 0);
|
||||
|
||||
|
||||
@@ -26,19 +22,12 @@ public class PathStep implements IonBinary {
|
||||
x = x < 0 ? -1 : x > 0 ? 1 : 0;
|
||||
y = y < 0 ? -1 : y > 0 ? 1 : 0;
|
||||
|
||||
if (x == 0 && y == -1) return NORTH;
|
||||
if (x == 0 && y == 1) return SOUTH;
|
||||
if (x == -1 && y == 0) return WEST;
|
||||
if (x == 1 && y == 0) return EAST;
|
||||
if (y == -1) return NORTH;
|
||||
if (y == 1) return SOUTH;
|
||||
if (x == -1) return WEST;
|
||||
if (x == 1) return EAST;
|
||||
|
||||
if (x == -1 && y == -1) return NORTH_WEST;
|
||||
if (x == 1 && y == -1) return NORTH_EAST;
|
||||
if (x == -1 && y == 1) return SOUTH_WEST;
|
||||
if (x == 1 && y == 1) return SOUTH_EAST;
|
||||
|
||||
if (x == 0 && y == 0) return NONE;
|
||||
|
||||
return new PathStep(x, y);
|
||||
return NONE;
|
||||
}
|
||||
|
||||
public static final int ION_MARK = 0;
|
||||
|
||||
@@ -43,4 +43,16 @@ public class PlayerControl {
|
||||
{
|
||||
world.playerEntity.addMoveListener(eml);
|
||||
}
|
||||
|
||||
|
||||
public WorldPos getPos()
|
||||
{
|
||||
return world.playerEntity.getPosition();
|
||||
}
|
||||
|
||||
|
||||
public void walk(PathStep step)
|
||||
{
|
||||
world.playerEntity.addStep(step);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import java.util.ArrayList;
|
||||
import mightypork.rogue.world.entity.Entities;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
import mightypork.util.constraints.rect.proxy.RectBound;
|
||||
import mightypork.util.control.timing.Updateable;
|
||||
import mightypork.util.ion.IonBundle;
|
||||
import mightypork.util.ion.IonBundled;
|
||||
@@ -105,20 +104,6 @@ public class World implements IonBundled, Updateable {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw on screen
|
||||
*
|
||||
* @param viewport rendering area on screen
|
||||
* @param xTiles Desired nr of tiles horizontally
|
||||
* @param yTiles Desired nr of tiles vertically
|
||||
* @param minSize minimum tile size
|
||||
*/
|
||||
public void render(RectBound viewport, final int xTiles, final int yTiles, final int minSize)
|
||||
{
|
||||
getCurrentLevel().render(playerEntity.getPosition(), viewport, xTiles, yTiles, minSize);
|
||||
}
|
||||
|
||||
|
||||
public Level getCurrentLevel()
|
||||
{
|
||||
return levels.get(player.getLevel());
|
||||
@@ -129,4 +114,10 @@ public class World implements IonBundled, Updateable {
|
||||
{
|
||||
return control;
|
||||
}
|
||||
|
||||
|
||||
public Entity getPlayerEntity()
|
||||
{
|
||||
return playerEntity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,7 +13,7 @@ import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.rogue.world.entity.models.EntityModel;
|
||||
import mightypork.rogue.world.entity.models.EntityMoveListener;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
import mightypork.rogue.world.level.render.EntityRenderContext;
|
||||
import mightypork.rogue.world.level.render.MapRenderContext;
|
||||
import mightypork.util.ion.IonBinary;
|
||||
import mightypork.util.ion.IonBundle;
|
||||
import mightypork.util.ion.IonBundled;
|
||||
@@ -188,13 +188,13 @@ public final class Entity implements IonBinary, IonBundled, EntityMoveListener {
|
||||
|
||||
walking = true;
|
||||
|
||||
final PathStep step = path.poll();
|
||||
PathStep step = path.poll();
|
||||
|
||||
final int projX = position.x + step.x, projY = position.y + step.y;
|
||||
|
||||
if (!level.canWalkInto(projX, projY)) {
|
||||
cancelPath();
|
||||
onPathAborted(this, world, level);
|
||||
onPathInterrupted(this, world, level);
|
||||
walking = false;
|
||||
} else {
|
||||
|
||||
@@ -214,7 +214,7 @@ public final class Entity implements IonBinary, IonBundled, EntityMoveListener {
|
||||
}
|
||||
|
||||
|
||||
public void render(EntityRenderContext context)
|
||||
public void render(MapRenderContext context)
|
||||
{
|
||||
model.renderer.render(this, context);
|
||||
}
|
||||
@@ -263,10 +263,10 @@ public final class Entity implements IonBinary, IonBundled, EntityMoveListener {
|
||||
|
||||
|
||||
@Override
|
||||
public void onPathAborted(Entity entity, World world, Level level)
|
||||
public void onPathInterrupted(Entity entity, World world, Level level)
|
||||
{
|
||||
for (final EntityMoveListener l : moveListeners) {
|
||||
l.onPathAborted(entity, world, level);
|
||||
l.onPathInterrupted(entity, world, level);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,6 @@ public abstract class EntityModel implements EntityMoveListener {
|
||||
|
||||
|
||||
@Override
|
||||
public abstract void onPathAborted(Entity entity, World world, Level level);
|
||||
public abstract void onPathInterrupted(Entity entity, World world, Level level);
|
||||
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@ public interface EntityMoveListener {
|
||||
|
||||
|
||||
/**
|
||||
* Path was aborted (bumped into a wall or entity)
|
||||
* Path was interrupted (bumped into a wall or entity)
|
||||
*/
|
||||
void onPathAborted(Entity entity, World world, Level level);
|
||||
void onPathInterrupted(Entity entity, World world, Level level);
|
||||
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ public class PlayerModel extends EntityModel {
|
||||
|
||||
|
||||
@Override
|
||||
public void onPathAborted(Entity entity, World world, Level level)
|
||||
public void onPathInterrupted(Entity entity, World world, Level level)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package mightypork.rogue.world.entity.renderers;
|
||||
|
||||
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.level.render.EntityRenderContext;
|
||||
import mightypork.rogue.world.level.render.MapRenderContext;
|
||||
|
||||
|
||||
public abstract class EntityRenderer {
|
||||
@@ -10,6 +10,6 @@ public abstract class EntityRenderer {
|
||||
public static final EntityRenderer NONE = new NullEntityRenderer();
|
||||
|
||||
|
||||
public abstract void render(Entity entity, EntityRenderContext context);
|
||||
public abstract void render(Entity entity, MapRenderContext context);
|
||||
|
||||
}
|
||||
|
||||
@@ -2,13 +2,13 @@ package mightypork.rogue.world.entity.renderers;
|
||||
|
||||
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.level.render.EntityRenderContext;
|
||||
import mightypork.rogue.world.level.render.MapRenderContext;
|
||||
|
||||
|
||||
public class NullEntityRenderer extends EntityRenderer {
|
||||
|
||||
@Override
|
||||
public void render(Entity entity, EntityRenderContext context)
|
||||
public void render(Entity entity, MapRenderContext context)
|
||||
{
|
||||
// hell no
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import mightypork.gamecore.render.textures.TxSheet;
|
||||
import mightypork.rogue.Res;
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.level.render.EntityRenderContext;
|
||||
import mightypork.rogue.world.level.render.MapRenderContext;
|
||||
import mightypork.util.constraints.rect.Rect;
|
||||
import mightypork.util.math.Calc;
|
||||
|
||||
@@ -24,7 +24,7 @@ public class PlayerRenderer extends EntityRenderer {
|
||||
|
||||
|
||||
@Override
|
||||
public void render(Entity entity, EntityRenderContext context)
|
||||
public void render(Entity entity, MapRenderContext context)
|
||||
{
|
||||
TxQuad q = sheet.getQuad(Calc.frag(entity.getPosition().getProgress()));
|
||||
|
||||
|
||||
@@ -2,25 +2,17 @@ package mightypork.rogue.world.level;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import mightypork.gamecore.render.Render;
|
||||
import mightypork.rogue.Res;
|
||||
import mightypork.rogue.world.World;
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.level.render.EntityRenderContext;
|
||||
import mightypork.rogue.world.level.render.TileRenderContext;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.rogue.world.tile.Tiles;
|
||||
import mightypork.rogue.world.tile.models.TileModel;
|
||||
import mightypork.util.constraints.rect.Rect;
|
||||
import mightypork.util.constraints.rect.RectConst;
|
||||
import mightypork.util.constraints.rect.proxy.RectBound;
|
||||
import mightypork.util.constraints.vect.VectConst;
|
||||
import mightypork.util.ion.IonBinary;
|
||||
import mightypork.util.ion.IonBundle;
|
||||
import mightypork.util.ion.IonInput;
|
||||
@@ -37,8 +29,6 @@ public class Level implements MapAccess, IonBinary {
|
||||
|
||||
public static final int ION_MARK = 53;
|
||||
|
||||
private static final boolean USE_BATCH_RENDERING = true;
|
||||
|
||||
private int width, height;
|
||||
|
||||
/** Array of tiles [y][x] */
|
||||
@@ -53,13 +43,11 @@ public class Level implements MapAccess, IonBinary {
|
||||
private transient NoiseGen noiseGen;
|
||||
|
||||
|
||||
public Level()
|
||||
{
|
||||
public Level() {
|
||||
}
|
||||
|
||||
|
||||
public Level(int width, int height)
|
||||
{
|
||||
public Level(int width, int height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
buildArray();
|
||||
@@ -231,83 +219,6 @@ public class Level implements MapAccess, IonBinary {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw on screen
|
||||
*
|
||||
* @param playerInfo layer
|
||||
* @param viewport rendering area on screen
|
||||
* @param xTiles Desired nr of tiles horizontally
|
||||
* @param yTiles Desired nr of tiles vertically
|
||||
* @param minSize minimum tile size
|
||||
*/
|
||||
public void render(WorldPos pos, RectBound viewport, final int xTiles, final int yTiles, final int minSize)
|
||||
{
|
||||
final Rect r = viewport.getRect();
|
||||
final double vpH = r.height().value();
|
||||
final double vpW = r.width().value();
|
||||
|
||||
// adjust tile size to fit desired amount of tiles
|
||||
|
||||
final double allowedSizeW = vpW / xTiles;
|
||||
final double allowedSizeH = vpH / yTiles;
|
||||
final int tileSize = (int) Math.round(Math.max(Math.min(allowedSizeH, allowedSizeW), minSize));
|
||||
|
||||
//tileSize -= tileSize % 8;
|
||||
|
||||
final VectConst vpCenter = r.center().sub(tileSize * 0.5, tileSize * 0.5).freeze(); // 0.5 to center, 1 to move up (down is teh navbar)
|
||||
|
||||
final double playerX = pos.getVisualX();
|
||||
final double playerY = pos.getVisualY();
|
||||
|
||||
// total map area
|
||||
//@formatter:off
|
||||
final RectConst mapRect = vpCenter.startRect().grow(
|
||||
playerX*tileSize,
|
||||
(getWidth() - playerX) * tileSize,
|
||||
playerY*tileSize,
|
||||
(getHeight() - playerY) * tileSize
|
||||
).freeze();
|
||||
//@formatter:on
|
||||
|
||||
// tiles to render
|
||||
final int x1 = (int) Math.floor(playerX - (vpW / tileSize / 2));
|
||||
|
||||
final int y1 = (int) Math.floor(playerY - (vpH / tileSize / 2));
|
||||
final int x2 = (int) Math.ceil(playerX + (vpW / tileSize / 2));
|
||||
final int y2 = (int) Math.ceil(playerY + (vpH / tileSize / 2));
|
||||
|
||||
final TileRenderContext trc = new TileRenderContext(this, mapRect); //-tileSize*0.5
|
||||
|
||||
// batch rendering of the tiles
|
||||
if (USE_BATCH_RENDERING) {
|
||||
Render.enterBatchTexturedQuadMode(Res.getTexture("tiles16"));
|
||||
}
|
||||
|
||||
for (trc.y = y1; trc.y <= y2; trc.y++) {
|
||||
for (trc.x = x1; trc.x <= x2; trc.x++) {
|
||||
trc.renderTile();
|
||||
}
|
||||
}
|
||||
|
||||
if (USE_BATCH_RENDERING) {
|
||||
Render.leaveBatchTexturedQuadMode();
|
||||
}
|
||||
|
||||
// render extras
|
||||
for (trc.y = y1; trc.y <= y2; trc.y++) {
|
||||
for (trc.x = x1; trc.x <= x2; trc.x++) {
|
||||
trc.renderItems();
|
||||
}
|
||||
}
|
||||
|
||||
// render entities
|
||||
final EntityRenderContext erc = new EntityRenderContext(this, mapRect);
|
||||
for (final Entity e : entity_set) {
|
||||
e.render(erc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Entity getEntity(int eid)
|
||||
{
|
||||
return entity_map.get(eid);
|
||||
@@ -359,4 +270,10 @@ public class Level implements MapAccess, IonBinary {
|
||||
{
|
||||
getTile(x, y).setOccupied(false);
|
||||
}
|
||||
|
||||
|
||||
public Collection<Entity> getEntities()
|
||||
{
|
||||
return entity_set;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user