diff --git a/.gitignore b/.gitignore index eb5a316..0f9d898 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ target +out diff --git a/src/main/java/xyz/valnet/engine/math/Vector2i.java b/src/main/java/xyz/valnet/engine/math/Vector2i.java index a99ee79..a498dba 100644 --- a/src/main/java/xyz/valnet/engine/math/Vector2i.java +++ b/src/main/java/xyz/valnet/engine/math/Vector2i.java @@ -14,4 +14,17 @@ public class Vector2i { this.y = y; } + public boolean equals(Vector2i other) { + return x == other.x && y == other.y; + } + + public boolean isOneOf(Vector2i[] others) { + for(Vector2i other : others) { + if(other.equals(this)) { + return true; + } + } + return false; + } + } diff --git a/src/main/java/xyz/valnet/engine/scenegraph/GameObject.java b/src/main/java/xyz/valnet/engine/scenegraph/GameObject.java index 465fdcd..682685c 100644 --- a/src/main/java/xyz/valnet/engine/scenegraph/GameObject.java +++ b/src/main/java/xyz/valnet/engine/scenegraph/GameObject.java @@ -11,6 +11,10 @@ public class GameObject implements IRenderable, ITickable { this.scene = scene; } + public boolean inScene() { + return scene.inScene(this); + } + protected T get(Class clazz) { return this.scene.get(clazz); } @@ -30,4 +34,8 @@ public class GameObject implements IRenderable, ITickable { public void tick(float dTime) {} public void start() {} + + public void remove(GameObject obj) { + scene.remove(obj); + } } diff --git a/src/main/java/xyz/valnet/hadean/Tile.java b/src/main/java/xyz/valnet/hadean/Tile.java index 3f12511..ef70ae6 100644 --- a/src/main/java/xyz/valnet/hadean/Tile.java +++ b/src/main/java/xyz/valnet/hadean/Tile.java @@ -22,6 +22,7 @@ public class Tile extends GameObject { private final Sprite sprite = Assets.defaultTerrain[(int)Math.floor(Math.random() * Assets.defaultTerrain.length)]; private List stuff = new ArrayList(); + private List toRemove = new ArrayList(); public Tile(int x, int y) { this.x = x; @@ -38,6 +39,23 @@ public class Tile extends GameObject { } } + @Override + public void tick(float dTime) { + for(ITileThing thing : stuff) { + if(thing.shouldRemove()) { + toRemove.add(thing); + } + } + for(ITileThing thing : toRemove) { + stuff.remove(thing); + thing.onRemove(); + if(thing instanceof GameObject) { + remove((GameObject)thing); + } + } + toRemove.clear(); + } + @Override public void render() { Drawing.setLayer(2f); diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/ISelectable.java b/src/main/java/xyz/valnet/hadean/gameobjects/ISelectable.java index be035cc..6b2ecf2 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/ISelectable.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/ISelectable.java @@ -7,4 +7,5 @@ public interface ISelectable { public Vector4f getWorldBox(); public Action[] getActions(); public void runAction(Action action); + public String details(); } \ No newline at end of file diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/ITileThing.java b/src/main/java/xyz/valnet/hadean/gameobjects/ITileThing.java index 1dafb8c..c70ea96 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/ITileThing.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/ITileThing.java @@ -2,4 +2,6 @@ package xyz.valnet.hadean.gameobjects; public interface ITileThing { public boolean isWalkable(); + public boolean shouldRemove(); + public void onRemove(); } diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/IWorkable.java b/src/main/java/xyz/valnet/hadean/gameobjects/IWorkable.java new file mode 100644 index 0000000..09d16b8 --- /dev/null +++ b/src/main/java/xyz/valnet/hadean/gameobjects/IWorkable.java @@ -0,0 +1,9 @@ +package xyz.valnet.hadean.gameobjects; + +import xyz.valnet.engine.math.Vector2i; + +public interface IWorkable { + public boolean hasWork(); + public Vector2i[] getWorablePositions(); + public void doWork(); +} diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/Log.java b/src/main/java/xyz/valnet/hadean/gameobjects/Log.java new file mode 100644 index 0000000..d4f94d0 --- /dev/null +++ b/src/main/java/xyz/valnet/hadean/gameobjects/Log.java @@ -0,0 +1,60 @@ +package xyz.valnet.hadean.gameobjects; + +import xyz.valnet.engine.math.Vector4f; +import xyz.valnet.engine.scenegraph.GameObject; +import xyz.valnet.hadean.util.Action; +import xyz.valnet.hadean.util.Assets; + +public class Log extends GameObject implements ITileThing, ISelectable { + + private Camera camera; + + private int x, y; + + public Log(int x, int y) { + this.x = x; + this.y = y; + } + + @Override + public void start() { + camera = get(Camera.class); + } + + @Override + public void render() { + camera.draw(Assets.log, x, y); + } + + @Override + public boolean isWalkable() { + return true; + } + + @Override + public boolean shouldRemove() { + return false; + } + + @Override + public void onRemove() {} + + @Override + public Vector4f getWorldBox() { + return new Vector4f(x, y, x + 1, y + 1); + } + + @Override + public Action[] getActions() { + return new Action[] {}; + } + + @Override + public void runAction(Action action) {} + + @Override + public String details() { + return "A fat log"; + } + +} diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/Pawn.java b/src/main/java/xyz/valnet/hadean/gameobjects/Pawn.java index 2c5e582..4a4e106 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/Pawn.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/Pawn.java @@ -7,8 +7,11 @@ import static org.lwjgl.opengl.GL11.glVertex3f; import static org.lwjgl.opengl.GL20.glVertexAttrib2f; import static xyz.valnet.engine.util.Math.lerp; +import java.util.List; + import xyz.valnet.engine.graphics.Drawing; import xyz.valnet.engine.math.Vector2f; +import xyz.valnet.engine.math.Vector2i; import xyz.valnet.engine.math.Vector4f; import xyz.valnet.engine.scenegraph.GameObject; import xyz.valnet.engine.shaders.SimpleShader; @@ -23,7 +26,6 @@ import xyz.valnet.hadean.util.Assets; public class Pawn extends GameObject implements ISelectable { private float x = 0.5f, y = 0.5f; - private float dx, dy; private float counter = 0; @@ -86,26 +88,68 @@ public class Pawn extends GameObject implements ISelectable { @Override public void tick(float dTime) { - if(path != null && !path.isComplete()) move(); - else newPath(); + // firstly, TRY PATHING. + if(path != null && !path.isComplete()) { + move(); + return; + } + + // then, try to do work! + if(currentJob != null && currentJob.hasWork()) { + if(getCurrentPos().isOneOf(currentJob.getWorablePositions())) { + currentJob.doWork(); + return; + } + } + + + // then try to get work?! + currentJob = null; + tryStartWork(); + + // then wander... + } - private void newPath() { - // set new destination - dx = 0.5f + (float)Math.floor(Math.random() * Terrain.WORLD_SIZE); - dy = 0.5f + (float)Math.floor(Math.random() * Terrain.WORLD_SIZE); - - // and route there. - route(); + private Vector2i getCurrentPos() { + return new Vector2i((int)Math.floor(x), (int)Math.floor(y)); } - private void route() { + private IWorkable currentJob; + + private void tryStartWork() { + List workables = getAll(IWorkable.class); + if(workables.size() > 0) { + for(IWorkable job : workables) { + if(!job.hasWork()) continue; + Vector2i[] workablePositions = job.getWorablePositions(); + Path bestPathToJob = pathfinder.getBestPath( + new Vector2i((int)Math.floor(x), (int)Math.floor(y)), + workablePositions + ); + if(bestPathToJob == null) continue; + this.path = bestPathToJob; + currentJob = job; + } + } + } + + // private void newPath() { + // // set new destination + // dx = 0.5f + (float)Math.floor(Math.random() * Terrain.WORLD_SIZE); + // dy = 0.5f + (float)Math.floor(Math.random() * Terrain.WORLD_SIZE); + + // // and route there. + // route(); + // } + + private void reroute() { // intify all the coordinates int ix = (int)Math.floor(x); int iy = (int)Math.floor(y); - int idx = (int)Math.floor(dx); - int idy = (int)Math.floor(dy); + int idx = path.dst.x; + int idy = path.dst.y; // try to make a new path. path = pathfinder.getPath(ix, iy, idx, idy); @@ -126,7 +170,7 @@ public class Pawn extends GameObject implements ISelectable { if(counter > 0) counter --; if(counter < 0) counter = 0; if(counter == 0) { - route(); + reroute(); } return; } @@ -160,7 +204,7 @@ public class Pawn extends GameObject implements ISelectable { @Override public Action[] getActions() { return new Action[] { - ACTION_REROUTE, + // ACTION_REROUTE, ACTION_TOGGLE_DEBUG, ACTION_PAUSE }; @@ -171,10 +215,15 @@ public class Pawn extends GameObject implements ISelectable { if(action == ACTION_PAUSE) { paused = !paused; } else if(action == ACTION_REROUTE) { - newPath(); + reroute(); } else if(action == ACTION_TOGGLE_DEBUG) { debug = !debug; } } + + @Override + public String details() { + return "IM A PAWNNNNN!!!!"; + } } diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/Selection.java b/src/main/java/xyz/valnet/hadean/gameobjects/Selection.java index a900592..0dbedc8 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/Selection.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/Selection.java @@ -34,6 +34,8 @@ public class Selection extends GameObject { // return (float) Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2)); // } + private List toRemove = new ArrayList(); + @Override public void tick(float dTime) { if(animation < animationMax) animation ++; @@ -58,6 +60,18 @@ public class Selection extends GameObject { initialCoords = null; } } + + for(ISelectable selectable : selected) { + if(selectable instanceof GameObject) { + if(!((GameObject)selectable).inScene()) { + toRemove.add(selectable); + } + } + } + for(ISelectable removeMe : toRemove) { + selected.remove(removeMe); + } + toRemove.clear(); } @Override diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/SelectionUI.java b/src/main/java/xyz/valnet/hadean/gameobjects/SelectionUI.java index a933f52..efbb684 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/SelectionUI.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/SelectionUI.java @@ -54,6 +54,11 @@ public class SelectionUI extends GameObject implements ISelectionChangeListener, if(selectedTypes.size() == 1) { Assets.font.drawString("" + count + "x " + name, 26, 376); + + if(count == 1) { + String details = selected.get(0).details(); + Assets.font.drawString(details, 26, 376 + 32); + } for(Button btn : actionButtons) { btn.draw(); diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/Terrain.java b/src/main/java/xyz/valnet/hadean/gameobjects/Terrain.java index 5872949..27ca4d1 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/Terrain.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/Terrain.java @@ -34,26 +34,15 @@ public class Terrain extends GameObject implements IPathable { return tiles[x][y]; } - @Override - public void render() { - // left = 400 - (WORLD_SIZE * TILE_SIZE / 2); - // top = 225 - (WORLD_SIZE * TILE_SIZE / 2); - - // Drawing.setLayer(0f); - // for (int i = 0; i < WORLD_SIZE; i++) { - // for (int j = 0; j < WORLD_SIZE; j++) { - // tiles[i][j].render(camera); - // } - // } - } - @Override public boolean isWalkable(int x, int y, int fromX, int fromY) { - return getTile(x, y).isWalkable(); + if(!isOutOfBounds(x, y)) { + return getTile(x, y).isWalkable(); + } else return false; } @Override - public boolean isInBounds(int x, int y) { + public boolean isOutOfBounds(int x, int y) { return x < 0 || y < 0 || x >= WORLD_SIZE || y >= WORLD_SIZE; } diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/Tree.java b/src/main/java/xyz/valnet/hadean/gameobjects/Tree.java index c94401d..9176e62 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/Tree.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/Tree.java @@ -1,13 +1,17 @@ package xyz.valnet.hadean.gameobjects; +import xyz.valnet.engine.math.Vector2i; import xyz.valnet.engine.math.Vector4f; import xyz.valnet.engine.scenegraph.GameObject; import xyz.valnet.hadean.util.Action; import xyz.valnet.hadean.util.Assets; -public class Tree extends GameObject implements ITileThing, ISelectable { +public class Tree extends GameObject implements ITileThing, ISelectable, IWorkable { private Camera camera; + private Terrain terrain; + private boolean chopFlag = false; + private int x, y; public Tree(int x, int y) { @@ -17,11 +21,14 @@ public class Tree extends GameObject implements ITileThing, ISelectable { public void start() { camera = get(Camera.class); + terrain = get(Terrain.class); } @Override public void render() { + Assets.flat.pushColor(new Vector4f(1 - getProgress(), 1 - getProgress(), 1 - getProgress(), 1.0f)); camera.draw(Assets.tree, x - 1, y - 2, 3, 3); + Assets.flat.popColor(); } @Override @@ -45,7 +52,64 @@ public class Tree extends GameObject implements ITileThing, ISelectable { @Override public void runAction(Action action) { - // TODO Auto-generated method stub + if(action == ACTION_CHOP) { + chopFlag = !chopFlag; + } + } + + @Override + public boolean hasWork() { + return chopFlag && choppage < strength; + } + + @Override + public Vector2i[] getWorablePositions() { + return new Vector2i[] { + new Vector2i(x, y - 1), + new Vector2i(x, y + 1), + new Vector2i(x - 1, y), + new Vector2i(x + 1, y) + }; + } + + protected float choppage = 0; + protected int strength = 500; + + private float getProgress() { + return (choppage / (float) strength); + } + + @Override + public void doWork() { + choppage ++; + } + + @Override + public String details() { + return "Chop Flag | " + chopFlag + "\n" + + "Progress | " + (String.format("%.2f", getProgress() * 100)) + "%"; + } + + @Override + public void tick(float dTime) { + if(choppage >= strength) { + return; + } + if(choppage > 0) { + choppage -= 0.01f; + } else { + choppage = 0; + } } + + @Override + public boolean shouldRemove() { + return getProgress() >= 1.0; + } + + @Override + public void onRemove() { + add(new Log(x, y)); + } } diff --git a/src/main/java/xyz/valnet/hadean/pathfinding/AStarPathfinder.java b/src/main/java/xyz/valnet/hadean/pathfinding/AStarPathfinder.java index 6243377..57abcf0 100644 --- a/src/main/java/xyz/valnet/hadean/pathfinding/AStarPathfinder.java +++ b/src/main/java/xyz/valnet/hadean/pathfinding/AStarPathfinder.java @@ -24,7 +24,7 @@ public class AStarPathfinder implements IPathfinder { private Node getPathfindingNode(int x, int y, List open, List closed, Node parent, int dstX, int dstY) { // TODO this isnt necessarily the BOUNDS so... think about that. - if(pathable.isInBounds(x, y)) { + if(pathable.isOutOfBounds(x, y)) { return null; } @@ -107,7 +107,7 @@ public class AStarPathfinder implements IPathfinder { path.pop(); - return new Path(path, current.getCost()); + return new Path(path, current); } Node[] neighbors = getNeighbors(current, open, closed, x2, y2); @@ -149,6 +149,7 @@ public class AStarPathfinder implements IPathfinder { Path bestPath = null; for(Vector2i dst : dsts) { Path path = getPath(src.x, src.y, dst.x, dst.y); + if(path == null) continue; if(path.cost < cost) { cost = path.cost; bestPath = path; diff --git a/src/main/java/xyz/valnet/hadean/pathfinding/IPathable.java b/src/main/java/xyz/valnet/hadean/pathfinding/IPathable.java index a6a6039..9f93e9f 100644 --- a/src/main/java/xyz/valnet/hadean/pathfinding/IPathable.java +++ b/src/main/java/xyz/valnet/hadean/pathfinding/IPathable.java @@ -2,5 +2,5 @@ package xyz.valnet.hadean.pathfinding; public interface IPathable { public boolean isWalkable(int x, int y, int fromX, int fromY); - public boolean isInBounds(int x, int y); + public boolean isOutOfBounds(int x, int y); } diff --git a/src/main/java/xyz/valnet/hadean/pathfinding/Path.java b/src/main/java/xyz/valnet/hadean/pathfinding/Path.java index f981f0a..683f666 100644 --- a/src/main/java/xyz/valnet/hadean/pathfinding/Path.java +++ b/src/main/java/xyz/valnet/hadean/pathfinding/Path.java @@ -6,10 +6,12 @@ import java.util.Stack; public class Path implements Iterable { private Stack nodes; public final int cost; + public final Node dst; - public Path(Stack nodes, int cost) { + public Path(Stack nodes, Node dst) { this.nodes = nodes; - this.cost = cost; + this.cost = dst.getCost(); + this.dst = dst; } public Node peek() { diff --git a/src/main/java/xyz/valnet/hadean/scenes/GameScene.java b/src/main/java/xyz/valnet/hadean/scenes/GameScene.java index ad47bb8..0afbdf5 100644 --- a/src/main/java/xyz/valnet/hadean/scenes/GameScene.java +++ b/src/main/java/xyz/valnet/hadean/scenes/GameScene.java @@ -16,6 +16,7 @@ public class GameScene implements IScene { // generic private List objects = new ArrayList(); private List newObjects = new ArrayList(); + private List removeObjects = new ArrayList(); // private List renderables = new ArrayList(); // specific @@ -62,6 +63,13 @@ public class GameScene implements IScene { } } + if(!removeObjects.isEmpty()) { + for(GameObject obj : removeObjects) { + objects.remove(obj); + } + removeObjects.clear(); + } + for(GameObject obj : objects) { obj.tick(dTime); } @@ -70,7 +78,7 @@ public class GameScene implements IScene { @Override public void enable() { objects.add(new Terrain()); - for(int i = 0; i < 3; i ++) { + for(int i = 0; i < 1; i ++) { objects.add(new Pawn()); } objects.add(new Camera()); @@ -95,5 +103,13 @@ public class GameScene implements IScene { newObjects.add(obj); obj.link(this); } + + public void remove(GameObject obj) { + removeObjects.add(obj); + } + + public boolean inScene(GameObject gameObject) { + return objects.contains(gameObject); + } } diff --git a/src/main/java/xyz/valnet/hadean/util/Assets.java b/src/main/java/xyz/valnet/hadean/util/Assets.java index 14be143..0655d26 100644 --- a/src/main/java/xyz/valnet/hadean/util/Assets.java +++ b/src/main/java/xyz/valnet/hadean/util/Assets.java @@ -23,11 +23,11 @@ public class Assets { public static final Tile9 uiFrameLight; public static final Tile9 uiFrameDark; - public static final Sprite[] defaultTerrain; public static final Sprite pawn; public static final Sprite tree; public static final Sprite rocks; + public static final Sprite log; public static final SimpleShader flat; @@ -46,6 +46,7 @@ public class Assets { pawn = new Sprite(atlas, 48, 88, 8, 8); tree = new Sprite(atlas, 64, 64, 24, 24); rocks = new Sprite(atlas, 64, 104, 8, 8); + log = new Sprite(atlas, 48, 96, 16, 16); Map charset = new HashMap();