initial Commit

This commit is contained in:
Halbear 2026-01-10 21:28:21 +00:00
parent fb15ff8f06
commit 82db1f9321
65 changed files with 1616 additions and 0 deletions

View file

@ -0,0 +1,11 @@
package net.halbear.Executable;
import net.halbear.Terrain4J.EngineCore.Main.GameCore;
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
public class Init {
public static void main(String[] args){
var GameEngine = new PrimaryRuntime("Terrain4J", new GameCore());
GameEngine.run();
}
}

View file

@ -0,0 +1,15 @@
package net.halbear.Terrain4J.EngineCore.Display;
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
public class Render {
public Render(EngineInstance engineInstance) {
}
public void cleanup() {
}
public void render(EngineInstance engineInstance) {
}
}

View file

@ -0,0 +1,18 @@
package net.halbear.Terrain4J.EngineCore.Display;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.vulkan.VK;
import org.lwjgl.vulkan.VkApplicationInfo;
import java.nio.ByteBuffer;
import static org.lwjgl.vulkan.VK14.VK_API_VERSION_1_4;
public class VulkanInstance {
public VulkanInstance(boolean validate){
try (MemoryStack stack = MemoryStack.stackPush()) {
ByteBuffer appShortName = stack.UTF8("Terrain4J");
var appInfo = VkApplicationInfo.calloc(stack).sType$Default().pApplicationName(appShortName).applicationVersion(1).pEngineName(appShortName).engineVersion(3).apiVersion(VK_API_VERSION_1_4);
}
}
}

View file

@ -0,0 +1,97 @@
package net.halbear.Terrain4J.EngineCore.Display;
import net.halbear.Terrain4J.EngineCore.Input.KeyboardInput;
import net.halbear.Terrain4J.EngineCore.Input.MouseListener;
import net.halbear.Terrain4J.EngineCore.Logic.Globals;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.system.MemoryUtil;
import static org.lwjgl.glfw.Callbacks.glfwFreeCallbacks;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.glfw.GLFWVulkan.glfwVulkanSupported;
public class Window {
private final long handle;
private final KeyboardInput keyboardInput;
private final MouseListener mouseInput;
private int height;
private int width;
private boolean displayFPS = true;
public Window(String title){
if (!glfwInit()) {
throw new RuntimeException("Unable to initialize GLFW");
}
if (!glfwVulkanSupported()) {
throw new RuntimeException("Cannot find a compatible Vulkan installable client driver (ICD)");
}
GLFWVidMode vidMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
if (vidMode == null) {
throw new RuntimeException("Error getting primary monitor");
}
width = vidMode.width(); //Globals.getInstance().getWidth();
height = vidMode.height();//Globals.getInstance().getHeight();
glfwDefaultWindowHints();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_MAXIMIZED, GLFW_FALSE);
handle = glfwCreateWindow(width, height, title, MemoryUtil.NULL, MemoryUtil.NULL);
if (handle == MemoryUtil.NULL) {
//throw new RuntimeException("Failed to create the GLFW window");
}
keyboardInput = new KeyboardInput(handle);
glfwSetFramebufferSizeCallback(handle, (window, w, h) -> {
width = w;
height = h;
});
glfwMakeContextCurrent(handle);
if (Globals.VSYNC) glfwSwapInterval(1);
else glfwSwapInterval(0);
mouseInput = new MouseListener(handle);
}
public void cleanup() {
glfwFreeCallbacks(handle);
glfwDestroyWindow(handle);
glfwTerminate();
}
public long getHandle(){
return handle;
}
public int getHeight(){return height;}
public int getWidth(){return width;}
public KeyboardInput getKeyboardInput(){
return keyboardInput;
}
public MouseListener getMouseInput(){
return mouseInput;
}
public void pollEvents() {
if (displayFPS) glfwSetWindowTitle(handle, "Terrain 4J Engine - FPS: " + Globals.FrameRate_PRIMARYTHREAD + " TPS: " + Globals.TPS + " RenderFPS: " + Globals.FrameRate_RENDER + " VSYNC: " + Globals.VSYNC);
if (keyboardInput.keySinglePress(GLFW_KEY_V)) {
SetVsync();
}
keyboardInput.input();
mouseInput.input();
Globals.RENDERFRAMES++;
}
public void SetVsync(){
if (Globals.VSYNC) {
glfwSwapInterval(0);
Globals.VSYNC = false;
}
else {
glfwSwapInterval(1);
Globals.VSYNC = true;
}
}
public void setShouldClose() {
glfwSetWindowShouldClose(handle, true);
}
public boolean shouldClose() {
//return false;
return glfwWindowShouldClose(handle);
}
}

View file

@ -0,0 +1,58 @@
package net.halbear.Terrain4J.EngineCore.Input;
import org.lwjgl.glfw.GLFWCharCallbackI;
import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.glfw.GLFWKeyCallbackI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.lwjgl.glfw.GLFW.*;
public class KeyboardInput {
private long window;
public List<Integer> keysPressed = new ArrayList<>();
public List<Integer> keysSinglePressed = new ArrayList<>();
public KeyboardInput(long Window){
window = Window;
glfwSetKeyCallback(window, this::KeyCallback);
}
public void input() {
glfwPollEvents();
}
public void KeyCallback(long Window, int key, int scancode, int action, int mods){
if (!keysPressed.contains(key) && action == GLFW_PRESS){
keysPressed.add(key);
} else if (keysPressed.contains(key) && action == GLFW_RELEASE){
if (keysPressed.indexOf(key) >= 0 && keysPressed.indexOf(key) <keysPressed.size()){
keysPressed.remove(keysPressed.indexOf(key));
}
}
if (keysSinglePressed.contains(key)&& action == GLFW_RELEASE) keysSinglePressed.remove(keysSinglePressed.indexOf(key));
}
public boolean keyPressed(int keyCode) {
if (keysPressed.contains(keyCode)) return true;
else return false;
}
public boolean keySinglePress(int keyCode) {
if (keysPressed.contains(keyCode)) {
if (keysSinglePressed.contains(keyCode)) return false;
else {
keysSinglePressed.add(keyCode);
return true;
}
}
else {
return false;
}
}
public void setCharCallBack(GLFWCharCallbackI charCallback) {
glfwSetCharCallback(window, charCallback);
}
}

View file

@ -0,0 +1,58 @@
package net.halbear.Terrain4J.EngineCore.Input;
import org.joml.Vector2f;
import static org.lwjgl.glfw.GLFW.*;
public class MouseListener {
private final Vector2f currentPos;
private final Vector2f deltaPos;
private final Vector2f previousPos;
private boolean FocusWindow;
private boolean leftButtonPressed;
private boolean rightButtonPressed;
private boolean middleButtonPressed;
public MouseListener(long window) {
previousPos = new Vector2f(-1,-1);
currentPos = new Vector2f();
deltaPos = new Vector2f();
leftButtonPressed = false;
rightButtonPressed = false;
FocusWindow = false;
glfwSetCursorPosCallback(window, (handle, xpos, ypos) -> {
currentPos.x = (float) xpos;
currentPos.y = (float) ypos;
});
glfwSetCursorEnterCallback(window, (handle, entered) -> FocusWindow = entered);
glfwSetMouseButtonCallback(window, (handle, button, action, mode) -> {
leftButtonPressed = button == GLFW_MOUSE_BUTTON_1 && action == GLFW_PRESS;
rightButtonPressed = button == GLFW_MOUSE_BUTTON_2 && action == GLFW_PRESS;
middleButtonPressed = button == GLFW_MOUSE_BUTTON_3 && action == GLFW_PRESS;
});
}
public Vector2f getCurrentPos() {
return currentPos;
}
public Vector2f getDeltaPos() {
return deltaPos;
}
public void input() {
deltaPos.x = 0;
deltaPos.y = 0;
if (previousPos.x >= 0 && previousPos.y >= 0 && FocusWindow) {
deltaPos.x = currentPos.x - previousPos.x;
deltaPos.y = currentPos.y - previousPos.y;
}
previousPos.x = currentPos.x;
previousPos.y = currentPos.y;
}
public boolean isLeftButtonPressed() {
return leftButtonPressed;
}
public boolean isRightButtonPressed() {
return rightButtonPressed;
}
public boolean isMiddleButtonPressed() {
return rightButtonPressed;
}
}

View file

@ -0,0 +1,10 @@
package net.halbear.Terrain4J.EngineCore.Logic;
import net.halbear.Terrain4J.EngineCore.Main.Scene;
import net.halbear.Terrain4J.EngineCore.Display.Window;
public record EngineInstance(Window window, Scene scene) {
public void cleanup(){
window.cleanup();
}
}

View file

@ -0,0 +1,8 @@
package net.halbear.Terrain4J.EngineCore.Logic;
public interface GameLogic {
void cleanup();
void Initialise(EngineInstance engineInstance);
void Input(EngineInstance engineInstance, long diffMS);
void Update(EngineInstance engineInstance, long diffMS);
}

View file

@ -0,0 +1,90 @@
package net.halbear.Terrain4J.EngineCore.Logic;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Properties;
import java.util.logging.Logger;
public class Globals {
private static final long DEFAULT_ACCURACY = 0;
private static final int DEFAULT_TICKRATE = 60;
private static final int DEFAULT_WIDTH = 640;
private static final int DEFAULT_HEIGHT = 480;
private static final String FILENAME = "terrain4j.properties";
private static Globals instance;
private long accuracy;
private int TickRate;
private int Width;
private int Height;
public static int FrameRate_PRIMARYTHREAD =0;
public static int TPS =0;
public static int FrameRate_MAINENGINETHREAD =0;
public static int FrameRate_RENDER =0;
public static int RENDERFRAMES =0;
public static boolean VSYNC = false;
private Globals() {
var EngineConfig = new Properties();
Path path = Paths.get("");
InputStream stream = Globals.class.getResourceAsStream(path.toAbsolutePath().toString() + "/" + FILENAME);
boolean SuccessfulLoad = false;
if (stream != null) {
try {
EngineConfig.load(stream);
SuccessfulLoad = true;
} catch (IOException excp) {
System.out.println(excp.getMessage());
}
}
if (SuccessfulLoad){
accuracy = Long.parseLong(EngineConfig.getOrDefault("frame_accuracy", DEFAULT_ACCURACY).toString());
TickRate = Integer.parseInt(EngineConfig.getOrDefault("main_tick_rate", DEFAULT_TICKRATE).toString());
Width = Integer.parseInt(EngineConfig.getOrDefault("display_width", DEFAULT_TICKRATE).toString());
Height = Integer.parseInt(EngineConfig.getOrDefault("display_height", DEFAULT_TICKRATE).toString());
VSYNC = Boolean.parseBoolean(EngineConfig.getOrDefault("vsync", false).toString());
try {
assert stream != null;
stream.close();
} catch(IOException excp) {
System.out.println(excp.getMessage());
}
} else{
try {
EngineConfig.setProperty("frame_accuracy", "0");
EngineConfig.setProperty("main_tick_rate", "60");
EngineConfig.setProperty("display_width", "640");
EngineConfig.setProperty("display_height", "480");
EngineConfig.setProperty("vsync", "false");
EngineConfig.store(new FileWriter(path.toAbsolutePath().toString() + "/" + FILENAME), "created new properties file");
} catch (IOException excp2) {
System.out.println(excp2.getMessage());
}
accuracy = DEFAULT_ACCURACY;
TickRate = DEFAULT_TICKRATE;
}
}
public static synchronized Globals getInstance() {
if (instance == null) {
instance = new Globals();
}
return instance;
}
public int getWidth(){
return Width;
}
public int getHeight(){
return Height;
}
public long getAccuracy() {
return accuracy;
}
public int getTickRate() {
return TickRate;
}
}

View file

@ -0,0 +1,26 @@
package net.halbear.Terrain4J.EngineCore.Main;
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
import net.halbear.Terrain4J.EngineCore.Logic.GameLogic;
public class GameCore implements GameLogic {
@Override
public void cleanup() {
}
@Override
public void Initialise(EngineInstance engineInstance) {
}
@Override
public void Input(EngineInstance engineInstance, long diffMS) {
}
@Override
public void Update(EngineInstance engineInstance, long diffMS) {
}
}

View file

@ -0,0 +1,74 @@
package net.halbear.Terrain4J.EngineCore.Main;
import net.halbear.Terrain4J.EngineCore.Display.Render;
import net.halbear.Terrain4J.EngineCore.Display.Window;
import net.halbear.Terrain4J.EngineCore.Logic.Globals;
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
import net.halbear.Terrain4J.EngineCore.Logic.GameLogic;
public class PrimaryRuntime {
private final EngineInstance engineInstance;
private final GameLogic gameLogic;
private final Render render;
private Window window;
private int Frames = 0;
private int TickFrames = 0;
public PrimaryRuntime(String windowTitle, GameLogic appLogic) {
this.gameLogic = appLogic;
window = new Window(windowTitle);
engineInstance = new EngineInstance(window, new Scene(window));
render = new Render(engineInstance);
gameLogic.Initialise(engineInstance);
}
private void cleanup() {
gameLogic.cleanup();
render.cleanup();
engineInstance.cleanup();
}
public EngineInstance getEngineInstance() {
return engineInstance;
}
public void run(){
long InitialTime = System.nanoTime();
long updateTime = InitialTime;
double FrameDiff =0;
double TickDiff =0;
double SecondCounter =0;
double tickDiff = 0;
while (!window.shouldClose()){
long now = System.nanoTime();
tickDiff = now - InitialTime;
FrameDiff += tickDiff;
TickDiff += tickDiff;
SecondCounter += tickDiff;
if (FrameDiff >= Globals.getInstance().getAccuracy()){
window.pollEvents();
gameLogic.Input(engineInstance, (now - InitialTime)/ 1000000);
Frames++;
if (TickDiff/1000 >= (double) 1000000 / (double)Globals.getInstance().getTickRate()) {
TickFrames++;
long nsTimeDiff = now - updateTime;
gameLogic.Update(engineInstance, nsTimeDiff / 1000000);
updateTime = now;
TickDiff = 0;
}
if (SecondCounter >= 1000000000){
SecondCounter = 0;
System.out.println("FPS: " + Frames + " Ticks: " + TickFrames);
Globals.FrameRate_PRIMARYTHREAD = Frames;
Globals.FrameRate_RENDER = Globals.RENDERFRAMES;
Globals.TPS = TickFrames;
Frames = 0;
TickFrames = 0;
Globals.RENDERFRAMES = 0;
}
render.render(engineInstance);
FrameDiff = 0;
}
InitialTime = now;
}
cleanup();
}
}

View file

@ -0,0 +1,8 @@
package net.halbear.Terrain4J.EngineCore.Main;
import net.halbear.Terrain4J.EngineCore.Display.Window;
public class Scene {
public Scene(Window window) {
}
}