improved entity & world gen
This commit is contained in:
@@ -2,36 +2,39 @@ package mightypork.rogue.screens.gamescreen.world;
|
||||
|
||||
|
||||
import mightypork.gamecore.input.InputSystem;
|
||||
import mightypork.rogue.world.Coord;
|
||||
import mightypork.rogue.world.PlayerControl;
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.util.math.constraints.vect.Vect;
|
||||
|
||||
|
||||
public class MIPClickPathfWalk implements MapInteractionPlugin {
|
||||
|
||||
private static final int BTN = 1; // right
|
||||
|
||||
|
||||
@Override
|
||||
public void onStepEnd(MapView wv, PlayerControl player)
|
||||
public void onStepEnd(MapView view, PlayerControl player)
|
||||
{
|
||||
if (InputSystem.isMouseButtonDown(0)) {
|
||||
final WorldPos clicked = wv.toWorldPos(InputSystem.getMousePos());
|
||||
if (InputSystem.isMouseButtonDown(BTN)) {
|
||||
final Coord clicked = view.toWorldPos(InputSystem.getMousePos());
|
||||
player.navigateTo(clicked);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(MapView wv, PlayerControl player, Vect mouse, int button, boolean down)
|
||||
public void onClick(MapView view, PlayerControl player, Vect mouse, int button, boolean down)
|
||||
{
|
||||
if (!down) return;
|
||||
if (!down || button != BTN) return;
|
||||
|
||||
final WorldPos clicked = wv.toWorldPos(mouse);
|
||||
final Coord clicked = view.toWorldPos(mouse);
|
||||
|
||||
player.navigateTo(clicked);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onKey(MapView wv, PlayerControl player, int key, boolean down)
|
||||
public void onKey(MapView view, PlayerControl player, int key, boolean down)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -10,20 +10,20 @@ import mightypork.util.math.constraints.vect.Vect;
|
||||
public class MIPKeyWalk implements MapInteractionPlugin {
|
||||
|
||||
@Override
|
||||
public void onStepEnd(MapView wv, PlayerControl player)
|
||||
public void onStepEnd(MapView view, PlayerControl player)
|
||||
{
|
||||
walkByKey(player);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(MapView wv, PlayerControl player, Vect mouse, int button, boolean down)
|
||||
public void onClick(MapView view, PlayerControl player, Vect mouse, int button, boolean down)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onKey(MapView wv, PlayerControl player, int key, boolean down)
|
||||
public void onKey(MapView view, PlayerControl player, int key, boolean down)
|
||||
{
|
||||
if (down) walkByKey(player);
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ package mightypork.rogue.screens.gamescreen.world;
|
||||
|
||||
|
||||
import mightypork.gamecore.input.InputSystem;
|
||||
import mightypork.rogue.world.Coord;
|
||||
import mightypork.rogue.world.PlayerControl;
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.util.math.Calc.Deg;
|
||||
import mightypork.util.math.Polar;
|
||||
import mightypork.util.math.constraints.vect.Vect;
|
||||
@@ -12,22 +12,22 @@ import mightypork.util.math.constraints.vect.Vect;
|
||||
public class MIPMouseWalk implements MapInteractionPlugin {
|
||||
|
||||
@Override
|
||||
public void onStepEnd(MapView wv, PlayerControl player)
|
||||
public void onStepEnd(MapView world, PlayerControl player)
|
||||
{
|
||||
if (InputSystem.isMouseButtonDown(0)) {
|
||||
// walk by holding btn
|
||||
onClick(wv, player, InputSystem.getMousePos(), 0, true);
|
||||
onClick(world, player, InputSystem.getMousePos(), 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(MapView wv, PlayerControl player, Vect mouse, int button, boolean down)
|
||||
public void onClick(MapView world, PlayerControl player, Vect mouse, int button, boolean down)
|
||||
{
|
||||
if (!down) return;
|
||||
|
||||
final WorldPos plpos = player.getPos();
|
||||
final WorldPos clicked = wv.toWorldPos(mouse);
|
||||
final Coord plpos = player.getCoord();
|
||||
final Coord clicked = world.toWorldPos(mouse);
|
||||
|
||||
final Polar p = Polar.fromCoord(clicked.x - plpos.x, clicked.y - plpos.y);
|
||||
|
||||
@@ -54,7 +54,7 @@ public class MIPMouseWalk implements MapInteractionPlugin {
|
||||
|
||||
|
||||
@Override
|
||||
public void onKey(MapView wv, PlayerControl player, int key, boolean down)
|
||||
public void onKey(MapView world, PlayerControl player, int key, boolean down)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -9,13 +9,12 @@ import mightypork.gamecore.control.events.input.KeyListener;
|
||||
import mightypork.gamecore.control.events.input.MouseButtonEvent;
|
||||
import mightypork.gamecore.control.events.input.MouseButtonListener;
|
||||
import mightypork.gamecore.gui.components.InputComponent;
|
||||
import mightypork.rogue.world.Coord;
|
||||
import mightypork.rogue.world.PlayerControl;
|
||||
import mightypork.rogue.world.World;
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.rogue.world.WorldRenderer;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.entity.models.EntityMoveListener;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
import mightypork.util.math.constraints.vect.Vect;
|
||||
|
||||
|
||||
@@ -31,7 +30,7 @@ public class MapView extends InputComponent implements KeyListener, MouseButtonL
|
||||
public MapView(World world)
|
||||
{
|
||||
this.world = world;
|
||||
this.worldRenderer = new WorldRenderer(world, this, 12, 8, 40);//8, 8, 64
|
||||
this.worldRenderer = new WorldRenderer(world, this, 12, 8, 32);//8, 8, 64
|
||||
pc = world.getPlayerControl();
|
||||
pc.addMoveListener(this);
|
||||
}
|
||||
@@ -57,14 +56,14 @@ public class MapView extends InputComponent implements KeyListener, MouseButtonL
|
||||
* @param pos position on screen (px)
|
||||
* @return position on map (tiles)
|
||||
*/
|
||||
public WorldPos toWorldPos(Vect pos)
|
||||
public Coord toWorldPos(Vect pos)
|
||||
{
|
||||
return worldRenderer.getClickedTile(pos);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onStepFinished(Entity entity, World world, Level level)
|
||||
public void onStepFinished(Entity entity)
|
||||
{
|
||||
for (final MapInteractionPlugin p : plugins) {
|
||||
p.onStepEnd(this, pc);
|
||||
@@ -73,7 +72,7 @@ public class MapView extends InputComponent implements KeyListener, MouseButtonL
|
||||
|
||||
|
||||
@Override
|
||||
public void onPathFinished(Entity entity, World world, Level level)
|
||||
public void onPathFinished(Entity entity)
|
||||
{
|
||||
for (final MapInteractionPlugin p : plugins) {
|
||||
p.onStepEnd(this, pc);
|
||||
@@ -82,7 +81,7 @@ public class MapView extends InputComponent implements KeyListener, MouseButtonL
|
||||
|
||||
|
||||
@Override
|
||||
public void onPathInterrupted(Entity entity, World world, Level level)
|
||||
public void onPathInterrupted(Entity entity)
|
||||
{
|
||||
for (final MapInteractionPlugin p : plugins) {
|
||||
p.onStepEnd(this, pc);
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
package mightypork.rogue.world;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import mightypork.util.annotations.FactoryMethod;
|
||||
import mightypork.util.files.ion.IonBundle;
|
||||
import mightypork.util.files.ion.IonBundled;
|
||||
|
||||
|
||||
// coord
|
||||
public class Coord {
|
||||
/**
|
||||
* Coordinate
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class Coord implements IonBundled {
|
||||
|
||||
public int x;
|
||||
public int y;
|
||||
@@ -25,6 +33,13 @@ public class Coord {
|
||||
}
|
||||
|
||||
|
||||
@FactoryMethod
|
||||
public static Coord zero()
|
||||
{
|
||||
return make(0, 0);
|
||||
}
|
||||
|
||||
|
||||
public Coord(int x, int y)
|
||||
{
|
||||
super();
|
||||
@@ -58,6 +73,44 @@ public class Coord {
|
||||
}
|
||||
|
||||
|
||||
public void setTo(int x, int y)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
|
||||
public void setTo(Coord pos)
|
||||
{
|
||||
setTo(pos.x, pos.y);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if coord is in a range (inclusive)
|
||||
*/
|
||||
public boolean isInRange(int x0, int y0, int x1, int y1)
|
||||
{
|
||||
return !(x < x0 || x > x1 || y < y0 || y > y1);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void load(IonBundle bundle) throws IOException
|
||||
{
|
||||
x = bundle.get("x", 0);
|
||||
y = bundle.get("y", 0);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void save(IonBundle bundle) throws IOException
|
||||
{
|
||||
bundle.put("x", x);
|
||||
bundle.put("y", y);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
@@ -87,5 +140,4 @@ public class Coord {
|
||||
if (y != other.y) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+66
-56
@@ -12,25 +12,29 @@ import mightypork.util.timing.Updateable;
|
||||
|
||||
|
||||
/**
|
||||
* A simple dimension data object
|
||||
* Entity position
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class WorldPos implements IonBundled, Updateable {
|
||||
public class EntityPos implements IonBundled, Updateable {
|
||||
|
||||
public int x, y;
|
||||
private final Coord coord = new Coord(0, 0);
|
||||
private final VectAnimated walkOffset = new VectAnimated(Vect.ZERO, Easing.LINEAR);
|
||||
|
||||
|
||||
public WorldPos(int x, int y)
|
||||
public EntityPos(Coord pos)
|
||||
{
|
||||
super();
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.coord.setTo(pos);
|
||||
}
|
||||
|
||||
|
||||
public WorldPos()
|
||||
public EntityPos(int x, int y)
|
||||
{
|
||||
this.coord.setTo(x, y);
|
||||
}
|
||||
|
||||
|
||||
public EntityPos()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -44,8 +48,7 @@ public class WorldPos implements IonBundled, Updateable {
|
||||
@Override
|
||||
public void load(IonBundle in) throws IOException
|
||||
{
|
||||
x = in.get("x", 0);
|
||||
y = in.get("y", 0);
|
||||
in.loadBundled("pos", coord);
|
||||
walkOffset.reset();
|
||||
}
|
||||
|
||||
@@ -53,42 +56,41 @@ public class WorldPos implements IonBundled, Updateable {
|
||||
@Override
|
||||
public void save(IonBundle out) throws IOException
|
||||
{
|
||||
out.put("x", x);
|
||||
out.put("y", y);
|
||||
out.putBundled("pos", coord);
|
||||
}
|
||||
|
||||
|
||||
public double getX()
|
||||
public int x()
|
||||
{
|
||||
return x;
|
||||
return coord.x;
|
||||
}
|
||||
|
||||
|
||||
public double getY()
|
||||
public int y()
|
||||
{
|
||||
return y;
|
||||
return coord.y;
|
||||
}
|
||||
|
||||
|
||||
public double getVisualX()
|
||||
public double visualX()
|
||||
{
|
||||
return x + walkOffset.x();
|
||||
return coord.x + walkOffset.x();
|
||||
}
|
||||
|
||||
|
||||
public double getVisualY()
|
||||
public double visualY()
|
||||
{
|
||||
return y + walkOffset.y();
|
||||
return coord.y + walkOffset.y();
|
||||
}
|
||||
|
||||
|
||||
public double getVisualXOffset()
|
||||
public double visualXOffset()
|
||||
{
|
||||
return walkOffset.x();
|
||||
}
|
||||
|
||||
|
||||
public double getVisualYOffset()
|
||||
public double visualYOffset()
|
||||
{
|
||||
return walkOffset.y();
|
||||
}
|
||||
@@ -96,53 +98,37 @@ public class WorldPos implements IonBundled, Updateable {
|
||||
|
||||
public void setTo(int x, int y)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
coord.setTo(x, y);
|
||||
walkOffset.reset();
|
||||
}
|
||||
|
||||
|
||||
public void setTo(WorldPos other)
|
||||
public void setTo(EntityPos pos)
|
||||
{
|
||||
setTo(other.x, other.y);
|
||||
|
||||
setTo(pos.getCoord());
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void setTo(Coord c)
|
||||
{
|
||||
coord.setTo(c);
|
||||
walkOffset.reset();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "WorldPos(" + x + "," + y + ")";
|
||||
return "EntityPos{" + coord + "}";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
public void walk(PathStep step, double secs)
|
||||
{
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + x;
|
||||
result = prime * result + y;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (!(obj instanceof WorldPos)) return false;
|
||||
final WorldPos other = (WorldPos) obj;
|
||||
if (x != other.x) return false;
|
||||
if (y != other.y) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void walk(int x, int y, double secs)
|
||||
{
|
||||
setTo(this.x + x, this.y + y);
|
||||
walkOffset.setTo(-x, -y);
|
||||
setTo(coord.x + step.x, coord.y + step.y);
|
||||
walkOffset.setTo(-step.x, -step.y);
|
||||
walkOffset.animate(0, 0, 0, secs);
|
||||
}
|
||||
|
||||
@@ -160,9 +146,33 @@ public class WorldPos implements IonBundled, Updateable {
|
||||
}
|
||||
|
||||
|
||||
public Coord toCoord()
|
||||
public Coord getCoord()
|
||||
{
|
||||
return new Coord(x, y);
|
||||
return coord;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((coord == null) ? 0 : coord.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (!(obj instanceof EntityPos)) return false;
|
||||
final EntityPos other = (EntityPos) obj;
|
||||
if (coord == null) {
|
||||
if (other.coord != null) return false;
|
||||
} else if (!coord.equals(other.coord)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,6 +8,12 @@ import mightypork.util.files.ion.IonInput;
|
||||
import mightypork.util.files.ion.IonOutput;
|
||||
|
||||
|
||||
/**
|
||||
* Path step.<br>
|
||||
* Must be binary in order to be saveable in lists.
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class PathStep implements IonBinary {
|
||||
|
||||
public static final PathStep NORTH = new PathStep(0, -1);
|
||||
@@ -59,6 +65,12 @@ public class PathStep implements IonBinary {
|
||||
}
|
||||
|
||||
|
||||
public Coord toCoord()
|
||||
{
|
||||
return Coord.make(x, y);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public short getIonMark()
|
||||
{
|
||||
@@ -69,7 +81,7 @@ public class PathStep implements IonBinary {
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "(" + x + "|" + y + ")";
|
||||
return "(" + x + ";" + y + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,43 +1,15 @@
|
||||
package mightypork.rogue.world;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.entity.models.EntityMoveListener;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
import mightypork.rogue.world.pathfinding.PathCostProvider;
|
||||
import mightypork.rogue.world.pathfinding.PathFinder;
|
||||
|
||||
|
||||
public class PlayerControl {
|
||||
|
||||
private final World world;
|
||||
|
||||
PathCostProvider costProvider = new PathCostProvider() {
|
||||
|
||||
@Override
|
||||
public boolean isAccessible(Coord pos)
|
||||
{
|
||||
return getLevel().canWalkInto(pos.x, pos.y);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMinCost()
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getCost(Coord from, Coord to)
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
};
|
||||
|
||||
private final PathFinder pf = new PathFinder(costProvider, PathFinder.CORNER_HEURISTIC);
|
||||
|
||||
|
||||
public PlayerControl(World w)
|
||||
{
|
||||
@@ -45,56 +17,55 @@ public class PlayerControl {
|
||||
}
|
||||
|
||||
|
||||
public Entity getEntity()
|
||||
{
|
||||
return world.getPlayerEntity();
|
||||
}
|
||||
|
||||
|
||||
public void goNorth()
|
||||
{
|
||||
world.getPlayerEntity().cancelPath();
|
||||
world.getPlayerEntity().addStep(PathStep.NORTH);
|
||||
getEntity().cancelPath();
|
||||
getEntity().addStep(PathStep.NORTH);
|
||||
}
|
||||
|
||||
|
||||
public void goSouth()
|
||||
{
|
||||
world.getPlayerEntity().cancelPath();
|
||||
world.getPlayerEntity().addStep(PathStep.SOUTH);
|
||||
getEntity().cancelPath();
|
||||
getEntity().addStep(PathStep.SOUTH);
|
||||
}
|
||||
|
||||
|
||||
public void goEast()
|
||||
{
|
||||
world.getPlayerEntity().cancelPath();
|
||||
world.getPlayerEntity().addStep(PathStep.EAST);
|
||||
getEntity().cancelPath();
|
||||
getEntity().addStep(PathStep.EAST);
|
||||
}
|
||||
|
||||
|
||||
public void goWest()
|
||||
{
|
||||
world.getPlayerEntity().cancelPath();
|
||||
world.getPlayerEntity().addStep(PathStep.WEST);
|
||||
getEntity().cancelPath();
|
||||
getEntity().addStep(PathStep.WEST);
|
||||
}
|
||||
|
||||
|
||||
public void navigateTo(WorldPos where)
|
||||
public void navigateTo(Coord pos)
|
||||
{
|
||||
final Coord start = world.getPlayerEntity().getPosition().toCoord();
|
||||
final Coord end = where.toCoord();
|
||||
final List<PathStep> path = pf.findPathRelative(start, end);
|
||||
|
||||
if (path == null) return;
|
||||
|
||||
world.getPlayerEntity().cancelPath();
|
||||
world.getPlayerEntity().addSteps(path);
|
||||
getEntity().navigateTo(pos);
|
||||
}
|
||||
|
||||
|
||||
public void addMoveListener(EntityMoveListener eml)
|
||||
{
|
||||
world.getPlayerEntity().addMoveListener(eml);
|
||||
getEntity().addMoveListener(eml);
|
||||
}
|
||||
|
||||
|
||||
public WorldPos getPos()
|
||||
public EntityPos getPos()
|
||||
{
|
||||
return world.getPlayerEntity().getPosition();
|
||||
return getEntity().getPosition();
|
||||
}
|
||||
|
||||
|
||||
@@ -108,4 +79,10 @@ public class PlayerControl {
|
||||
{
|
||||
return world.getCurrentLevel();
|
||||
}
|
||||
|
||||
|
||||
public Coord getCoord()
|
||||
{
|
||||
return getEntity().getCoord();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,11 @@ public class World implements IonBundled, Updateable {
|
||||
|
||||
private final PlayerControl control = new PlayerControl(this);
|
||||
|
||||
private long seed; // world seed
|
||||
private int eid; // next entity ID
|
||||
/** World seed */
|
||||
private long seed;
|
||||
|
||||
/** Next entity ID */
|
||||
private int eid;
|
||||
|
||||
|
||||
@Override
|
||||
@@ -36,6 +39,12 @@ public class World implements IonBundled, Updateable {
|
||||
seed = in.get("seed", 0L);
|
||||
eid = in.get("next_eid", 0);
|
||||
in.loadSequence("levels", levels);
|
||||
|
||||
// join levels to world
|
||||
for (final Level lvl : levels) {
|
||||
lvl.setWorld(this);
|
||||
}
|
||||
|
||||
in.loadBundled("player", playerInfo);
|
||||
|
||||
playerEntity = levels.get(playerInfo.getLevel()).getEntity(playerInfo.getEID());
|
||||
@@ -61,7 +70,7 @@ public class World implements IonBundled, Updateable {
|
||||
@Override
|
||||
public void update(double delta)
|
||||
{
|
||||
getCurrentLevel().update(this, delta);
|
||||
getCurrentLevel().update(delta);
|
||||
}
|
||||
|
||||
|
||||
@@ -86,27 +95,19 @@ public class World implements IonBundled, Updateable {
|
||||
}
|
||||
|
||||
|
||||
public void createPlayer(WorldPos pos, int level)
|
||||
public void createPlayer(int level)
|
||||
{
|
||||
createPlayer(pos.x, pos.y, level);
|
||||
}
|
||||
|
||||
|
||||
public void createPlayer(int x, int y, int level)
|
||||
{
|
||||
if (playerInfo.isInitialized()) {
|
||||
throw new RuntimeException("Player already created.");
|
||||
}
|
||||
if (playerInfo.isInitialized()) { throw new RuntimeException("Player already created."); }
|
||||
|
||||
// make entity
|
||||
final int playerEid = getNewEID();
|
||||
|
||||
playerEntity = Entities.PLAYER.createEntity(playerEid, new WorldPos(x, y));
|
||||
playerEntity = Entities.PLAYER.createEntity(playerEid);
|
||||
levels.get(level).addEntity(playerEntity);
|
||||
playerEntity.setPosition(levels.get(level).getEnterPoint());
|
||||
|
||||
playerInfo.setLevel(level);
|
||||
playerInfo.setEID(playerEid);
|
||||
|
||||
levels.get(level).addEntity(playerEntity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,9 +23,10 @@ public class WorldCreator {
|
||||
Level l;
|
||||
|
||||
// first level
|
||||
l = LevelGenerator.build(rand.nextLong(), LevelGenerator.DUNGEON_THEME);
|
||||
l = LevelGenerator.build(rand.nextLong(), 2, LevelGenerator.DUNGEON_THEME); //
|
||||
w.addLevel(l);
|
||||
w.createPlayer(l.getEnterPoint(), 0);
|
||||
|
||||
w.createPlayer(0);
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
@@ -83,9 +83,9 @@ public class WorldRenderer extends RectProxy implements Pollable {
|
||||
|
||||
private Vect getOffset()
|
||||
{
|
||||
final WorldPos pos = player.getPosition();
|
||||
final double playerX = pos.getVisualX();
|
||||
final double playerY = pos.getVisualY();
|
||||
final EntityPos pos = player.getPosition();
|
||||
final double playerX = pos.visualX();
|
||||
final double playerY = pos.visualY();
|
||||
|
||||
final double ts = tileSize.value();
|
||||
|
||||
@@ -100,7 +100,7 @@ public class WorldRenderer extends RectProxy implements Pollable {
|
||||
Render.translate(getOffset());
|
||||
|
||||
// tiles to render
|
||||
final WorldPos pos = player.getPosition();
|
||||
final EntityPos pos = player.getPosition();
|
||||
final double w = width().value();
|
||||
final double h = height().value();
|
||||
final double ts = tileSize.value();
|
||||
@@ -108,10 +108,10 @@ public class WorldRenderer extends RectProxy implements Pollable {
|
||||
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;
|
||||
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 ===
|
||||
|
||||
@@ -120,8 +120,8 @@ public class WorldRenderer extends RectProxy implements Pollable {
|
||||
Render.enterBatchTexturedQuadMode(Res.getTexture("tiles16"));
|
||||
}
|
||||
|
||||
for (trc.y = y1; trc.y <= y2; trc.y++) {
|
||||
for (trc.x = x1; trc.x <= x2; trc.x++) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -132,8 +132,8 @@ public class WorldRenderer extends RectProxy implements Pollable {
|
||||
|
||||
// === ITEMS ON TILES ===
|
||||
|
||||
for (trc.y = y1; trc.y <= y2; trc.y++) {
|
||||
for (trc.x = x1; trc.x <= x2; trc.x++) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -143,8 +143,8 @@ public class WorldRenderer extends RectProxy implements Pollable {
|
||||
for (final Entity e : activeLevel.getEntities()) {
|
||||
|
||||
// avoid entities out of view rect
|
||||
final int x = (int) Math.round(e.getPosition().getVisualX());
|
||||
final int y = (int) Math.round(e.getPosition().getVisualY());
|
||||
final int x = (int) Math.round(e.getPosition().visualX());
|
||||
final int y = (int) Math.round(e.getPosition().visualY());
|
||||
|
||||
if (x < x1 - ts || x > x2 + ts) continue;
|
||||
if (y < y1 - ts || y > y2 + ts) continue;
|
||||
@@ -164,11 +164,11 @@ public class WorldRenderer extends RectProxy implements Pollable {
|
||||
}
|
||||
|
||||
|
||||
public WorldPos getClickedTile(Vect clickPos)
|
||||
public Coord getClickedTile(Vect clickPos)
|
||||
{
|
||||
final Vect v = clickPos.sub(mapRect.origin().add(getOffset()));
|
||||
final int ts = (int) tileSize.value();
|
||||
return new WorldPos(v.xi() / ts, v.yi() / ts);
|
||||
return new Coord(v.xi() / ts, v.yi() / ts);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -19,13 +19,9 @@ public final class Entities {
|
||||
|
||||
public static void register(int id, EntityModel model)
|
||||
{
|
||||
if (id < 0 || id >= entities.length) {
|
||||
throw new IllegalArgumentException("Entity model ID " + id + " is out of range.");
|
||||
}
|
||||
if (id < 0 || id >= entities.length) { throw new IllegalArgumentException("Entity model ID " + id + " is out of range."); }
|
||||
|
||||
if (entities[id] != null) {
|
||||
throw new IllegalArgumentException("Entity model ID " + id + " already in use.");
|
||||
}
|
||||
if (entities[id] != null) { throw new IllegalArgumentException("Entity model ID " + id + " already in use."); }
|
||||
|
||||
entities[id] = model;
|
||||
}
|
||||
@@ -35,9 +31,7 @@ public final class Entities {
|
||||
{
|
||||
final EntityModel e = entities[id];
|
||||
|
||||
if (e == null) {
|
||||
throw new IllegalArgumentException("No entity model with ID " + id + ".");
|
||||
}
|
||||
if (e == null) { throw new IllegalArgumentException("No entity model with ID " + id + "."); }
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
@@ -3,20 +3,21 @@ package mightypork.rogue.world.entity;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
|
||||
import mightypork.rogue.world.Coord;
|
||||
import mightypork.rogue.world.EntityPos;
|
||||
import mightypork.rogue.world.PathStep;
|
||||
import mightypork.rogue.world.World;
|
||||
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.MapRenderContext;
|
||||
import mightypork.rogue.world.pathfinding.Heuristic;
|
||||
import mightypork.rogue.world.pathfinding.PathFinder;
|
||||
import mightypork.rogue.world.pathfinding.PathFindingContext;
|
||||
import mightypork.util.files.ion.IonBinary;
|
||||
import mightypork.util.files.ion.IonBundle;
|
||||
import mightypork.util.files.ion.IonBundled;
|
||||
import mightypork.util.files.ion.IonInput;
|
||||
import mightypork.util.files.ion.IonOutput;
|
||||
|
||||
@@ -26,51 +27,68 @@ import mightypork.util.files.ion.IonOutput;
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public final class Entity implements IonBinary, IonBundled, EntityMoveListener {
|
||||
|
||||
// binary & bundled - binary stores via a bundle
|
||||
public final class Entity implements IonBinary, EntityMoveListener {
|
||||
|
||||
public static final int ION_MARK = 52;
|
||||
|
||||
private final WorldPos position = new WorldPos(); // saved
|
||||
private final WorldPos lastPosition = new WorldPos();
|
||||
/** Last pos, will be freed upon finishing move */
|
||||
private final EntityPos lastPosition = new EntityPos();
|
||||
private boolean walking = false;
|
||||
|
||||
private Level level;
|
||||
private EntityModel model;
|
||||
|
||||
/** Entity ID */
|
||||
private int eid = 0; // saved
|
||||
private int entityId = -1;
|
||||
|
||||
/** Model ID */
|
||||
private int id; // saved
|
||||
private int modelId = -1;
|
||||
|
||||
private final Queue<PathStep> path = new LinkedList<>(); // saved
|
||||
private EntityModel model;
|
||||
public final IonBundle metadata = new IonBundle(); // saved
|
||||
/** Entity data holder */
|
||||
private final EntityData data = new EntityData();
|
||||
|
||||
/** Some infos for/by the renderer, not saved */
|
||||
/** Temporary renderer's data */
|
||||
public final EntityRenderData renderData = new EntityRenderData();
|
||||
|
||||
private final List<EntityMoveListener> moveListeners = new ArrayList<>();
|
||||
|
||||
// tmp flag
|
||||
private boolean walking = false;
|
||||
|
||||
|
||||
public Entity(int eid, WorldPos pos, EntityModel entityModel)
|
||||
{
|
||||
this.eid = eid;
|
||||
setPosition(pos);
|
||||
private final PathFindingContext pfc = new PathFindingContext() {
|
||||
|
||||
@Override
|
||||
public boolean isAccessible(Coord pos)
|
||||
{
|
||||
return model.canWalkInto(Entity.this, pos);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMinCost()
|
||||
{
|
||||
return model.getPathMinCost();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Heuristic getHeuristic()
|
||||
{
|
||||
return model.getPathHeuristic();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getCost(Coord from, Coord to)
|
||||
{
|
||||
return model.getPathCost(Entity.this, from, to);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public Entity(int eid, EntityModel entityModel)
|
||||
{
|
||||
this.entityId = eid;
|
||||
setModel(entityModel);
|
||||
}
|
||||
|
||||
|
||||
protected final void setModel(EntityModel entityModel)
|
||||
{
|
||||
// replace listener
|
||||
if (model != null) moveListeners.remove(model);
|
||||
moveListeners.add(entityModel);
|
||||
|
||||
this.id = entityModel.id;
|
||||
this.model = entityModel;
|
||||
model.initMetadata(data);
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +98,30 @@ public final class Entity implements IonBinary, IonBundled, EntityMoveListener {
|
||||
}
|
||||
|
||||
|
||||
private void setModel(EntityModel entityModel)
|
||||
{
|
||||
// replace listener
|
||||
if (model != null) moveListeners.remove(model);
|
||||
moveListeners.add(entityModel);
|
||||
|
||||
this.modelId = entityModel.id;
|
||||
this.model = entityModel;
|
||||
}
|
||||
|
||||
|
||||
public Level getLevel()
|
||||
{
|
||||
if (level == null) throw new IllegalStateException("Entity has no level assigned.");
|
||||
return level;
|
||||
}
|
||||
|
||||
|
||||
public World getWorld()
|
||||
{
|
||||
return getLevel().getWorld();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public short getIonMark()
|
||||
{
|
||||
@@ -90,114 +132,81 @@ public final class Entity implements IonBinary, IonBundled, EntityMoveListener {
|
||||
@Override
|
||||
public void save(IonOutput out) throws IOException
|
||||
{
|
||||
final IonBundle ib = new IonBundle();
|
||||
save(ib);
|
||||
out.writeBundle(ib);
|
||||
final IonBundle bundle = new IonBundle();
|
||||
bundle.put("model", modelId);
|
||||
bundle.put("id", entityId);
|
||||
bundle.putBundled("data", data);
|
||||
|
||||
out.writeBundle(bundle);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void load(IonInput in) throws IOException
|
||||
{
|
||||
load(in.readBundle());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void save(IonBundle bundle) throws IOException
|
||||
{
|
||||
bundle.put("id", id);
|
||||
bundle.putBundled("pos", position);
|
||||
bundle.putSequence("steps", path);
|
||||
bundle.put("eid", eid);
|
||||
final IonBundle bundle = in.readBundle();
|
||||
modelId = bundle.get("model", 0);
|
||||
entityId = bundle.get("id", entityId);
|
||||
bundle.loadBundled("data", data);
|
||||
|
||||
if (model.hasMetadata()) {
|
||||
bundle.put("metadata", metadata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void load(IonBundle bundle) throws IOException
|
||||
{
|
||||
id = bundle.get("id", 0);
|
||||
|
||||
if (model == null || id != model.id) {
|
||||
setModel(Entities.get(id));
|
||||
}
|
||||
|
||||
bundle.loadBundled("pos", position);
|
||||
bundle.loadSequence("path", path);
|
||||
eid = bundle.get("eid", eid);
|
||||
|
||||
if (model.hasMetadata()) {
|
||||
metadata.clear();
|
||||
bundle.loadBundle("metadata", metadata);
|
||||
}
|
||||
setModel(Entities.get(modelId));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return unique entity id
|
||||
*/
|
||||
public int getEID()
|
||||
public int getEntityId()
|
||||
{
|
||||
return eid;
|
||||
return entityId;
|
||||
}
|
||||
|
||||
|
||||
public WorldPos getPosition()
|
||||
public EntityPos getPosition()
|
||||
{
|
||||
return position;
|
||||
return data.position;
|
||||
}
|
||||
|
||||
|
||||
public final void setPosition(WorldPos pos)
|
||||
public void setPosition(Coord coord)
|
||||
{
|
||||
setPosition(pos.x, pos.y);
|
||||
}
|
||||
|
||||
|
||||
public void setPosition(int x, int y)
|
||||
{
|
||||
position.setTo(x, y);
|
||||
lastPosition.setTo(x, y);
|
||||
data.position.setTo(coord);
|
||||
lastPosition.setTo(coord);
|
||||
cancelPath(); // discard remaining steps
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param world the world
|
||||
* @param delta delta time
|
||||
*/
|
||||
public void update(World world, Level level, double delta)
|
||||
public void update(double delta)
|
||||
{
|
||||
if (!position.isFinished()) {
|
||||
position.update(delta);
|
||||
if (!data.position.isFinished()) {
|
||||
data.position.update(delta);
|
||||
}
|
||||
|
||||
if (walking && position.isFinished()) {
|
||||
if (walking && data.position.isFinished()) {
|
||||
walking = false;
|
||||
level.freeTile(lastPosition.x, lastPosition.y);
|
||||
level.freeTile(lastPosition.getCoord());
|
||||
|
||||
onStepFinished(this, world, level);
|
||||
onStepFinished(this);
|
||||
|
||||
if (path.isEmpty()) {
|
||||
onPathFinished(this, world, level);
|
||||
if (data.path.isEmpty()) {
|
||||
onPathFinished(this);
|
||||
}
|
||||
}
|
||||
|
||||
if (!walking && !path.isEmpty()) {
|
||||
if (!walking && !data.path.isEmpty()) {
|
||||
|
||||
walking = true;
|
||||
|
||||
final PathStep step = path.poll();
|
||||
final PathStep step = data.path.poll();
|
||||
|
||||
final int projX = position.x + step.x, projY = position.y + step.y;
|
||||
final Coord planned = data.position.getCoord().add(step.toCoord());
|
||||
|
||||
if (!level.canWalkInto(projX, projY)) {
|
||||
if (!level.canWalkInto(planned)) {
|
||||
cancelPath();
|
||||
onPathInterrupted(this, world, level);
|
||||
onPathInterrupted(this);
|
||||
walking = false;
|
||||
} else {
|
||||
|
||||
@@ -205,14 +214,14 @@ public final class Entity implements IonBinary, IonBundled, EntityMoveListener {
|
||||
if (step.x != 0) renderData.lastXDir = step.x;
|
||||
if (step.y != 0) renderData.lastYDir = step.y;
|
||||
|
||||
lastPosition.setTo(position);
|
||||
position.walk(step.x, step.y, getStepTime());
|
||||
level.occupyTile(projX, projY);
|
||||
lastPosition.setTo(data.position);
|
||||
data.position.walk(step, model.getStepTime(this));
|
||||
level.occupyTile(planned);
|
||||
}
|
||||
}
|
||||
|
||||
if (!walking) {
|
||||
model.update(this, level, delta);
|
||||
model.update(this, delta);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,51 +234,57 @@ public final class Entity implements IonBinary, IonBundled, EntityMoveListener {
|
||||
|
||||
public boolean isPathFinished()
|
||||
{
|
||||
return position.isFinished() && path.isEmpty();
|
||||
return data.position.isFinished() && data.path.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
public void addStep(PathStep step)
|
||||
{
|
||||
path.add(step);
|
||||
data.path.add(step);
|
||||
}
|
||||
|
||||
|
||||
public void cancelPath()
|
||||
{
|
||||
path.clear();
|
||||
data.path.clear();
|
||||
}
|
||||
|
||||
|
||||
protected double getStepTime()
|
||||
public boolean navigateTo(Coord pos)
|
||||
{
|
||||
return model.getStepTime(this);
|
||||
final List<PathStep> path = PathFinder.findPathRelative(pfc, getPosition().getCoord(), pos);
|
||||
|
||||
if (path == null) return false;
|
||||
|
||||
this.cancelPath();
|
||||
this.addSteps(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onStepFinished(Entity entity, World world, Level level)
|
||||
public void onStepFinished(Entity entity)
|
||||
{
|
||||
for (final EntityMoveListener l : moveListeners) {
|
||||
l.onStepFinished(entity, world, level);
|
||||
l.onStepFinished(entity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPathFinished(Entity entity, World world, Level level)
|
||||
public void onPathFinished(Entity entity)
|
||||
{
|
||||
for (final EntityMoveListener l : moveListeners) {
|
||||
l.onStepFinished(entity, world, level);
|
||||
l.onStepFinished(entity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPathInterrupted(Entity entity, World world, Level level)
|
||||
public void onPathInterrupted(Entity entity)
|
||||
{
|
||||
for (final EntityMoveListener l : moveListeners) {
|
||||
l.onPathInterrupted(entity, world, level);
|
||||
l.onPathInterrupted(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,6 +297,18 @@ public final class Entity implements IonBinary, IonBundled, EntityMoveListener {
|
||||
|
||||
public void addSteps(List<PathStep> path)
|
||||
{
|
||||
this.path.addAll(path);
|
||||
data.path.addAll(path);
|
||||
}
|
||||
|
||||
|
||||
public void setLevel(Level level)
|
||||
{
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
|
||||
public Coord getCoord()
|
||||
{
|
||||
return data.position.getCoord();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package mightypork.rogue.world.entity;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
import mightypork.rogue.world.EntityPos;
|
||||
import mightypork.rogue.world.PathStep;
|
||||
import mightypork.util.files.ion.IonBundle;
|
||||
import mightypork.util.files.ion.IonBundled;
|
||||
|
||||
|
||||
public class EntityData implements IonBundled {
|
||||
|
||||
public int health = 1;
|
||||
public int maxHealth = 1;
|
||||
public boolean dead = false;
|
||||
|
||||
public final IonBundle extra = new IonBundle();
|
||||
public final Queue<PathStep> path = new LinkedList<>();
|
||||
public final EntityPos position = new EntityPos();
|
||||
|
||||
|
||||
@Override
|
||||
public void save(IonBundle bundle) throws IOException
|
||||
{
|
||||
bundle.put("health", health);
|
||||
bundle.put("max_health", maxHealth);
|
||||
bundle.put("dead", dead);
|
||||
bundle.putSequence("steps", path);
|
||||
bundle.putBundled("pos", position);
|
||||
|
||||
bundle.put("extra", extra);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void load(IonBundle bundle) throws IOException
|
||||
{
|
||||
health = bundle.get("health", health);
|
||||
maxHealth = bundle.get("max_health", maxHealth);
|
||||
dead = bundle.get("dead", dead);
|
||||
bundle.loadSequence("path", path);
|
||||
bundle.loadBundled("pos", position);
|
||||
|
||||
bundle.loadBundle("extra", extra);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
package mightypork.rogue.world.entity.models;
|
||||
|
||||
|
||||
import mightypork.rogue.world.World;
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.rogue.world.Coord;
|
||||
import mightypork.rogue.world.entity.Entities;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.entity.EntityData;
|
||||
import mightypork.rogue.world.entity.renderers.EntityRenderer;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
import mightypork.rogue.world.pathfinding.Heuristic;
|
||||
import mightypork.rogue.world.pathfinding.PathFinder;
|
||||
|
||||
|
||||
/**
|
||||
@@ -38,22 +39,16 @@ public abstract class EntityModel implements EntityMoveListener {
|
||||
/**
|
||||
* @return new tile of this type; if 100% invariant, can return cached one.
|
||||
*/
|
||||
public Entity createEntity(int eid, WorldPos pos)
|
||||
public Entity createEntity(int eid)
|
||||
{
|
||||
return new Entity(eid, pos, this);
|
||||
return new Entity(eid, this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Entity is idle, waiting for action.
|
||||
*/
|
||||
public abstract void update(Entity entity, Level level, double delta);
|
||||
|
||||
|
||||
/**
|
||||
* @return true if this entity type has metadata worth saving
|
||||
*/
|
||||
public abstract boolean hasMetadata();
|
||||
public abstract void update(Entity entity, double delta);
|
||||
|
||||
|
||||
/**
|
||||
@@ -63,14 +58,41 @@ public abstract class EntityModel implements EntityMoveListener {
|
||||
|
||||
|
||||
@Override
|
||||
public abstract void onStepFinished(Entity entity, World world, Level level);
|
||||
public abstract void onStepFinished(Entity entity);
|
||||
|
||||
|
||||
@Override
|
||||
public abstract void onPathFinished(Entity entity, World world, Level level);
|
||||
public abstract void onPathFinished(Entity entity);
|
||||
|
||||
|
||||
@Override
|
||||
public abstract void onPathInterrupted(Entity entity, World world, Level level);
|
||||
public abstract void onPathInterrupted(Entity entity);
|
||||
|
||||
|
||||
public boolean canWalkInto(Entity entity, Coord pos)
|
||||
{
|
||||
return entity.getLevel().canWalkInto(pos);
|
||||
}
|
||||
|
||||
|
||||
public int getPathMinCost()
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
|
||||
public Heuristic getPathHeuristic()
|
||||
{
|
||||
return PathFinder.DIAGONAL_HEURISTIC;
|
||||
}
|
||||
|
||||
|
||||
public int getPathCost(Entity entity, Coord from, Coord to)
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
|
||||
public abstract void initMetadata(EntityData metadata);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package mightypork.rogue.world.entity.models;
|
||||
|
||||
|
||||
import mightypork.rogue.world.World;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
|
||||
|
||||
public interface EntityMoveListener {
|
||||
@@ -11,18 +9,18 @@ public interface EntityMoveListener {
|
||||
/**
|
||||
* One step of a path finished
|
||||
*/
|
||||
void onStepFinished(Entity entity, World world, Level level);
|
||||
void onStepFinished(Entity entity);
|
||||
|
||||
|
||||
/**
|
||||
* Scheduled path finished
|
||||
*/
|
||||
void onPathFinished(Entity entity, World world, Level level);
|
||||
void onPathFinished(Entity entity);
|
||||
|
||||
|
||||
/**
|
||||
* Path was interrupted (bumped into a wall or entity)
|
||||
*/
|
||||
void onPathInterrupted(Entity entity, World world, Level level);
|
||||
void onPathInterrupted(Entity entity);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package mightypork.rogue.world.entity.models;
|
||||
|
||||
|
||||
import mightypork.rogue.world.World;
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.entity.EntityData;
|
||||
import mightypork.rogue.world.entity.renderers.PlayerRenderer;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
|
||||
|
||||
/**
|
||||
@@ -15,7 +13,7 @@ import mightypork.rogue.world.level.Level;
|
||||
*/
|
||||
public class PlayerModel extends EntityModel {
|
||||
|
||||
private static final double STEP_TIME = 0.3;
|
||||
private static final double STEP_TIME = 0.25;
|
||||
|
||||
|
||||
public PlayerModel(int id)
|
||||
@@ -26,26 +24,8 @@ public class PlayerModel extends EntityModel {
|
||||
|
||||
|
||||
@Override
|
||||
public Entity createEntity(int eid, WorldPos pos)
|
||||
public void update(Entity entity, double delta)
|
||||
{
|
||||
final Entity e = super.createEntity(eid, pos);
|
||||
|
||||
// set metadata
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void update(Entity entity, Level level, double delta)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasMetadata()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,19 +37,25 @@ public class PlayerModel extends EntityModel {
|
||||
|
||||
|
||||
@Override
|
||||
public void onStepFinished(Entity entity, World world, Level level)
|
||||
public void onStepFinished(Entity entity)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPathFinished(Entity entity, World world, Level level)
|
||||
public void onPathFinished(Entity entity)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPathInterrupted(Entity entity, World world, Level level)
|
||||
public void onPathInterrupted(Entity entity)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void initMetadata(EntityData metadata)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import mightypork.gamecore.render.Render;
|
||||
import mightypork.gamecore.render.textures.TxQuad;
|
||||
import mightypork.gamecore.render.textures.TxSheet;
|
||||
import mightypork.rogue.Res;
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.rogue.world.EntityPos;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.level.render.MapRenderContext;
|
||||
import mightypork.util.math.Calc;
|
||||
@@ -30,12 +30,12 @@ public class PlayerRenderer extends EntityRenderer {
|
||||
|
||||
if (entity.renderData.lastXDir == -1) q = q.flipX();
|
||||
|
||||
final WorldPos pos = entity.getPosition();
|
||||
final EntityPos pos = entity.getPosition();
|
||||
|
||||
final Rect tileRect = context.getRectForTile(pos.x, pos.y);
|
||||
final Rect tileRect = context.getRectForTile(pos.getCoord());
|
||||
final double w = tileRect.width().value();
|
||||
|
||||
Rect spriteRect = tileRect.move(pos.getVisualXOffset() * w, pos.getVisualYOffset() * w);
|
||||
Rect spriteRect = tileRect.move(pos.visualXOffset() * w, pos.visualYOffset() * w);
|
||||
spriteRect = spriteRect.shrink(w * 0.1);
|
||||
|
||||
Render.quadTextured(spriteRect, q);
|
||||
|
||||
@@ -18,22 +18,22 @@ public class LevelGenerator {
|
||||
private static final RoomBuilder DEAD_END = new DeadEndRoom();
|
||||
|
||||
|
||||
public static Level build(long seed, Theme theme)
|
||||
public static Level build(long seed, int complexity, Theme theme)
|
||||
{
|
||||
final Random rand = new Random(seed + 13);
|
||||
|
||||
final int max_size = 512;
|
||||
final int max_size = 256;
|
||||
|
||||
final ScratchMap map = new ScratchMap(max_size, theme, rand);
|
||||
|
||||
// start
|
||||
map.addRoom(ROOM_SQUARE);
|
||||
|
||||
for (int i = 0; i < 5 + rand.nextInt(8); i++) {
|
||||
for (int i = 0; i < 2 + rand.nextInt(1 + complexity + (int) Math.pow(complexity, 1.6)); i++) {
|
||||
map.addRoom(ROOM_SQUARE);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5 + rand.nextInt(6); i++) {
|
||||
for (int i = 0; i < 2 + rand.nextInt(1 + complexity / 3 + (int) Math.pow(complexity, 1.2)); i++) {
|
||||
map.addRoom(DEAD_END);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,9 +30,7 @@ public class RoomDesc {
|
||||
int rw = amax.x - amin.x;
|
||||
int rh = amax.y - amin.y;
|
||||
|
||||
if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) {
|
||||
return false;
|
||||
}
|
||||
if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) { return false; }
|
||||
|
||||
final int tx = min.x;
|
||||
final int ty = min.y;
|
||||
|
||||
@@ -6,10 +6,10 @@ import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import mightypork.rogue.world.Coord;
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
import mightypork.rogue.world.pathfinding.PathCostProvider;
|
||||
import mightypork.rogue.world.pathfinding.Heuristic;
|
||||
import mightypork.rogue.world.pathfinding.PathFinder;
|
||||
import mightypork.rogue.world.pathfinding.PathFindingContext;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.rogue.world.tile.TileModel;
|
||||
import mightypork.rogue.world.tile.Tiles;
|
||||
@@ -18,14 +18,27 @@ import mightypork.util.logging.Log;
|
||||
|
||||
public class ScratchMap {
|
||||
|
||||
private final Tile[][] map;
|
||||
//@formatter:off
|
||||
public static final Coord[] MOVES = {
|
||||
Coord.make(-1, 0),
|
||||
Coord.make(-1, -1),
|
||||
Coord.make(0, -1),
|
||||
Coord.make(1, -1),
|
||||
Coord.make(1, 0),
|
||||
Coord.make(1, 1),
|
||||
Coord.make(0, 1),
|
||||
Coord.make(-1, 1)
|
||||
};
|
||||
//@formatter:on
|
||||
|
||||
private Tile[][] map;
|
||||
private final int width;
|
||||
private final int height;
|
||||
|
||||
private final List<RoomDesc> rooms = new ArrayList<>();
|
||||
private final List<Coord> nodes = new ArrayList<>(); // points to connect with corridors
|
||||
|
||||
private final PathCostProvider pcp = new PathCostProvider() {
|
||||
private final PathFindingContext pfc = new PathFindingContext() {
|
||||
|
||||
@Override
|
||||
public boolean isAccessible(Coord pos)
|
||||
@@ -39,12 +52,14 @@ public class ScratchMap {
|
||||
{
|
||||
final Tile t = get(pos);
|
||||
|
||||
if (t.isNull()) return 15;
|
||||
if (t.isNull()) return 60;
|
||||
|
||||
if (t.isDoor()) return 10; // door
|
||||
if (t.isFloor()) return 20; // floor
|
||||
|
||||
return 400; // wall
|
||||
|
||||
if (t.isWall() && t.genData.isProtected) return 1000;
|
||||
|
||||
return 100; // wall
|
||||
}
|
||||
|
||||
|
||||
@@ -54,16 +69,27 @@ public class ScratchMap {
|
||||
return 10;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Heuristic getHeuristic()
|
||||
{
|
||||
return PathFinder.CORNER_HEURISTIC;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private final PathFinder pathFinder = new PathFinder(pcp, PathFinder.CORNER_HEURISTIC);
|
||||
|
||||
Coord genMin;
|
||||
Coord genMax;
|
||||
|
||||
private final Theme theme;
|
||||
private final Random rand;
|
||||
private Coord enterPoint;
|
||||
|
||||
public static final byte CARDINAL = (byte) 0b10101010;
|
||||
public static final byte DIAGONAL = (byte) 0b01010101;
|
||||
|
||||
private static final boolean FIX_GLITCHES = true;
|
||||
|
||||
|
||||
public ScratchMap(int max_size, Theme theme, Random rand)
|
||||
{
|
||||
@@ -77,7 +103,7 @@ public class ScratchMap {
|
||||
this.rand = rand;
|
||||
this.theme = theme;
|
||||
|
||||
fill(Coord.make(0, 0), Coord.make(width - 1, height - 1), Tiles.NULL_EMPTY);
|
||||
fill(Coord.make(0, 0), Coord.make(width - 1, height - 1), Tiles.NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -148,9 +174,7 @@ public class ScratchMap {
|
||||
|
||||
public Tile get(Coord pos)
|
||||
{
|
||||
if (!isIn(pos)) {
|
||||
throw new IndexOutOfBoundsException("Tile not in map: " + pos);
|
||||
}
|
||||
if (!isIn(pos)) { throw new IndexOutOfBoundsException("Tile not in map: " + pos); }
|
||||
|
||||
return map[pos.y][pos.x];
|
||||
}
|
||||
@@ -164,9 +188,7 @@ public class ScratchMap {
|
||||
|
||||
public boolean set(Coord pos, Tile tile)
|
||||
{
|
||||
if (!isIn(pos)) {
|
||||
throw new IndexOutOfBoundsException("Tile not in map: " + pos);
|
||||
}
|
||||
if (!isIn(pos)) { throw new IndexOutOfBoundsException("Tile not in map: " + pos); }
|
||||
|
||||
map[pos.y][pos.x] = tile;
|
||||
return true;
|
||||
@@ -184,6 +206,17 @@ public class ScratchMap {
|
||||
}
|
||||
|
||||
|
||||
public void protect(Coord min, Coord max)
|
||||
{
|
||||
if (!isIn(min) || !isIn(max)) throw new IndexOutOfBoundsException("Tile(s) not in map: " + min + " , " + max);
|
||||
|
||||
final Coord c = Coord.make(0, 0);
|
||||
for (c.x = min.x; c.x <= max.x; c.x++)
|
||||
for (c.y = min.y; c.y <= max.y; c.y++)
|
||||
get(c).genData.isProtected = true;
|
||||
}
|
||||
|
||||
|
||||
public void fill(Coord min, Coord max, TileModel tm)
|
||||
{
|
||||
if (!isIn(min) || !isIn(max)) throw new IndexOutOfBoundsException("Tile(s) not in map: " + min + " , " + max);
|
||||
@@ -200,14 +233,23 @@ public class ScratchMap {
|
||||
if (!isIn(min) || !isIn(max)) throw new IndexOutOfBoundsException("Tile(s) not in map: " + min + " , " + max);
|
||||
|
||||
final Coord c = Coord.make(0, 0);
|
||||
for (c.x = min.x; c.x <= max.x; c.x++) {
|
||||
for (c.y = min.y; c.y <= max.y; c.y++) {
|
||||
|
||||
if (c.y > min.y && c.y < max.y && c.x > min.x && c.x < max.x) continue;
|
||||
|
||||
set(c, tm.createTile());
|
||||
}
|
||||
}
|
||||
|
||||
// top
|
||||
for (c.x = min.x, c.y = min.y; c.x <= max.x; c.x++)
|
||||
set(c, tm.createTile());
|
||||
|
||||
//bottom
|
||||
for (c.x = min.x, c.y = max.y; c.x <= max.x; c.x++)
|
||||
set(c, tm.createTile());
|
||||
|
||||
//left
|
||||
for (c.x = min.x, c.y = min.y + 1; c.y < max.y; c.y++)
|
||||
set(c, tm.createTile());
|
||||
|
||||
//right
|
||||
for (c.x = max.x, c.y = min.y + 1; c.y < max.y; c.y++)
|
||||
set(c, tm.createTile());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -225,7 +267,7 @@ public class ScratchMap {
|
||||
private void buildCorridor(Coord node1, Coord node2)
|
||||
{
|
||||
//Log.f3("Finding path " + node1 + " -> " + node2);
|
||||
final List<Coord> steps = pathFinder.findPath(node1, node2);
|
||||
final List<Coord> steps = PathFinder.findPath(pfc, node1, node2);
|
||||
|
||||
if (steps == null) {
|
||||
Log.w("Could not build corridor " + node1 + "->" + node2);
|
||||
@@ -254,10 +296,11 @@ public class ScratchMap {
|
||||
|
||||
final Tile current = get(c);
|
||||
if (!current.isNull() && (current.isPotentiallyWalkable())) continue; // floor already, let it be
|
||||
|
||||
|
||||
if (i == 0 && j == 0) {
|
||||
set(c, theme.floor());
|
||||
} else {
|
||||
if (current.isWall()) continue;
|
||||
set(c, theme.wall());
|
||||
}
|
||||
}
|
||||
@@ -271,7 +314,7 @@ public class ScratchMap {
|
||||
}
|
||||
|
||||
|
||||
private int countBits(byte b)
|
||||
public int countBits(byte b)
|
||||
{
|
||||
int c = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
@@ -281,129 +324,158 @@ public class ScratchMap {
|
||||
}
|
||||
|
||||
|
||||
public byte findWalls(Coord pos)
|
||||
{
|
||||
byte walls = 0;
|
||||
for (int i = 0; i <= 7; i++) {
|
||||
final Coord cc = pos.add(MOVES[i]);
|
||||
if (!isIn(cc)) continue;
|
||||
|
||||
if (get(cc).isWall()) {
|
||||
walls |= 1 << (7 - i);
|
||||
}
|
||||
}
|
||||
return walls;
|
||||
}
|
||||
|
||||
|
||||
public byte findFloors(Coord pos)
|
||||
{
|
||||
byte floors = 0;
|
||||
for (int i = 0; i <= 7; i++) {
|
||||
final Coord cc = pos.add(MOVES[i]);
|
||||
if (!isIn(cc)) continue;
|
||||
|
||||
if (get(cc).isFloor()) {
|
||||
floors |= 1 << (7 - i);
|
||||
}
|
||||
}
|
||||
return floors;
|
||||
}
|
||||
|
||||
|
||||
public byte findDoors(Coord pos)
|
||||
{
|
||||
byte doors = 0;
|
||||
for (int i = 0; i <= 7; i++) {
|
||||
final Coord cc = pos.add(MOVES[i]);
|
||||
if (!isIn(cc)) continue;
|
||||
|
||||
if (get(cc).isDoor()) {
|
||||
doors |= 1 << (7 - i);
|
||||
}
|
||||
}
|
||||
return doors;
|
||||
}
|
||||
|
||||
|
||||
public byte findNils(Coord pos)
|
||||
{
|
||||
byte nils = 0;
|
||||
for (int i = 0; i <= 7; i++) {
|
||||
final Coord cc = pos.add(MOVES[i]);
|
||||
|
||||
if (!isIn(cc) || get(cc).isNull()) {
|
||||
nils |= 1 << (7 - i);
|
||||
}
|
||||
}
|
||||
return nils;
|
||||
}
|
||||
|
||||
|
||||
public void writeToLevel(Level level)
|
||||
{
|
||||
//@formatter:off
|
||||
final Coord[] moves = {
|
||||
Coord.make(-1, 0),
|
||||
Coord.make(-1, -1),
|
||||
Coord.make(0, -1),
|
||||
Coord.make(1, -1),
|
||||
Coord.make(1, 0),
|
||||
Coord.make(1, 1),
|
||||
Coord.make(0, 1),
|
||||
Coord.make(-1, 1)
|
||||
};
|
||||
//@formatter:on
|
||||
|
||||
final byte cardinal = (byte) 0b10101010;
|
||||
final byte diagonal = (byte) 0b01010101;
|
||||
|
||||
// make sure no walkable are at edges.
|
||||
final Coord c = Coord.make(0, 0);
|
||||
final Coord c1 = Coord.make(0, 0);
|
||||
for (c.x = 0; c.x < width; c.x++) {
|
||||
for (c.y = 0; c.y < height; c.y++) {
|
||||
|
||||
final Tile t = get(c);
|
||||
final boolean isNull = t.isNull();
|
||||
|
||||
final boolean isDoor = !isNull && t.isDoor();
|
||||
final boolean isFloor = !isNull && t.isFloor();
|
||||
final boolean isWall = !isNull && t.isWall();
|
||||
|
||||
// bitmasks
|
||||
byte walls = 0;
|
||||
byte nils = 0;
|
||||
byte doors = 0;
|
||||
byte floors = 0;
|
||||
|
||||
// gather info
|
||||
for (int i = 0; i <= 7; i++) {
|
||||
final Coord cc = c.add(moves[i]);
|
||||
|
||||
if (FIX_GLITCHES) {
|
||||
|
||||
final Tile[][] out = new Tile[height][width];
|
||||
|
||||
for (c.x = 0; c.x < width; c.x++) {
|
||||
for (c.y = 0; c.y < height; c.y++) {
|
||||
|
||||
if (!isIn(cc)) {
|
||||
nils |= 1 << (7 - i);
|
||||
continue;
|
||||
}
|
||||
final Tile t = get(c);
|
||||
final boolean isNull = t.isNull();
|
||||
|
||||
final Tile t2 = get(cc);
|
||||
final boolean isDoor = !isNull && t.isDoor();
|
||||
final boolean isFloor = !isNull && t.isFloor();
|
||||
final boolean isWall = !isNull && t.isWall();
|
||||
|
||||
if (t2.isNull()) {
|
||||
nils |= 1 << (7 - i);
|
||||
continue;
|
||||
}
|
||||
// bitmasks
|
||||
final byte walls = findWalls(c);
|
||||
final byte nils = findNils(c);
|
||||
final byte floors = findFloors(c);
|
||||
|
||||
if (t2.isDoor()) {
|
||||
doors |= 1 << (7 - i);
|
||||
continue;
|
||||
}
|
||||
boolean toWall = false;
|
||||
boolean toFloor = false;
|
||||
boolean toNull = false;
|
||||
|
||||
if (t2.isWall()) {
|
||||
walls |= 1 << (7 - i);
|
||||
continue;
|
||||
}
|
||||
|
||||
floors |= 1 << (7 - i);
|
||||
}
|
||||
|
||||
boolean toWall = false;
|
||||
boolean toFloor = false;
|
||||
boolean toNull = false;
|
||||
|
||||
if (isFloor && (nils & cardinal) != 0) {
|
||||
toWall = true; // floor with adjacent cardinal null
|
||||
}
|
||||
|
||||
if (isNull && (floors & diagonal) != 0) {
|
||||
toWall = true; // null with adjacent diagonal floor
|
||||
}
|
||||
|
||||
if (isWall && floors == 0) {
|
||||
toNull = true;
|
||||
}
|
||||
|
||||
if (isDoor) {
|
||||
do {
|
||||
if (countBits((byte) (floors & cardinal)) < 2) {
|
||||
toWall = true;
|
||||
if (isWall && floors == 0) {
|
||||
toNull = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (countBits((byte) (walls & cardinal)) > 2) {
|
||||
toWall = true;
|
||||
if (isFloor && (nils & CARDINAL) != 0) {
|
||||
toWall = true; // floor with adjacent cardinal null
|
||||
break;
|
||||
}
|
||||
|
||||
if (countBits((byte) (floors & cardinal)) > 2) {
|
||||
toFloor = true;
|
||||
if (isNull && (floors & DIAGONAL) != 0) {
|
||||
System.out.println(c);
|
||||
toWall = true; // null with adjacent diagonal floor
|
||||
break;
|
||||
}
|
||||
|
||||
if ((floors & 0b11100000) == 0b11100000) toWall = true;
|
||||
if ((floors & 0b00111000) == 0b00111000) toWall = true;
|
||||
if ((floors & 0b00001110) == 0b00001110) toWall = true;
|
||||
if ((floors & 0b10000011) == 0b10000011) toWall = true;
|
||||
if (isDoor) {
|
||||
|
||||
if (countBits((byte) (floors & CARDINAL)) < 2) {
|
||||
toWall = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (countBits((byte) (walls & CARDINAL)) > 2) {
|
||||
toWall = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (countBits((byte) (floors & CARDINAL)) > 2) {
|
||||
toFloor = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((floors & 0b11100000) == 0b11100000) toWall = true;
|
||||
if ((floors & 0b00111000) == 0b00111000) toWall = true;
|
||||
if ((floors & 0b00001110) == 0b00001110) toWall = true;
|
||||
if ((floors & 0b10000011) == 0b10000011) toWall = true;
|
||||
|
||||
}
|
||||
} while (false);
|
||||
}
|
||||
|
||||
if (toWall) {
|
||||
set(c, theme.wall());
|
||||
} else if (toFloor) {
|
||||
set(c, theme.floor());
|
||||
} else if (toNull) {
|
||||
set(c, Tiles.NULL_EMPTY);
|
||||
|
||||
if (toNull) {
|
||||
out[c.y][c.x] = Tiles.NULL.createTile();
|
||||
} else if (toWall) {
|
||||
out[c.y][c.x] = theme.wall().createTile();
|
||||
} else if (toFloor) {
|
||||
out[c.y][c.x] = theme.floor().createTile();
|
||||
} else {
|
||||
out[c.y][c.x] = map[c.y][c.x];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
map = out;
|
||||
}
|
||||
|
||||
for (c.x = genMin.x, c1.x = 0; c.x <= genMax.x; c.x++, c1.x++) {
|
||||
for (c.y = genMin.y, c1.y = 0; c.y <= genMax.y; c.y++, c1.y++) {
|
||||
level.setTile(get(c), c1.x, c1.y);
|
||||
level.setTile(c1, get(c));
|
||||
}
|
||||
}
|
||||
|
||||
final WorldPos p = new WorldPos(enterPoint.x - genMin.x, enterPoint.y - genMin.y);
|
||||
level.setEnterPoint(p);
|
||||
final Coord entrance = new Coord(enterPoint.x - genMin.x, enterPoint.y - genMin.y);
|
||||
level.setEnterPoint(entrance);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,14 +15,11 @@ public class DeadEndRoom implements RoomBuilder {
|
||||
@Override
|
||||
public RoomDesc buildToFit(ScratchMap map, Theme theme, Random rand, Coord center)
|
||||
{
|
||||
final Coord min = new Coord(center.x - 1, center.y - 1);
|
||||
final Coord max = new Coord(center.x + 1, center.y + 1);
|
||||
|
||||
if (!map.isClear(min, max)) return null;
|
||||
if (!map.isClear(center, center)) return null;
|
||||
|
||||
map.fill(min, max, theme.floor());
|
||||
map.border(min, max, theme.wall());
|
||||
map.set(center, theme.floor());
|
||||
|
||||
return new RoomDesc(min, max);
|
||||
return new RoomDesc(center, center);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,29 +26,32 @@ public class SimpleRectRoom implements RoomBuilder {
|
||||
|
||||
map.fill(min, max, theme.floor());
|
||||
map.border(min, max, theme.wall());
|
||||
map.protect(min, max);
|
||||
|
||||
for (int i = 0; i < 2 + rand.nextInt(4); i++) {
|
||||
final Coord d = min.copy();
|
||||
for (int i = 0; i <= 2 + rand.nextInt(4); i++) {
|
||||
final Coord door = min.copy();
|
||||
switch (rand.nextInt(4)) {
|
||||
case 0:
|
||||
d.y = min.y;
|
||||
d.x += 1 + rand.nextInt((width - 1) * 2);
|
||||
door.y = min.y;
|
||||
door.x += 1 + rand.nextInt((width - 1) * 2);
|
||||
break;
|
||||
case 1:
|
||||
d.y = max.y;
|
||||
d.x += 1 + rand.nextInt((width - 1) * 2);
|
||||
door.y = max.y;
|
||||
door.x += 1 + rand.nextInt((width - 1) * 2);
|
||||
break;
|
||||
case 2:
|
||||
d.x = min.x;
|
||||
d.y += 1 + rand.nextInt((height - 1) * 2);
|
||||
door.x = min.x;
|
||||
door.y += 1 + rand.nextInt((height - 1) * 2);
|
||||
break;
|
||||
case 3:
|
||||
d.x = max.x;
|
||||
d.y += 1 + rand.nextInt((height - 1) * 2);
|
||||
door.x = max.x;
|
||||
door.y += 1 + rand.nextInt((height - 1) * 2);
|
||||
break;
|
||||
}
|
||||
|
||||
map.set(d, theme.door());
|
||||
if ((map.findDoors(door) & map.CARDINAL) == 0) {
|
||||
map.set(door, theme.door());
|
||||
}
|
||||
}
|
||||
|
||||
return new RoomDesc(min.add(-1, -1), max);
|
||||
|
||||
@@ -8,8 +8,8 @@ import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import mightypork.rogue.world.Coord;
|
||||
import mightypork.rogue.world.World;
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.rogue.world.tile.TileModel;
|
||||
@@ -18,6 +18,7 @@ import mightypork.util.files.ion.IonBinary;
|
||||
import mightypork.util.files.ion.IonBundle;
|
||||
import mightypork.util.files.ion.IonInput;
|
||||
import mightypork.util.files.ion.IonOutput;
|
||||
import mightypork.util.logging.Log;
|
||||
import mightypork.util.math.noise.NoiseGen;
|
||||
|
||||
|
||||
@@ -30,15 +31,16 @@ public class Level implements MapAccess, IonBinary {
|
||||
|
||||
public static final int ION_MARK = 53;
|
||||
|
||||
private int width, height;
|
||||
private final Coord size = Coord.zero();
|
||||
private World world;
|
||||
|
||||
private WorldPos enterPoint;
|
||||
private final Coord enterPoint = Coord.zero();
|
||||
|
||||
/** Array of tiles [y][x] */
|
||||
private Tile[][] tiles;
|
||||
|
||||
private final Map<Integer, Entity> entity_map = new HashMap<>();
|
||||
private final Set<Entity> entity_set = new HashSet<>();
|
||||
private final Map<Integer, Entity> entityMap = new HashMap<>();
|
||||
private final Set<Entity> entitySet = new HashSet<>();
|
||||
|
||||
/** Level seed (used for generation and tile variation) */
|
||||
public long seed;
|
||||
@@ -53,15 +55,14 @@ public class Level implements MapAccess, IonBinary {
|
||||
|
||||
public Level(int width, int height)
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
size.setTo(width, height);
|
||||
buildArray();
|
||||
}
|
||||
|
||||
|
||||
private void buildArray()
|
||||
{
|
||||
this.tiles = new Tile[height][width];
|
||||
this.tiles = new Tile[size.y][size.x];
|
||||
}
|
||||
|
||||
|
||||
@@ -73,54 +74,57 @@ public class Level implements MapAccess, IonBinary {
|
||||
|
||||
public void fill(TileModel model)
|
||||
{
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
tiles[y][x] = model.createTile();
|
||||
for (final Coord c = Coord.zero(); c.x < size.x; c.x++) {
|
||||
for (c.y = 0; c.y < size.y; c.y++) {
|
||||
setTile(c, model.createTile());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final Tile getTile(int x, int y)
|
||||
public final Tile getTile(Coord pos)
|
||||
{
|
||||
if (x < 0 || x >= width || y < 0 || y >= height) return Tiles.NULL_SOLID.createTile(); // out of range
|
||||
|
||||
return tiles[y][x];
|
||||
if (!pos.isInRange(0, 0, size.x - 1, size.y - 1)) return Tiles.NULL.createTile(); // out of range
|
||||
|
||||
return tiles[pos.y][pos.x];
|
||||
}
|
||||
|
||||
|
||||
public final void setTile(TileModel model, int x, int y)
|
||||
public final void setTile(Coord pos, TileModel model)
|
||||
{
|
||||
setTile(model.createTile(), x, y);
|
||||
setTile(pos, model.createTile());
|
||||
}
|
||||
|
||||
|
||||
public final void setTile(int tileId, int x, int y)
|
||||
public final void setTile(Coord pos, int tileId)
|
||||
{
|
||||
setTile(new Tile(tileId), x, y);
|
||||
setTile(pos, new Tile(tileId));
|
||||
}
|
||||
|
||||
|
||||
public final void setTile(Tile tile, int x, int y)
|
||||
public final void setTile(Coord pos, Tile tile)
|
||||
{
|
||||
if (x < 0 || x > width || y < 0 || y >= height) return; // out of range
|
||||
|
||||
tiles[y][x] = tile;
|
||||
if (!pos.isInRange(0, 0, size.x - 1, size.y - 1)) {
|
||||
Log.w("Invalid tile coord to set: " + pos + ", map size: " + size);
|
||||
return; // out of range
|
||||
}
|
||||
|
||||
tiles[pos.y][pos.x] = tile;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final int getWidth()
|
||||
{
|
||||
return width;
|
||||
return size.x;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final int getHeight()
|
||||
{
|
||||
return height;
|
||||
return size.y;
|
||||
}
|
||||
|
||||
|
||||
@@ -143,29 +147,31 @@ public class Level implements MapAccess, IonBinary {
|
||||
// metadata
|
||||
final IonBundle ib = in.readBundle();
|
||||
seed = ib.get("seed", 0L);
|
||||
width = ib.get("w", 0);
|
||||
height = ib.get("h", 0);
|
||||
ib.loadBundled("size", size);
|
||||
ib.loadBundled("enter_point", enterPoint);
|
||||
|
||||
ib.loadSequence("entities", entity_set);
|
||||
for (final Entity ent : entity_set) {
|
||||
entity_map.put(ent.getEID(), ent);
|
||||
ib.loadSequence("entities", entitySet);
|
||||
for (final Entity ent : entitySet) {
|
||||
ent.setLevel(this);
|
||||
entityMap.put(ent.getEntityId(), ent);
|
||||
}
|
||||
|
||||
// init array of size
|
||||
buildArray();
|
||||
|
||||
// load tiles
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (final Coord c = Coord.zero(); c.x < size.x; c.x++) {
|
||||
for (c.y = 0; c.y < size.y; c.y++) {
|
||||
// no mark
|
||||
tiles[y][x] = new Tile();
|
||||
tiles[y][x].load(in);
|
||||
final Tile tile = new Tile();
|
||||
tile.load(in);
|
||||
setTile(c, tile);
|
||||
}
|
||||
}
|
||||
|
||||
// mark tiles as occupied
|
||||
for (final Entity e : entity_set) {
|
||||
occupyTile(e.getPosition().x, e.getPosition().y);
|
||||
for (final Entity e : entitySet) {
|
||||
occupyTile(e.getPosition().getCoord());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,16 +182,17 @@ public class Level implements MapAccess, IonBinary {
|
||||
// metadata
|
||||
final IonBundle ib = new IonBundle();
|
||||
ib.put("seed", seed);
|
||||
ib.put("w", width);
|
||||
ib.put("h", height);
|
||||
ib.putSequence("entities", entity_set);
|
||||
ib.putBundled("size", size);
|
||||
ib.putBundled("enter_point", enterPoint);
|
||||
ib.putSequence("entities", entitySet);
|
||||
out.writeBundle(ib);
|
||||
|
||||
// tiles (writing this way to save space)
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
|
||||
for (final Coord c = Coord.zero(); c.x < size.x; c.x++) {
|
||||
for (c.y = 0; c.y < size.y; c.y++) {
|
||||
// no mark to save space
|
||||
tiles[y][x].save(out);
|
||||
getTile(c).save(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -198,17 +205,17 @@ public class Level implements MapAccess, IonBinary {
|
||||
}
|
||||
|
||||
|
||||
public void update(World w, double delta)
|
||||
public void update(double delta)
|
||||
{
|
||||
// just update them all
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
getTile(x, y).update(this, delta);
|
||||
for (final Coord c = Coord.zero(); c.x < size.x; c.x++) {
|
||||
for (c.y = 0; c.y < size.y; c.y++) {
|
||||
getTile(c).update(this, delta);
|
||||
}
|
||||
}
|
||||
|
||||
for (final Entity e : entity_set) {
|
||||
e.update(w, this, delta);
|
||||
for (final Entity e : entitySet) {
|
||||
e.update(delta);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,34 +233,42 @@ public class Level implements MapAccess, IonBinary {
|
||||
|
||||
public Entity getEntity(int eid)
|
||||
{
|
||||
return entity_map.get(eid);
|
||||
return entityMap.get(eid);
|
||||
}
|
||||
|
||||
|
||||
public void addEntity(Entity entity)
|
||||
{
|
||||
entity_map.put(entity.getEID(), entity);
|
||||
entity_set.add(entity);
|
||||
if (entityMap.containsKey(entity.getEntityId())) {
|
||||
Log.w("Entity already in level.");
|
||||
return;
|
||||
}
|
||||
|
||||
entityMap.put(entity.getEntityId(), entity);
|
||||
entitySet.add(entity);
|
||||
|
||||
// join to level & world
|
||||
entity.setLevel(this);
|
||||
}
|
||||
|
||||
|
||||
public void removeEntity(Entity entity)
|
||||
{
|
||||
entity_map.remove(entity.getEID());
|
||||
entity_set.remove(entity);
|
||||
entityMap.remove(entity.getEntityId());
|
||||
entitySet.remove(entity);
|
||||
}
|
||||
|
||||
|
||||
public void removeEntity(int eid)
|
||||
{
|
||||
final Entity removed = entity_map.remove(eid);
|
||||
entity_set.remove(removed);
|
||||
final Entity removed = entityMap.remove(eid);
|
||||
entitySet.remove(removed);
|
||||
}
|
||||
|
||||
|
||||
public boolean canWalkInto(int x, int y)
|
||||
public boolean canWalkInto(Coord pos)
|
||||
{
|
||||
final Tile t = getTile(x, y);
|
||||
final Tile t = getTile(pos);
|
||||
|
||||
return t.isWalkable() && !t.isOccupied();
|
||||
}
|
||||
@@ -262,35 +277,47 @@ public class Level implements MapAccess, IonBinary {
|
||||
/**
|
||||
* Mark tile as occupied by an entity
|
||||
*/
|
||||
public void occupyTile(int x, int y)
|
||||
public void occupyTile(Coord pos)
|
||||
{
|
||||
getTile(x, y).setOccupied(true);
|
||||
getTile(pos).setOccupied(true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mark tile as free (no longet occupied)
|
||||
*/
|
||||
public void freeTile(int x, int y)
|
||||
public void freeTile(Coord pos)
|
||||
{
|
||||
getTile(x, y).setOccupied(false);
|
||||
getTile(pos).setOccupied(false);
|
||||
}
|
||||
|
||||
|
||||
public Collection<Entity> getEntities()
|
||||
{
|
||||
return entity_set;
|
||||
return entitySet;
|
||||
}
|
||||
|
||||
|
||||
public void setEnterPoint(WorldPos enterPoint)
|
||||
public void setEnterPoint(Coord pos)
|
||||
{
|
||||
this.enterPoint = enterPoint;
|
||||
this.enterPoint.setTo(pos);
|
||||
}
|
||||
|
||||
|
||||
public WorldPos getEnterPoint()
|
||||
public Coord getEnterPoint()
|
||||
{
|
||||
return enterPoint;
|
||||
}
|
||||
|
||||
|
||||
public World getWorld()
|
||||
{
|
||||
return world;
|
||||
}
|
||||
|
||||
|
||||
public void setWorld(World world)
|
||||
{
|
||||
this.world = world;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package mightypork.rogue.world.level;
|
||||
|
||||
|
||||
import mightypork.rogue.world.Coord;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.util.math.noise.NoiseGen;
|
||||
|
||||
@@ -15,11 +16,10 @@ public interface MapAccess {
|
||||
/**
|
||||
* Ge tile at X,Y
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @param pos
|
||||
* @return tile
|
||||
*/
|
||||
Tile getTile(int x, int y);
|
||||
Tile getTile(Coord pos);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package mightypork.rogue.world.level.render;
|
||||
|
||||
|
||||
import mightypork.rogue.world.Coord;
|
||||
import mightypork.rogue.world.level.MapAccess;
|
||||
import mightypork.util.math.constraints.rect.Rect;
|
||||
import mightypork.util.math.constraints.rect.builders.TiledRect;
|
||||
@@ -22,9 +23,9 @@ public abstract class MapRenderContext {
|
||||
}
|
||||
|
||||
|
||||
public Rect getRectForTile(int x, int y)
|
||||
public Rect getRectForTile(Coord pos)
|
||||
{
|
||||
return tiler.tile(x, y);
|
||||
return tiler.tile(pos.x, pos.y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package mightypork.rogue.world.level.render;
|
||||
|
||||
|
||||
import mightypork.rogue.world.Coord;
|
||||
import mightypork.rogue.world.level.MapAccess;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.util.math.constraints.rect.Rect;
|
||||
@@ -15,8 +16,7 @@ import mightypork.util.math.noise.NoiseGen;
|
||||
*/
|
||||
public final class TileRenderContext extends MapRenderContext implements RectBound {
|
||||
|
||||
public int x;
|
||||
public int y;
|
||||
public final Coord pos = Coord.zero();
|
||||
private final NoiseGen noise;
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ public final class TileRenderContext extends MapRenderContext implements RectBou
|
||||
*/
|
||||
public Tile getTile()
|
||||
{
|
||||
return map.getTile(x, y);
|
||||
return map.getTile(pos);
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ public final class TileRenderContext extends MapRenderContext implements RectBou
|
||||
*/
|
||||
public Tile getAdjacentTile(int offsetX, int offsetY)
|
||||
{
|
||||
return map.getTile(x + offsetX, y + offsetY);
|
||||
return map.getTile(pos.add(offsetX, offsetY));
|
||||
}
|
||||
|
||||
|
||||
@@ -57,19 +57,19 @@ public final class TileRenderContext extends MapRenderContext implements RectBou
|
||||
*/
|
||||
public double getTileNoise()
|
||||
{
|
||||
return noise.valueAt(x, y);
|
||||
return noise.valueAt(pos.x, pos.y);
|
||||
}
|
||||
|
||||
|
||||
public void renderTile()
|
||||
{
|
||||
map.getTile(x, y).renderTile(this);
|
||||
map.getTile(pos).renderTile(this);
|
||||
}
|
||||
|
||||
|
||||
public void renderItems()
|
||||
{
|
||||
map.getTile(x, y).renderItems(this);
|
||||
map.getTile(pos).renderItems(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -79,6 +79,6 @@ public final class TileRenderContext extends MapRenderContext implements RectBou
|
||||
@Override
|
||||
public Rect getRect()
|
||||
{
|
||||
return getRectForTile(x, y);
|
||||
return getRectForTile(pos);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,28 +19,19 @@ import mightypork.rogue.world.PathStep;
|
||||
public class PathFinder {
|
||||
|
||||
private static final FComparator F_COMPARATOR = new FComparator();
|
||||
|
||||
public static final Heuristic CORNER_HEURISTIC = new ManhattanHeuristic();
|
||||
public static final Heuristic DIAGONAL_HEURISTIC = new DiagonalHeuristic();
|
||||
|
||||
private final PathCostProvider costProvider;
|
||||
private final Heuristic heuristic;
|
||||
|
||||
|
||||
public PathFinder(PathCostProvider costProvider, Heuristic heuristic)
|
||||
public static List<PathStep> findPathRelative(PathFindingContext context, Coord start, Coord end)
|
||||
{
|
||||
this.costProvider = costProvider;
|
||||
this.heuristic = heuristic;
|
||||
}
|
||||
|
||||
|
||||
public List<PathStep> findPathRelative(Coord start, Coord end)
|
||||
{
|
||||
final List<Coord> path = findPath(start, end);
|
||||
final List<Coord> path = findPath(context, start, end);
|
||||
if (path == null) return null;
|
||||
|
||||
final List<PathStep> out = new ArrayList<>();
|
||||
|
||||
final Coord current = start;
|
||||
final Coord current = start.copy();
|
||||
for (final Coord c : path) {
|
||||
if (c.equals(current)) continue;
|
||||
out.add(PathStep.make(c.x - current.x, c.y - current.y));
|
||||
@@ -52,15 +43,17 @@ public class PathFinder {
|
||||
}
|
||||
|
||||
|
||||
public List<Coord> findPath(Coord start, Coord end)
|
||||
public static List<Coord> findPath(PathFindingContext context, Coord start, Coord end)
|
||||
{
|
||||
final LinkedList<Node> open = new LinkedList<>();
|
||||
final LinkedList<Node> closed = new LinkedList<>();
|
||||
|
||||
final Heuristic heuristic = context.getHeuristic();
|
||||
|
||||
// add first node
|
||||
{
|
||||
final Node n = new Node(start);
|
||||
n.h_cost = (int) (heuristic.getCost(start, end) * costProvider.getMinCost());
|
||||
n.h_cost = (int) (heuristic.getCost(start, end) * context.getMinCost());
|
||||
n.g_cost = 0;
|
||||
open.add(n);
|
||||
}
|
||||
@@ -92,13 +85,13 @@ public class PathFinder {
|
||||
for (final Coord go : walkDirs) {
|
||||
|
||||
final Coord c = current.pos.add(go);
|
||||
if (!costProvider.isAccessible(c)) continue;
|
||||
if (!context.isAccessible(c)) continue;
|
||||
final Node a = new Node(c);
|
||||
a.g_cost = current.g_cost + costProvider.getCost(c, a.pos);
|
||||
a.h_cost = (int) (heuristic.getCost(a.pos, end) * costProvider.getMinCost());
|
||||
a.g_cost = current.g_cost + context.getCost(c, a.pos);
|
||||
a.h_cost = (int) (heuristic.getCost(a.pos, end) * context.getMinCost());
|
||||
a.parent = current;
|
||||
|
||||
if (costProvider.isAccessible(a.pos)) {
|
||||
if (context.isAccessible(a.pos)) {
|
||||
if (!closed.contains(a)) {
|
||||
|
||||
if (open.contains(a)) {
|
||||
@@ -128,8 +121,7 @@ public class PathFinder {
|
||||
|
||||
}
|
||||
|
||||
if (current == null) {
|
||||
return null; // no path found
|
||||
if (current == null) { return null; // no path found
|
||||
}
|
||||
|
||||
final LinkedList<Coord> path = new LinkedList<>();
|
||||
|
||||
+7
-1
@@ -4,7 +4,7 @@ package mightypork.rogue.world.pathfinding;
|
||||
import mightypork.rogue.world.Coord;
|
||||
|
||||
|
||||
public interface PathCostProvider {
|
||||
public interface PathFindingContext {
|
||||
|
||||
/**
|
||||
* @param pos tile pos
|
||||
@@ -27,4 +27,10 @@ public interface PathCostProvider {
|
||||
* @return lowest cost. Used to multiply heuristics.
|
||||
*/
|
||||
int getMinCost();
|
||||
|
||||
|
||||
/**
|
||||
* @return used heuristic
|
||||
*/
|
||||
Heuristic getHeuristic();
|
||||
}
|
||||
@@ -33,6 +33,7 @@ public final class Tile implements IonBinary {
|
||||
public final IonBundle metadata = new IonBundle();
|
||||
|
||||
public final TileRenderData renderData = new TileRenderData();
|
||||
public final TileGenData genData = new TileGenData();
|
||||
|
||||
// temporary flag for map.
|
||||
private boolean occupied;
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package mightypork.rogue.world.tile;
|
||||
|
||||
|
||||
/**
|
||||
* Data storage for world generator
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class TileGenData {
|
||||
|
||||
public boolean isProtected = false;
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package mightypork.rogue.world.tile;
|
||||
|
||||
|
||||
/**
|
||||
* Data storage for renderer / entity.
|
||||
* Data storage for tile renderer
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
|
||||
@@ -2,8 +2,7 @@ package mightypork.rogue.world.tile;
|
||||
|
||||
|
||||
import mightypork.rogue.world.tile.models.Floor;
|
||||
import mightypork.rogue.world.tile.models.NullFloor;
|
||||
import mightypork.rogue.world.tile.models.NullWall;
|
||||
import mightypork.rogue.world.tile.models.NullTile;
|
||||
import mightypork.rogue.world.tile.models.SimpleDoor;
|
||||
import mightypork.rogue.world.tile.models.Wall;
|
||||
import mightypork.rogue.world.tile.renderers.FloorRenderer;
|
||||
@@ -19,8 +18,7 @@ public final class Tiles {
|
||||
|
||||
private static final TileModel[] tiles = new TileModel[256];
|
||||
|
||||
public static final TileModel NULL_SOLID = new NullWall(0);
|
||||
public static final TileModel NULL_EMPTY = new NullFloor(1);
|
||||
public static final TileModel NULL = new NullTile(0);
|
||||
|
||||
public static final TileModel FLOOR_DARK = new Floor(10).setRenderer(new FloorRenderer("tile.floor.dark"));
|
||||
public static final TileModel WALL_BRICK = new Wall(11).setRenderer(new WallRenderer("tile.wall.brick"));
|
||||
@@ -45,13 +43,9 @@ public final class Tiles {
|
||||
|
||||
public static void register(int id, TileModel model)
|
||||
{
|
||||
if (id < 0 || id >= tiles.length) {
|
||||
throw new IllegalArgumentException("Tile ID " + id + " is out of range.");
|
||||
}
|
||||
if (id < 0 || id >= tiles.length) { throw new IllegalArgumentException("Tile ID " + id + " is out of range."); }
|
||||
|
||||
if (tiles[id] != null) {
|
||||
throw new IllegalArgumentException("Tile ID " + id + " already in use.");
|
||||
}
|
||||
if (tiles[id] != null) { throw new IllegalArgumentException("Tile ID " + id + " already in use."); }
|
||||
|
||||
tiles[id] = model;
|
||||
}
|
||||
@@ -61,9 +55,7 @@ public final class Tiles {
|
||||
{
|
||||
final TileModel m = tiles[id];
|
||||
|
||||
if (m == null) {
|
||||
throw new IllegalArgumentException("No tile with ID " + id + ".");
|
||||
}
|
||||
if (m == null) { throw new IllegalArgumentException("No tile with ID " + id + "."); }
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
package mightypork.rogue.world.tile.models;
|
||||
|
||||
|
||||
public class NullFloor extends AbstractNullTile {
|
||||
|
||||
public NullFloor(int id)
|
||||
{
|
||||
super(id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isFloor()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isPotentiallyWalkable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
+2
-8
@@ -1,9 +1,9 @@
|
||||
package mightypork.rogue.world.tile.models;
|
||||
|
||||
|
||||
public class NullWall extends AbstractNullTile {
|
||||
public class NullTile extends AbstractNullTile {
|
||||
|
||||
public NullWall(int id)
|
||||
public NullTile(int id)
|
||||
{
|
||||
super(id);
|
||||
}
|
||||
@@ -15,10 +15,4 @@ public class NullWall extends AbstractNullTile {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isWall()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user