slxn details, logs, jobs, pathfinding hogs.

pull/1/head
Valerie 2022-05-21 08:57:05 -04:00
parent ce80c4945d
commit 7fa2648a9a
18 changed files with 293 additions and 40 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
target target
out

View File

@ -14,4 +14,17 @@ public class Vector2i {
this.y = y; 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;
}
} }

View File

@ -11,6 +11,10 @@ public class GameObject implements IRenderable, ITickable {
this.scene = scene; this.scene = scene;
} }
public boolean inScene() {
return scene.inScene(this);
}
protected <T> T get(Class<T> clazz) { protected <T> T get(Class<T> clazz) {
return this.scene.get(clazz); return this.scene.get(clazz);
} }
@ -30,4 +34,8 @@ public class GameObject implements IRenderable, ITickable {
public void tick(float dTime) {} public void tick(float dTime) {}
public void start() {} public void start() {}
public void remove(GameObject obj) {
scene.remove(obj);
}
} }

View File

@ -22,6 +22,7 @@ public class Tile extends GameObject {
private final Sprite sprite = Assets.defaultTerrain[(int)Math.floor(Math.random() * Assets.defaultTerrain.length)]; private final Sprite sprite = Assets.defaultTerrain[(int)Math.floor(Math.random() * Assets.defaultTerrain.length)];
private List<ITileThing> stuff = new ArrayList<ITileThing>(); private List<ITileThing> stuff = new ArrayList<ITileThing>();
private List<ITileThing> toRemove = new ArrayList<ITileThing>();
public Tile(int x, int y) { public Tile(int x, int y) {
this.x = x; 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 @Override
public void render() { public void render() {
Drawing.setLayer(2f); Drawing.setLayer(2f);

View File

@ -7,4 +7,5 @@ public interface ISelectable {
public Vector4f getWorldBox(); public Vector4f getWorldBox();
public Action[] getActions(); public Action[] getActions();
public void runAction(Action action); public void runAction(Action action);
public String details();
} }

View File

@ -2,4 +2,6 @@ package xyz.valnet.hadean.gameobjects;
public interface ITileThing { public interface ITileThing {
public boolean isWalkable(); public boolean isWalkable();
public boolean shouldRemove();
public void onRemove();
} }

View File

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

View File

@ -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";
}
}

View File

@ -7,8 +7,11 @@ import static org.lwjgl.opengl.GL11.glVertex3f;
import static org.lwjgl.opengl.GL20.glVertexAttrib2f; import static org.lwjgl.opengl.GL20.glVertexAttrib2f;
import static xyz.valnet.engine.util.Math.lerp; import static xyz.valnet.engine.util.Math.lerp;
import java.util.List;
import xyz.valnet.engine.graphics.Drawing; import xyz.valnet.engine.graphics.Drawing;
import xyz.valnet.engine.math.Vector2f; import xyz.valnet.engine.math.Vector2f;
import xyz.valnet.engine.math.Vector2i;
import xyz.valnet.engine.math.Vector4f; import xyz.valnet.engine.math.Vector4f;
import xyz.valnet.engine.scenegraph.GameObject; import xyz.valnet.engine.scenegraph.GameObject;
import xyz.valnet.engine.shaders.SimpleShader; import xyz.valnet.engine.shaders.SimpleShader;
@ -23,7 +26,6 @@ import xyz.valnet.hadean.util.Assets;
public class Pawn extends GameObject implements ISelectable { public class Pawn extends GameObject implements ISelectable {
private float x = 0.5f, y = 0.5f; private float x = 0.5f, y = 0.5f;
private float dx, dy;
private float counter = 0; private float counter = 0;
@ -86,26 +88,68 @@ public class Pawn extends GameObject implements ISelectable {
@Override @Override
public void tick(float dTime) { public void tick(float dTime) {
if(path != null && !path.isComplete()) move(); // firstly, TRY PATHING.
else newPath(); 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() { private Vector2i getCurrentPos() {
// set new destination return new Vector2i((int)Math.floor(x), (int)Math.floor(y));
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 route() { private IWorkable currentJob;
private void tryStartWork() {
List<IWorkable> 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 // intify all the coordinates
int ix = (int)Math.floor(x); int ix = (int)Math.floor(x);
int iy = (int)Math.floor(y); int iy = (int)Math.floor(y);
int idx = (int)Math.floor(dx); int idx = path.dst.x;
int idy = (int)Math.floor(dy); int idy = path.dst.y;
// try to make a new path. // try to make a new path.
path = pathfinder.getPath(ix, iy, idx, idy); 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 --;
if(counter < 0) counter = 0; if(counter < 0) counter = 0;
if(counter == 0) { if(counter == 0) {
route(); reroute();
} }
return; return;
} }
@ -160,7 +204,7 @@ public class Pawn extends GameObject implements ISelectable {
@Override @Override
public Action[] getActions() { public Action[] getActions() {
return new Action[] { return new Action[] {
ACTION_REROUTE, // ACTION_REROUTE,
ACTION_TOGGLE_DEBUG, ACTION_TOGGLE_DEBUG,
ACTION_PAUSE ACTION_PAUSE
}; };
@ -171,10 +215,15 @@ public class Pawn extends GameObject implements ISelectable {
if(action == ACTION_PAUSE) { if(action == ACTION_PAUSE) {
paused = !paused; paused = !paused;
} else if(action == ACTION_REROUTE) { } else if(action == ACTION_REROUTE) {
newPath(); reroute();
} else if(action == ACTION_TOGGLE_DEBUG) { } else if(action == ACTION_TOGGLE_DEBUG) {
debug = !debug; debug = !debug;
} }
} }
@Override
public String details() {
return "IM A PAWNNNNN!!!!";
}
} }

View File

@ -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)); // return (float) Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
// } // }
private List<ISelectable> toRemove = new ArrayList<ISelectable>();
@Override @Override
public void tick(float dTime) { public void tick(float dTime) {
if(animation < animationMax) animation ++; if(animation < animationMax) animation ++;
@ -58,6 +60,18 @@ public class Selection extends GameObject {
initialCoords = null; 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 @Override

View File

@ -55,6 +55,11 @@ public class SelectionUI extends GameObject implements ISelectionChangeListener,
if(selectedTypes.size() == 1) { if(selectedTypes.size() == 1) {
Assets.font.drawString("" + count + "x " + name, 26, 376); 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) { for(Button btn : actionButtons) {
btn.draw(); btn.draw();
} }

View File

@ -34,26 +34,15 @@ public class Terrain extends GameObject implements IPathable {
return tiles[x][y]; 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 @Override
public boolean isWalkable(int x, int y, int fromX, int fromY) { 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 @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; return x < 0 || y < 0 || x >= WORLD_SIZE || y >= WORLD_SIZE;
} }

View File

@ -1,12 +1,16 @@
package xyz.valnet.hadean.gameobjects; package xyz.valnet.hadean.gameobjects;
import xyz.valnet.engine.math.Vector2i;
import xyz.valnet.engine.math.Vector4f; import xyz.valnet.engine.math.Vector4f;
import xyz.valnet.engine.scenegraph.GameObject; import xyz.valnet.engine.scenegraph.GameObject;
import xyz.valnet.hadean.util.Action; import xyz.valnet.hadean.util.Action;
import xyz.valnet.hadean.util.Assets; 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 Camera camera;
private Terrain terrain;
private boolean chopFlag = false;
private int x, y; private int x, y;
@ -17,11 +21,14 @@ public class Tree extends GameObject implements ITileThing, ISelectable {
public void start() { public void start() {
camera = get(Camera.class); camera = get(Camera.class);
terrain = get(Terrain.class);
} }
@Override @Override
public void render() { 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); camera.draw(Assets.tree, x - 1, y - 2, 3, 3);
Assets.flat.popColor();
} }
@Override @Override
@ -45,7 +52,64 @@ public class Tree extends GameObject implements ITileThing, ISelectable {
@Override @Override
public void runAction(Action action) { 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));
}
} }

View File

@ -24,7 +24,7 @@ public class AStarPathfinder implements IPathfinder {
private Node getPathfindingNode(int x, int y, List<Node> open, List<Node> closed, Node parent, int dstX, int dstY) { private Node getPathfindingNode(int x, int y, List<Node> open, List<Node> closed, Node parent, int dstX, int dstY) {
// TODO this isnt necessarily the BOUNDS so... think about that. // TODO this isnt necessarily the BOUNDS so... think about that.
if(pathable.isInBounds(x, y)) { if(pathable.isOutOfBounds(x, y)) {
return null; return null;
} }
@ -107,7 +107,7 @@ public class AStarPathfinder implements IPathfinder {
path.pop(); path.pop();
return new Path(path, current.getCost()); return new Path(path, current);
} }
Node[] neighbors = getNeighbors(current, open, closed, x2, y2); Node[] neighbors = getNeighbors(current, open, closed, x2, y2);
@ -149,6 +149,7 @@ public class AStarPathfinder implements IPathfinder {
Path bestPath = null; Path bestPath = null;
for(Vector2i dst : dsts) { for(Vector2i dst : dsts) {
Path path = getPath(src.x, src.y, dst.x, dst.y); Path path = getPath(src.x, src.y, dst.x, dst.y);
if(path == null) continue;
if(path.cost < cost) { if(path.cost < cost) {
cost = path.cost; cost = path.cost;
bestPath = path; bestPath = path;

View File

@ -2,5 +2,5 @@ package xyz.valnet.hadean.pathfinding;
public interface IPathable { public interface IPathable {
public boolean isWalkable(int x, int y, int fromX, int fromY); 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);
} }

View File

@ -6,10 +6,12 @@ import java.util.Stack;
public class Path implements Iterable<Node> { public class Path implements Iterable<Node> {
private Stack<Node> nodes; private Stack<Node> nodes;
public final int cost; public final int cost;
public final Node dst;
public Path(Stack<Node> nodes, int cost) { public Path(Stack<Node> nodes, Node dst) {
this.nodes = nodes; this.nodes = nodes;
this.cost = cost; this.cost = dst.getCost();
this.dst = dst;
} }
public Node peek() { public Node peek() {

View File

@ -16,6 +16,7 @@ public class GameScene implements IScene {
// generic // generic
private List<GameObject> objects = new ArrayList<GameObject>(); private List<GameObject> objects = new ArrayList<GameObject>();
private List<GameObject> newObjects = new ArrayList<GameObject>(); private List<GameObject> newObjects = new ArrayList<GameObject>();
private List<GameObject> removeObjects = new ArrayList<GameObject>();
// private List<IRenderable> renderables = new ArrayList<IRenderable>(); // private List<IRenderable> renderables = new ArrayList<IRenderable>();
// specific // 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) { for(GameObject obj : objects) {
obj.tick(dTime); obj.tick(dTime);
} }
@ -70,7 +78,7 @@ public class GameScene implements IScene {
@Override @Override
public void enable() { public void enable() {
objects.add(new Terrain()); 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 Pawn());
} }
objects.add(new Camera()); objects.add(new Camera());
@ -96,4 +104,12 @@ public class GameScene implements IScene {
obj.link(this); obj.link(this);
} }
public void remove(GameObject obj) {
removeObjects.add(obj);
}
public boolean inScene(GameObject gameObject) {
return objects.contains(gameObject);
}
} }

View File

@ -23,11 +23,11 @@ public class Assets {
public static final Tile9 uiFrameLight; public static final Tile9 uiFrameLight;
public static final Tile9 uiFrameDark; public static final Tile9 uiFrameDark;
public static final Sprite[] defaultTerrain; public static final Sprite[] defaultTerrain;
public static final Sprite pawn; public static final Sprite pawn;
public static final Sprite tree; public static final Sprite tree;
public static final Sprite rocks; public static final Sprite rocks;
public static final Sprite log;
public static final SimpleShader flat; public static final SimpleShader flat;
@ -46,6 +46,7 @@ public class Assets {
pawn = new Sprite(atlas, 48, 88, 8, 8); pawn = new Sprite(atlas, 48, 88, 8, 8);
tree = new Sprite(atlas, 64, 64, 24, 24); tree = new Sprite(atlas, 64, 64, 24, 24);
rocks = new Sprite(atlas, 64, 104, 8, 8); rocks = new Sprite(atlas, 64, 104, 8, 8);
log = new Sprite(atlas, 48, 96, 16, 16);
Map<Character, Sprite> charset = new HashMap<Character, Sprite>(); Map<Character, Sprite> charset = new HashMap<Character, Sprite>();