From 8e1f91d947a197d5ec170ff889c41d32a9bd1b45 Mon Sep 17 00:00:00 2001 From: Valerie Date: Thu, 19 May 2022 06:27:48 -0400 Subject: [PATCH] pawns and basic pathfinding --- res/textures.png | Bin 7645 -> 7744 bytes .../xyz/valnet/engine/graphics/Drawing.java | 14 +- .../xyz/valnet/engine/graphics/Sprite.java | 4 + .../valnet/engine/scenegraph/GameObject.java | 14 +- src/main/java/xyz/valnet/hadean/Tile.java | 31 ++++ .../xyz/valnet/hadean/gameobjects/Pawn.java | 111 ++++++++++++ .../valnet/hadean/gameobjects/Terrain.java | 171 ++++++++++++++++-- .../xyz/valnet/hadean/pathfinding/Node.java | 10 + .../xyz/valnet/hadean/scenes/GameScene.java | 19 +- .../java/xyz/valnet/hadean/util/Assets.java | 3 + 10 files changed, 345 insertions(+), 32 deletions(-) create mode 100644 src/main/java/xyz/valnet/hadean/Tile.java create mode 100644 src/main/java/xyz/valnet/hadean/gameobjects/Pawn.java create mode 100644 src/main/java/xyz/valnet/hadean/pathfinding/Node.java diff --git a/res/textures.png b/res/textures.png index 052e2df80259b26c6114c8f6171e289315361409..82599410e35fc30d49279b5bf946cc19fd45631e 100644 GIT binary patch delta 7294 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 V*N*!l$DpgD`Be8wt%_ab{{afPP^|y} delta 7204 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 T get(Class clazz) { + return this.scene.get(clazz); } @Override diff --git a/src/main/java/xyz/valnet/hadean/Tile.java b/src/main/java/xyz/valnet/hadean/Tile.java new file mode 100644 index 0000000..cd56361 --- /dev/null +++ b/src/main/java/xyz/valnet/hadean/Tile.java @@ -0,0 +1,31 @@ +package xyz.valnet.hadean; + +import xyz.valnet.engine.graphics.Drawing; +import xyz.valnet.engine.graphics.Sprite; +import xyz.valnet.engine.math.Vector4f; +import xyz.valnet.hadean.gameobjects.Terrain; +import xyz.valnet.hadean.util.Assets; + +public class Tile { + private final int x, y; + private final Vector4f color = new Vector4f((float) Math.random() * 0.1f, 0.4f + (float) Math.random() * 0.15f, (float) Math.random() * 0.05f, 1f); + private final Sprite sprite = Assets.defaultTerrain[(int)Math.floor(Math.random() * Assets.defaultTerrain.length)]; + private final boolean obstacle; + + public Tile(int x, int y) { + float distanceFromOrigin = 0.9f - (float)Math.sqrt(x * x + y * y) / 42; + this.x = x; + this.y = y; + this.obstacle = Math.random() > 0.8f; + } + + public void render() { + Assets.flat.pushColor(isWalkable() ? color : new Vector4f(0.1f, 0.1f, 0.1f, 1f)); + Drawing.drawSprite(sprite, Terrain.left + x * Terrain.TILE_SIZE, Terrain.top + y * Terrain.TILE_SIZE); + Assets.flat.popColor(); + } + + public boolean isWalkable() { + return !obstacle; + } +} diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/Pawn.java b/src/main/java/xyz/valnet/hadean/gameobjects/Pawn.java new file mode 100644 index 0000000..131c223 --- /dev/null +++ b/src/main/java/xyz/valnet/hadean/gameobjects/Pawn.java @@ -0,0 +1,111 @@ +package xyz.valnet.hadean.gameobjects; + +import static xyz.valnet.engine.util.Math.lerp; + +import java.util.Stack; + +import xyz.valnet.engine.graphics.Drawing; +import xyz.valnet.engine.math.Vector4f; +import xyz.valnet.engine.scenegraph.GameObject; +import xyz.valnet.hadean.pathfinding.Node; +import xyz.valnet.hadean.scenes.GameScene; +import xyz.valnet.hadean.util.Assets; + +import static org.lwjgl.opengl.GL20.*; +// import org.lwjgl.opengl.GL20; + +public class Pawn extends GameObject { + + private float x, y; + private float dx, dy; + + private float counter = 0; + + private Stack path; + + private final float speed = 20f; + + public Pawn(GameScene scene) { + super(scene); + } + + @Override + public void render() { + + Drawing.setLayer(0.15f); + + if(path != null && path.size() > 0) { + float cx = (int)(Terrain.left + (x - 0.5f) * Terrain.TILE_SIZE); + float cy = (int)(Terrain.top + (y - 0.5f) * Terrain.TILE_SIZE); + + Node n = path.peek(); + + float nx = Terrain.left + n.x * Terrain.TILE_SIZE; + float ny = Terrain.top + n.y * Terrain.TILE_SIZE; + + System.out.println("" + n.x + " " + n.y); + + Drawing.drawSprite(Assets.pawn, (int)lerp(cx, nx, counter / speed), (int)lerp(cy, ny, counter / speed)); + + if(path != null) { + for(Node node : path) { + glBegin(GL_LINES); + if(node.from == null) { + glVertex2f(Terrain.left + x * Terrain.TILE_SIZE, Terrain.top + y * Terrain.TILE_SIZE); + } else { + glVertex2f(Terrain.left + (node.from.x + 0.5f) * Terrain.TILE_SIZE, Terrain.top + (node.from.y + 0.5f) * Terrain.TILE_SIZE); + } + glVertex2f(Terrain.left + (node.x + 0.5f) * Terrain.TILE_SIZE, Terrain.top + (node.y + 0.5f) * Terrain.TILE_SIZE); + glEnd(); + } + } + } else { + int nx = (int)(Terrain.left + (x - 0.5f) * Terrain.TILE_SIZE); + int ny = (int)(Terrain.top + (y - 0.5f) * Terrain.TILE_SIZE); + + Drawing.drawSprite(Assets.pawn, nx, ny); + } + + // Drawing.setLayer(0.1f); + // Assets.flat.pushColor(Vector4f.black); + // Drawing.drawSprite(Assets.pawn, (int)(Terrain.left + dx * Terrain.TILE_SIZE) - Assets.pawn.width / 2, (int)(Terrain.top + dy * Terrain.TILE_SIZE) - Assets.pawn.height / 2); + + // Assets.flat.swapColor(new Vector4f(1, 0, 0, 1)); + // Drawing.setLayer(0.05f); + + // Assets.flat.popColor(); + } + + @Override + public void tick(float dTime) { + counter ++; + if(counter >= speed) action(); + } + + + + private void action() { + if(path == null || path.empty()) { + dx = 0.5f + (float)Math.floor(Math.random() * Terrain.WORLD_SIZE); + dy = 0.5f + (float)Math.floor(Math.random() * Terrain.WORLD_SIZE); + + int ix = (int)Math.floor(x); + int iy = (int)Math.floor(y); + + int idx = (int)Math.floor(dx); + int idy = (int)Math.floor(dy); + + path = get(Terrain.class).getPath(ix, iy, idx, idy); + if(path != null) { + counter = 0; + } + } else { + Node n = path.pop(); + x = n.x + 0.5f; + y = n.y + 0.5f; + counter = 0; + } + + } + +} diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/Terrain.java b/src/main/java/xyz/valnet/hadean/gameobjects/Terrain.java index fc81051..71198c8 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/Terrain.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/Terrain.java @@ -1,47 +1,178 @@ package xyz.valnet.hadean.gameobjects; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.LinkedList; +import java.util.List; +import java.util.Stack; + import xyz.valnet.engine.graphics.Drawing; -import xyz.valnet.engine.graphics.Sprite; -import xyz.valnet.engine.math.Vector4f; import xyz.valnet.engine.scenegraph.GameObject; import xyz.valnet.engine.scenegraph.IScene; -import xyz.valnet.hadean.util.Assets; +import xyz.valnet.hadean.Tile; +import xyz.valnet.hadean.pathfinding.Node; +import xyz.valnet.hadean.scenes.GameScene; +// implements IPathable, the thing that has callbacks for interfacing with a pathfinder. public class Terrain extends GameObject { - private final int WORLD_SIZE = 30; - private final int TILE_SIZE = 8; + public static final int WORLD_SIZE = 40; + public static final int TILE_SIZE = 8; - private int[][] variation = new int[WORLD_SIZE][WORLD_SIZE]; - private Vector4f[][] colorVariations = new Vector4f[WORLD_SIZE][WORLD_SIZE]; + public static int left, top; - public Terrain(IScene scene) { + private Tile[][] tiles = new Tile[WORLD_SIZE][WORLD_SIZE]; + + public Terrain(GameScene scene) { super(scene); for (int i = 0; i < WORLD_SIZE; i++) { for (int j = 0; j < WORLD_SIZE; j++) { - variation[i][j] = (int) Math.floor(Math.random() * 4); - colorVariations[i][j] = new Vector4f((float) Math.random() * 0.2f, 0.4f + (float) Math.random() * 0.2f, (float) Math.random() * 0.05f, 1f); + tiles[i][j] = new Tile(i, j); } } } + public Tile getTile(int x, int y) { + return tiles[x][y]; + } + + private Node findNodeInList(List nodes, int x, int y) { + for(Node node : nodes) { + if(node.x == x && node.y == y) return node; + } + return null; + } + + private Node getPathfindingNode(int x, int y, List open, List closed, Node parent, int dstX, int dstY) { + if(x < 0 || y < 0 || x >= WORLD_SIZE || y >= WORLD_SIZE) { + // * out of bounds + return null; + } + + Node node = findNodeInList(open, x, y); + if(node == null) { + node = findNodeInList(closed, x, y); + } + if(node == null) { + node = new Node(); + node.x = x; + node.y = y; + node.from = parent; + node.g = 0; + if(parent != null) { + node.g += parent.g; + } + if(node.from == null) { + node.g = 0; + } else { + node.g += (int)(Math.round(10 * Math.sqrt(Math.pow(node.from.x - x, 2) + Math.pow(node.from.y - y, 2)))); + } + node.h = (int)(Math.round(10 * Math.sqrt(Math.pow(dstX - x, 2) + Math.pow(dstY - y, 2)))); + } + return node; + } + + private Node[] getNeighbors(Node base, List open, List closed, int dstX, int dstY) { + Node[] neighbors = new Node[8]; + neighbors[0] = getPathfindingNode(base.x - 1, base.y - 1, open, closed, base, dstX, dstY); + neighbors[1] = getPathfindingNode(base.x, base.y - 1, open, closed, base, dstX, dstY); + neighbors[2] = getPathfindingNode(base.x + 1, base.y - 1, open, closed, base, dstX, dstY); + neighbors[3] = getPathfindingNode(base.x - 1, base.y, open, closed, base, dstX, dstY); + neighbors[4] = getPathfindingNode(base.x + 1, base.y, open, closed, base, dstX, dstY); + neighbors[5] = getPathfindingNode(base.x - 1, base.y + 1, open, closed, base, dstX, dstY); + neighbors[6] = getPathfindingNode(base.x, base.y + 1, open, closed, base, dstX, dstY); + neighbors[7] = getPathfindingNode(base.x + 1, base.y + 1, open, closed, base, dstX, dstY); + return neighbors; + } + + public Stack getPath(int x1, int y1, int x2, int y2) { + List open = new ArrayList(); + List closed = new ArrayList(); + + if(getTile(x2, y2).isWalkable() == false) return null; + + open.add(getPathfindingNode(x1, y1, open, closed, null, x2, y2)); + + while (open.size() != 0) { + open.sort(new Comparator() { + @Override + public int compare(Node a, Node b) { + int aCost = a.getCost(); + int bCost = b.getCost(); + if(aCost > bCost) { + return 1; + } else if (aCost < bCost) { + return -1; + } else if (a.h > b.h) { + return 1; + } else if (a.h < b.h) { + return -1; + } else { + return 0; + } + } + }); + Node current = open.get(0); + + open.remove(current); + closed.add(current); + + if(current.x == x2 && current.y == y2) { + Stack path = new Stack(); + + Node n = current; + while(n != null) { + path.push(n); + n = n.from; + } + + return path; + } + + Node[] neighbors = getNeighbors(current, open, closed, x2, y2); + + for(Node node : neighbors) { + if(node == null) continue; + if(closed.contains(node)) continue; + if(!getTile(node.x, node.y).isWalkable()) continue; + if(open.contains(node)) { + int newGCost = current.g + (int)(Math.round(10 * Math.sqrt(Math.pow(node.x - current.x, 2) + Math.pow(node.y - current.y, 2)))); + + if(node.g > newGCost) { + if(closed.contains(node)) { + closed.remove(node); + } + if(!open.contains(node)) { + open.add(node); + } + node.g = newGCost; + node.from = current; + } + } else { + open.add(node); + } + + + } + + } + + // i guess theres no path?! + + return null; + } + @Override public void render() { - int left = 400 - (WORLD_SIZE * TILE_SIZE / 2); - int top = 225 - (WORLD_SIZE * TILE_SIZE / 2); + left = 400 - (WORLD_SIZE * TILE_SIZE / 2); + top = 225 - (WORLD_SIZE * TILE_SIZE / 2); - - Sprite s; - Assets.flat.pushColor(Vector4f.one); + Drawing.setLayer(0f); for (int i = 0; i < WORLD_SIZE; i++) { for (int j = 0; j < WORLD_SIZE; j++) { - s = Assets.defaultTerrain[variation[i][j]]; - Assets.flat.swapColor(colorVariations[i][j]); - Drawing.drawSprite(s, left + i * s.width, top + j * s.height); + tiles[i][j].render(); } } - Assets.flat.popColor(); - } } diff --git a/src/main/java/xyz/valnet/hadean/pathfinding/Node.java b/src/main/java/xyz/valnet/hadean/pathfinding/Node.java new file mode 100644 index 0000000..b3463c5 --- /dev/null +++ b/src/main/java/xyz/valnet/hadean/pathfinding/Node.java @@ -0,0 +1,10 @@ +package xyz.valnet.hadean.pathfinding; + +public class Node { + public int x, y, g, h; + public Node from; + + public int getCost() { + return g + h; + } +} diff --git a/src/main/java/xyz/valnet/hadean/scenes/GameScene.java b/src/main/java/xyz/valnet/hadean/scenes/GameScene.java index 74dcf8c..1331ed9 100644 --- a/src/main/java/xyz/valnet/hadean/scenes/GameScene.java +++ b/src/main/java/xyz/valnet/hadean/scenes/GameScene.java @@ -5,6 +5,7 @@ import java.util.List; import xyz.valnet.engine.scenegraph.GameObject; import xyz.valnet.engine.scenegraph.IScene; +import xyz.valnet.hadean.gameobjects.Pawn; import xyz.valnet.hadean.gameobjects.Terrain; public class GameScene implements IScene { @@ -14,12 +15,20 @@ public class GameScene implements IScene { // private List renderables = new ArrayList(); // specific - private GameObject terrain; + + public T get(Class clazz) { + for(GameObject obj : objects) { + if(clazz.isInstance(obj)) { + return clazz.cast(obj); + } + } + return null; + } @Override public void render() { for(GameObject obj : objects) { - ((Terrain)obj).render(); + obj.render(); } } @@ -32,8 +41,10 @@ public class GameScene implements IScene { @Override public void enable() { - terrain = new Terrain(this); - objects.add(terrain); + objects.add(new Terrain(this)); + for(int i = 0; i < 3; i ++) { + objects.add(new Pawn(this)); + } } @Override diff --git a/src/main/java/xyz/valnet/hadean/util/Assets.java b/src/main/java/xyz/valnet/hadean/util/Assets.java index cd567d3..869389e 100644 --- a/src/main/java/xyz/valnet/hadean/util/Assets.java +++ b/src/main/java/xyz/valnet/hadean/util/Assets.java @@ -19,6 +19,7 @@ public class Assets { public static final Tile9 fireFrame; public static final Sprite[] defaultTerrain; + public static final Sprite pawn; public static final SimpleShader flat; @@ -34,6 +35,8 @@ public class Assets { new Sprite(atlas, new Vector4i(32, 64, 8, 8)) }; + pawn = new Sprite(atlas, 48, 88, 8, 8); + Map charset = new HashMap(); charset.put('A', new Sprite(atlas, new Vector4i( 0, 0, 8, 16)));