ui updates & camera!

bottom-bar
Ivory 2023-01-20 06:47:44 -05:00
parent 7c0a3be105
commit 9f59efc3d7
17 changed files with 204 additions and 50 deletions

View File

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

View File

@ -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) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<Integer> keys = new HashSet<Integer>();
@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);
}
}

View File

@ -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<Vector4f> getGuiBoxes() {
return List.of(Vector4f.zero);
}
@Override
public float getLayer() {
return 0;
}
}

View File

@ -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() {

View File

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

View File

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

View File

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

View File

@ -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 ++) {{

View File

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

View File

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

View File

@ -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 ++;