From 9f59efc3d7959f4d0c241c816a6f53ae6902eb4f Mon Sep 17 00:00:00 2001 From: Ivory Date: Fri, 20 Jan 2023 06:47:44 -0500 Subject: [PATCH] ui updates & camera! --- .vscode/settings.json | 3 +- src/main/java/xyz/valnet/engine/App.java | 36 ++++---- src/main/java/xyz/valnet/engine/Game.java | 12 +++ .../java/xyz/valnet/engine/graphics/Font.java | 20 +++++ .../java/xyz/valnet/engine/math/Vector2f.java | 23 +++++ .../valnet/engine/scenegraph/GameObject.java | 4 + .../xyz/valnet/engine/scenegraph/IScene.java | 4 + .../valnet/engine/scenegraph/SceneGraph.java | 24 ++++++ .../xyz/valnet/hadean/gameobjects/Camera.java | 84 ++++++++++++++++--- .../xyz/valnet/hadean/gameobjects/Clock.java | 17 +--- .../valnet/hadean/gameobjects/Terrain.java | 2 +- .../inputlayer/SelectionLayer.java | 9 +- .../hadean/gameobjects/ui/HoverQuery.java | 8 +- .../hadean/gameobjects/ui/tabs/BuildTab.java | 2 +- .../hadean/gameobjects/worldobjects/Rice.java | 3 +- .../worldobjects/agents/Agent.java | 2 +- .../java/xyz/valnet/hadean/util/Layers.java | 1 + 17 files changed, 204 insertions(+), 50 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 13f5352..e359646 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,5 @@ { "java.configuration.updateBuildConfiguration": "automatic", - "java.dependency.packagePresentation": "hierarchical" + "java.dependency.packagePresentation": "hierarchical", + "java.jdt.ls.vmargs": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx2G -Xms100m -Xlog:disable" } \ No newline at end of file diff --git a/src/main/java/xyz/valnet/engine/App.java b/src/main/java/xyz/valnet/engine/App.java index 23f3928..235162a 100644 --- a/src/main/java/xyz/valnet/engine/App.java +++ b/src/main/java/xyz/valnet/engine/App.java @@ -1,21 +1,26 @@ package xyz.valnet.engine; -import org.lwjgl.glfw.*; -import org.lwjgl.openal.*; -import org.lwjgl.opengl.*; -import org.lwjgl.system.*; - -import xyz.valnet.engine.math.Matrix4f; - -import java.nio.*; - import static org.lwjgl.glfw.Callbacks.*; import static org.lwjgl.glfw.GLFW.*; +import static org.lwjgl.openal.ALC10.*; import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.system.MemoryStack.*; import static org.lwjgl.system.MemoryUtil.*; -import static org.lwjgl.openal.ALC10.*; +import java.nio.IntBuffer; + +import org.lwjgl.glfw.GLFWCursorPosCallback; +import org.lwjgl.glfw.GLFWErrorCallback; +import org.lwjgl.glfw.GLFWMouseButtonCallback; +import org.lwjgl.glfw.GLFWVidMode; +import org.lwjgl.openal.AL; +import org.lwjgl.openal.ALC; +import org.lwjgl.openal.ALCCapabilities; +import org.lwjgl.openal.ALCapabilities; +import org.lwjgl.opengl.GL; +import org.lwjgl.system.MemoryStack; + +import xyz.valnet.engine.math.Matrix4f; public class App { @@ -35,7 +40,6 @@ public class App { public void run() { - init(); loop(); @@ -72,11 +76,15 @@ public class App { // Setup a key callback. It will be called every time a key is pressed, repeated or released. glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> { - if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE ) - glfwSetWindowShouldClose(window, true); // We will detect this in the rendering loop + if(action == GLFW_RELEASE) { + game.keyRelease(key); + } else if(action == GLFW_PRESS) { + game.keyPress(key); + } else { + game.keyRepeat(key); + } }); - glfwSetCursorPosCallback(window, new GLFWCursorPosCallback() { @Override public void invoke(long window, double xpos, double ypos) { diff --git a/src/main/java/xyz/valnet/engine/Game.java b/src/main/java/xyz/valnet/engine/Game.java index fe9055f..cebe2e0 100644 --- a/src/main/java/xyz/valnet/engine/Game.java +++ b/src/main/java/xyz/valnet/engine/Game.java @@ -60,4 +60,16 @@ public abstract class Game { public final void mouseUp(int button) { scene.mouseUp(button); } + + public final void keyPress(int key) { + scene.keyPress(key); + } + + public final void keyRelease(int key) { + scene.keyRelease(key); + } + + public final void keyRepeat(int key) { + scene.keyRepeat(key); + } } diff --git a/src/main/java/xyz/valnet/engine/graphics/Font.java b/src/main/java/xyz/valnet/engine/graphics/Font.java index 76f136f..6c453fc 100644 --- a/src/main/java/xyz/valnet/engine/graphics/Font.java +++ b/src/main/java/xyz/valnet/engine/graphics/Font.java @@ -2,7 +2,9 @@ package xyz.valnet.engine.graphics; import java.util.Map; +import xyz.valnet.engine.math.Vector4f; import xyz.valnet.engine.math.Vector4i; +import xyz.valnet.hadean.util.Assets; public class Font { @@ -18,6 +20,24 @@ public class Font { this.h = h * scale; } + public void drawStringOutlined(String str, int x, int y) { + Assets.flat.pushColor(Vector4f.black); + drawString(str, x - scale, y - scale); + drawString(str, x, y - scale); + drawString(str, x + scale, y - scale); + + drawString(str, x - scale, y); + + drawString(str, x + scale, y); + + drawString(str, x - scale, y + scale); + drawString(str, x, y + scale); + drawString(str, x + scale, y + scale); + Assets.flat.popColor(); + + drawString(str, x, y); + } + public void drawString(String str, int x, int y) { int cursorX = x; int cursorY = y; diff --git a/src/main/java/xyz/valnet/engine/math/Vector2f.java b/src/main/java/xyz/valnet/engine/math/Vector2f.java index ce4bab1..a7a3565 100644 --- a/src/main/java/xyz/valnet/engine/math/Vector2f.java +++ b/src/main/java/xyz/valnet/engine/math/Vector2f.java @@ -6,6 +6,12 @@ public class Vector2f implements Serializable { public float x, y; + public static Vector2f zero = new Vector2f(0, 0); + public static Vector2f north = new Vector2f(0, -1); + public static Vector2f east = new Vector2f(1, 0); + public static Vector2f south = new Vector2f(0, 1); + public static Vector2f west = new Vector2f(-1, 0); + public Vector2f() { x = 0.0f; y = 0.0f; @@ -28,4 +34,21 @@ public class Vector2f implements Serializable { return new Vector2f(x + v.x, y + v.y); } + public Vector2f subtract(Vector2f v) { + return new Vector2f(x - v.x, y - v.y); + } + + public Vector2f normalize() { + float r = (float) Math.sqrt(x*x + y*y); + if(r == 0) return Vector2f.zero; + return new Vector2f(x / r, y / r); + } + + public Vector2f multiply(float m) { + return new Vector2f(x * m, y * m); + } + + public String toString() { + return "<" + x + ", " + y + ">"; + } } diff --git a/src/main/java/xyz/valnet/engine/scenegraph/GameObject.java b/src/main/java/xyz/valnet/engine/scenegraph/GameObject.java index b8e1d85..81401b6 100644 --- a/src/main/java/xyz/valnet/engine/scenegraph/GameObject.java +++ b/src/main/java/xyz/valnet/engine/scenegraph/GameObject.java @@ -77,4 +77,8 @@ public class GameObject implements IRenderable, ITickable, Serializable { protected void load() { scene.queueLoad(); } + + protected boolean getKey(int key) { + return scene.getKey(key); + } } diff --git a/src/main/java/xyz/valnet/engine/scenegraph/IScene.java b/src/main/java/xyz/valnet/engine/scenegraph/IScene.java index 7dddf66..24a7d7f 100644 --- a/src/main/java/xyz/valnet/engine/scenegraph/IScene.java +++ b/src/main/java/xyz/valnet/engine/scenegraph/IScene.java @@ -7,6 +7,10 @@ public interface IScene { public void mouseDown(int button); public void mouseUp(int button); + public void keyPress(int key); + public void keyRelease(int key); + public void keyRepeat(int key); + public void enable(); public void disable(); } diff --git a/src/main/java/xyz/valnet/engine/scenegraph/SceneGraph.java b/src/main/java/xyz/valnet/engine/scenegraph/SceneGraph.java index a6e50a6..ac4ac20 100644 --- a/src/main/java/xyz/valnet/engine/scenegraph/SceneGraph.java +++ b/src/main/java/xyz/valnet/engine/scenegraph/SceneGraph.java @@ -7,9 +7,11 @@ import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import java.util.stream.Collectors; import xyz.valnet.engine.App; @@ -243,4 +245,26 @@ public abstract class SceneGraph implements IScene { iml.mouseUp(button); } } + + private static Set keys = new HashSet(); + + @Override + public final void keyPress(int key) { + keys.add(key); + System.out.println("keyCode: " + key); + } + + @Override + public final void keyRelease(int key) { + if(keys.contains(key)) keys.remove(key); + } + + @Override + public final void keyRepeat(int key) { + + } + + public boolean getKey(int key) { + return keys.contains(key); + } } diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/Camera.java b/src/main/java/xyz/valnet/hadean/gameobjects/Camera.java index 281757e..b52a255 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/Camera.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/Camera.java @@ -1,18 +1,24 @@ package xyz.valnet.hadean.gameobjects; -import static xyz.valnet.engine.util.Math.lerp; +import static xyz.valnet.engine.util.Math.*; +import java.util.List; + +import xyz.valnet.engine.App; import xyz.valnet.engine.graphics.Drawing; import xyz.valnet.engine.graphics.Sprite; import xyz.valnet.engine.math.Vector2f; +import xyz.valnet.engine.math.Vector2i; import xyz.valnet.engine.math.Vector4f; import xyz.valnet.engine.math.Vector4i; import xyz.valnet.engine.scenegraph.GameObject; +import xyz.valnet.engine.scenegraph.IMouseCaptureArea; +import xyz.valnet.engine.scenegraph.ITransient; import xyz.valnet.hadean.interfaces.IWorldBoundsAdapter; import xyz.valnet.hadean.util.Assets; import xyz.valnet.hadean.util.Layers; -public class Camera extends GameObject { +public class Camera extends GameObject implements ITransient, IMouseCaptureArea { private int tileWidth = 16; // TODO link these in some way to the real resolution. lot of work here. @@ -30,16 +36,42 @@ public class Camera extends GameObject { maxY = bounds.w; } + public void update(float dTime) { + Vector2f direction = Vector2f.zero; + if(dragOrigin == null) { + if(getKey(87)) { + direction = direction.add(Vector2f.north); + } + if(getKey(65)) { + direction = direction.add(Vector2f.west); + } + if(getKey(83)) { + direction = direction.add(Vector2f.south); + } + if(getKey(68)) { + direction = direction.add(Vector2f.east); + } + + Vector2f move = direction.normalize().multiply(dTime / 5f); + // move = Vector2f.east; + // System.out.println(move); + focus = focus.add(move); + } else { + Vector2f dragDifference = screen2world(App.mouseX, App.mouseY).subtract(focus); + focus = dragOrigin.subtract(dragDifference); + } + } + public void focus(float x, float y) { this.focus.x = x; this.focus.y = y; } - public Vector2f world2screen(float x, float y) { - return new Vector2f(x * tileWidth + screenWidth / 2 - focus.x * tileWidth, y * tileWidth + screenHeight / 2 - focus.y * tileWidth); + public Vector2i world2screen(float x, float y) { + return new Vector2i((int)(x * tileWidth + screenWidth / 2 - focus.x * tileWidth), (int)(y * tileWidth + screenHeight / 2 - focus.y * tileWidth)); } - public Vector2f world2screen(Vector2f pos) { + public Vector2i world2screen(Vector2f pos) { return world2screen(pos.x, pos.y); } @@ -58,14 +90,14 @@ public class Camera extends GameObject { @Deprecated public void draw(Sprite sprite, float x, float y) { - Vector2f screenPos = world2screen(x, y); - Drawing.drawSprite(sprite, (int)(screenPos.x), (int)(screenPos.y), tileWidth, tileWidth); + Vector2i screenPos = world2screen(x, y); + Drawing.drawSprite(sprite, (screenPos.x), (screenPos.y), tileWidth, tileWidth); } @Deprecated public void draw(Sprite sprite, float x, float y, float w, float h) { - Vector2f screenPos = world2screen(x, y); - Drawing.drawSprite(sprite, (int)(screenPos.x), (int)(screenPos.y), (int)(tileWidth * w), (int)(tileWidth * h)); + Vector2i screenPos = world2screen(x, y); + Drawing.drawSprite(sprite, (screenPos.x), (screenPos.y), (int)(tileWidth * w), (int)(tileWidth * h)); } public void draw(float layer, Sprite sprite, float x, float y) { @@ -81,7 +113,7 @@ public class Camera extends GameObject { } public void draw(float layer, Sprite sprite, float x, float y, float w, float h) { - Vector2f screenPos = world2screen(x, y); + Vector2i screenPos = world2screen(x, y); Drawing.setLayer(layer + (((y + h) - minY) / (maxY - minY))); Drawing.drawSprite(sprite, (int)(screenPos.x), (int)(screenPos.y), (int)(tileWidth * w), (int)(tileWidth * h)); } @@ -96,5 +128,37 @@ public class Camera extends GameObject { Assets.fillColor.draw(box.x + 1 - h, box.y + 1 + box.w / 2 - h / 2, (int)Math.round(lerp(0, box.z - 3 + h * 2, progress)) + 1, h - 2); Assets.flat.popColor(); } + + @Override + public void mouseEnter() {} + + @Override + public void mouseLeave() {} + + private Vector2f dragOrigin = null; + + @Override + public void mouseDown(int button) { + if(button == 2) { + dragOrigin = screen2world(App.mouseX, App.mouseY); + } + } + + @Override + public void mouseUp(int button) { + if(button == 2) { + dragOrigin = null; + } + } + + @Override + public List getGuiBoxes() { + return List.of(Vector4f.zero); + } + + @Override + public float getLayer() { + return 0; + } } diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/Clock.java b/src/main/java/xyz/valnet/hadean/gameobjects/Clock.java index 0509358..750de9d 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/Clock.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/Clock.java @@ -30,20 +30,9 @@ public class Clock extends GameObject { @Override public void render() { Drawing.setLayer(Layers.GENERAL_UI); - String str = toString() + " (Light: " + Math.round(getSunlight() * 100) + "%)"; - int left = 440; - Assets.flat.pushColor(Vector4f.black); - Assets.font.drawString(str, left - 1, 9); - Assets.font.drawString(str, left, 9); - Assets.font.drawString(str, left + 1, 9); - Assets.font.drawString(str, left - 1, 10); - Assets.font.drawString(str, left + 1, 10); - Assets.font.drawString(str, left - 1, 11); - Assets.font.drawString(str, left, 11); - Assets.font.drawString(str, left + 1, 11); - Assets.flat.swapColor(Vector4f.one); - Assets.font.drawString(str, left, 10); - Assets.flat.popColor(); + String str = toString(); + int left = 950; + Assets.font.drawStringOutlined(str, left, 520); } public float getSunlight() { diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/Terrain.java b/src/main/java/xyz/valnet/hadean/gameobjects/Terrain.java index 20fa4fb..236bd62 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/Terrain.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/Terrain.java @@ -9,7 +9,7 @@ import xyz.valnet.hadean.pathfinding.IPathable; public class Terrain extends GameObject implements IPathable, IWorldBoundsAdapter { - public static final int WORLD_SIZE = 30; + public static final int WORLD_SIZE = 64; public static final int TILE_SIZE = 8; // public static int left, top; diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/inputlayer/SelectionLayer.java b/src/main/java/xyz/valnet/hadean/gameobjects/inputlayer/SelectionLayer.java index a1010cf..88c6fee 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/inputlayer/SelectionLayer.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/inputlayer/SelectionLayer.java @@ -1,11 +1,14 @@ package xyz.valnet.hadean.gameobjects.inputlayer; +import static xyz.valnet.engine.util.Math.*; + import java.util.ArrayList; import java.util.List; import xyz.valnet.engine.App; 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.scenegraph.IMouseCaptureArea; @@ -17,8 +20,6 @@ import xyz.valnet.hadean.interfaces.ISelectionChangeListener; import xyz.valnet.hadean.util.Assets; import xyz.valnet.hadean.util.Layers; -import static xyz.valnet.engine.util.Math.lerp; - public class SelectionLayer extends GameObject implements IMouseCaptureArea, ITransient { public Vector2f initialCoords; @@ -82,8 +83,8 @@ public class SelectionLayer extends GameObject implements IMouseCaptureArea, ITr for(ISelectable thing : selected) { Vector4f box = thing.getWorldBox(); - Vector2f min = camera.world2screen(box.x - p, box.y - p); - Vector2f max = camera.world2screen(box.z + p, box.w + p); + Vector2i min = camera.world2screen(box.x - p, box.y - p); + Vector2i max = camera.world2screen(box.z + p, box.w + p); Drawing.setLayer(Layers.SELECTION_IDENTIFIERS); Assets.selectedFrame.draw((int)min.x, (int)min.y, (int)(max.x - min.x), (int)(max.y - min.y)); thing.selectedRender(); diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/ui/HoverQuery.java b/src/main/java/xyz/valnet/hadean/gameobjects/ui/HoverQuery.java index 3849d48..9a018f9 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/ui/HoverQuery.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/ui/HoverQuery.java @@ -4,15 +4,18 @@ import java.util.ArrayList; import java.util.List; import xyz.valnet.engine.App; +import xyz.valnet.engine.graphics.Drawing; import xyz.valnet.engine.math.Vector2f; import xyz.valnet.engine.math.Vector4f; import xyz.valnet.engine.scenegraph.GameObject; import xyz.valnet.engine.scenegraph.ITransient; import xyz.valnet.hadean.HadeanGame; +import xyz.valnet.hadean.gameobjects.BottomBar; import xyz.valnet.hadean.gameobjects.Camera; import xyz.valnet.hadean.gameobjects.Tile; import xyz.valnet.hadean.gameobjects.worldobjects.WorldObject; import xyz.valnet.hadean.util.Assets; +import xyz.valnet.hadean.util.Layers; public class HoverQuery extends GameObject implements ITransient { @@ -50,11 +53,12 @@ public class HoverQuery extends GameObject implements ITransient { @Override public void render() { - int i = 16; + Drawing.setLayer(Layers.LOW_PRIORITY_UI); + int i = 576 - BottomBar.bottomBarHeight - 32; for(String thingString : thingStrings) { for(String str : thingString.split("\n")) { Assets.font.drawString(str, 16, i); - i += 14; + i -= 14; } } } diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/ui/tabs/BuildTab.java b/src/main/java/xyz/valnet/hadean/gameobjects/ui/tabs/BuildTab.java index 303ee1e..da59e7e 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/ui/tabs/BuildTab.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/ui/tabs/BuildTab.java @@ -115,7 +115,7 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IMouseCap if(selectedBuildable == null) return; // draw the currently selected build item Assets.flat.pushColor(new Vector4f(1f, 1f, 1f, 1.0f)); - Vector2i topLeft = camera.world2screen(x, y).asInt(); + Vector2i topLeft = camera.world2screen(x, y); Assets.font.drawString(selectedBuildable.name, topLeft.x, topLeft.y - 20); Assets.flat.swapColor(new Vector4f(1f, 1f, 1f, 0.5f)); for(int i = 0; i < w; i ++) for(int j = 0; j < h; j ++) {{ diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/Rice.java b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/Rice.java index 89037c8..a88d872 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/Rice.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/Rice.java @@ -1,6 +1,5 @@ package xyz.valnet.hadean.gameobjects.worldobjects; -import xyz.valnet.engine.math.Vector2f; import xyz.valnet.engine.math.Vector2i; import xyz.valnet.engine.math.Vector4f; import xyz.valnet.hadean.gameobjects.worldobjects.items.Item; @@ -22,7 +21,7 @@ public class Rice extends Item { camera.draw(Layers.AIR, Assets.riceBag, pos.x, pos.y); Assets.flat.pushColor(Vector4f.black); - Vector2f screeCoords = camera.world2screen(pos.x, pos.y); + Vector2i screeCoords = camera.world2screen(pos.x, pos.y); Assets.miniFont.drawString("123", (int)screeCoords.x, (int)screeCoords.y); Assets.flat.popColor(); } diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/agents/Agent.java b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/agents/Agent.java index 7ff302f..b8bd7de 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/agents/Agent.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/agents/Agent.java @@ -165,7 +165,7 @@ public abstract class Agent extends WorldObject implements ISelectable { int count = 0; for(Node node : path) { glBegin(GL_LINES); - Vector2f u, v; + Vector2i u, v; Vector2i pos = getWorldPosition().xy(); if(node.from == null) u = camera.world2screen(pos.x, pos.y); diff --git a/src/main/java/xyz/valnet/hadean/util/Layers.java b/src/main/java/xyz/valnet/hadean/util/Layers.java index 04d3000..c522492 100644 --- a/src/main/java/xyz/valnet/hadean/util/Layers.java +++ b/src/main/java/xyz/valnet/hadean/util/Layers.java @@ -16,6 +16,7 @@ public class Layers { public static final float SELECTION_IDENTIFIERS = current ++; public static final float AREA_SELECT_BOX = current ++; public static final float BUILD_INTERACTABLE = current ++; + public static final float LOW_PRIORITY_UI = current ++; public static final float GENERAL_UI = current ++; public static final float GENERAL_UI_INTERACTABLE = current ++; public static final float BOTTOM_BAR = current ++;