Compare commits
10 Commits
9a4ef72765
...
c28ec45f8c
| Author | SHA1 | Date | |
|---|---|---|---|
| c28ec45f8c | |||
| f13d4e3902 | |||
| eb3a5e7dd1 | |||
| 9cf088cc6c | |||
| 42f162a03a | |||
| edff4b27db | |||
| 2a66ed1062 | |||
| 1b7b9e4ffd | |||
| 31d8cac12a | |||
| 38c5021090 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,3 +4,4 @@ target/
|
|||||||
|
|
||||||
.classpath
|
.classpath
|
||||||
.project
|
.project
|
||||||
|
.factorypath
|
||||||
|
|||||||
8
assets/shaders/default.frag.glsl
Normal file
8
assets/shaders/default.frag.glsl
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
in vec4 fColour;
|
||||||
|
out vec4 colour;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
colour = fColour;
|
||||||
|
}
|
||||||
11
assets/shaders/default.vert.glsl
Normal file
11
assets/shaders/default.vert.glsl
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout (location = 0) in vec3 aPos;
|
||||||
|
layout (location = 1) in vec4 aColour;
|
||||||
|
|
||||||
|
out vec4 fColour;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
fColour = aColour;
|
||||||
|
gl_Position = vec4(aPos, 1.0);
|
||||||
|
}
|
||||||
17
pom.xml
17
pom.xml
@@ -35,9 +35,20 @@
|
|||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>org.mockito</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>mockito-core</artifactId>
|
||||||
<version>3.8.1</version>
|
<version>5.19.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.18.38</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter</artifactId>
|
||||||
|
<version>5.13.4</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.lwjgl</groupId>
|
<groupId>org.lwjgl</groupId>
|
||||||
|
|||||||
37
src/main/java/org/hirw/game/Keyboard.java
Normal file
37
src/main/java/org/hirw/game/Keyboard.java
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package org.hirw.game;
|
||||||
|
|
||||||
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class Keyboard {
|
||||||
|
private static Keyboard instance;
|
||||||
|
private HashMap<Integer, Boolean> buttons;
|
||||||
|
|
||||||
|
private Keyboard() {
|
||||||
|
this.buttons = new HashMap<Integer, Boolean>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Keyboard getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
synchronized (Keyboard.class) {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new Keyboard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void keyCallback(long window, int keyCode, int _scan, int action, int _modifiers) {
|
||||||
|
if (action == GLFW_PRESS) {
|
||||||
|
getInstance().buttons.put(keyCode, true);
|
||||||
|
} else if (action == GLFW_RELEASE) {
|
||||||
|
getInstance().buttons.put(keyCode, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isPressed(int keyCode) {
|
||||||
|
return getInstance().buttons.getOrDefault(keyCode, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
67
src/main/java/org/hirw/game/Mouse.java
Normal file
67
src/main/java/org/hirw/game/Mouse.java
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
package org.hirw.game;
|
||||||
|
|
||||||
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class Mouse {
|
||||||
|
private double x, y, oldX, oldY;
|
||||||
|
private HashMap<Integer, Boolean> buttons;
|
||||||
|
|
||||||
|
private static Mouse instance;
|
||||||
|
|
||||||
|
public interface Buttons {
|
||||||
|
public final int LEFT = GLFW_MOUSE_BUTTON_LEFT;
|
||||||
|
public final int RIGHT = GLFW_MOUSE_BUTTON_RIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mouse() {
|
||||||
|
this.buttons = new HashMap<Integer, Boolean>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Mouse getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
synchronized (Mouse.class) { // Double checked locking
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new Mouse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void cursorPositionCallback(long window, double newX, double newY) {
|
||||||
|
getInstance().oldX = getInstance().x;
|
||||||
|
getInstance().oldY = getInstance().y;
|
||||||
|
getInstance().x = newX;
|
||||||
|
getInstance().y = newY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void mouseButtonCallback(long window, int keyCode, int action, int _modifiers) {
|
||||||
|
if (action == GLFW_PRESS) {
|
||||||
|
getInstance().buttons.put(keyCode, true);
|
||||||
|
} else if (action == GLFW_RELEASE) {
|
||||||
|
getInstance().buttons.put(keyCode, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getX() {
|
||||||
|
return getInstance().x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getY() {
|
||||||
|
return getInstance().y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getDeltaX() {
|
||||||
|
return getInstance().oldX - getInstance().x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getDeltaY() {
|
||||||
|
return getInstance().oldY - getInstance().y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isPressed(int keyCode) {
|
||||||
|
return getInstance().buttons.getOrDefault(keyCode, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/main/java/org/hirw/game/Scene.java
Normal file
8
src/main/java/org/hirw/game/Scene.java
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package org.hirw.game;
|
||||||
|
|
||||||
|
|
||||||
|
public abstract class Scene {
|
||||||
|
public Scene() {}
|
||||||
|
|
||||||
|
abstract void update();
|
||||||
|
}
|
||||||
20
src/main/java/org/hirw/game/SceneManager.java
Normal file
20
src/main/java/org/hirw/game/SceneManager.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package org.hirw.game;
|
||||||
|
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
final class SceneManager {
|
||||||
|
private static final EnumMap<SceneType, Scene> SCENES =
|
||||||
|
new EnumMap<>(
|
||||||
|
Map.of(
|
||||||
|
SceneType.SPLASH, new SplashScene(),
|
||||||
|
SceneType.MENU, new SplashScene(),
|
||||||
|
SceneType.GAME, new SplashScene()));
|
||||||
|
|
||||||
|
@Getter private static Scene scene = SCENES.get(SceneType.SPLASH);
|
||||||
|
|
||||||
|
public static void setScene(SceneType sType) {
|
||||||
|
scene = SCENES.get(sType);
|
||||||
|
}
|
||||||
|
}
|
||||||
7
src/main/java/org/hirw/game/SceneType.java
Normal file
7
src/main/java/org/hirw/game/SceneType.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package org.hirw.game;
|
||||||
|
|
||||||
|
public enum SceneType {
|
||||||
|
SPLASH,
|
||||||
|
MENU,
|
||||||
|
GAME
|
||||||
|
}
|
||||||
115
src/main/java/org/hirw/game/Shader.java
Normal file
115
src/main/java/org/hirw/game/Shader.java
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
package org.hirw.game;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL20.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.InvalidPathException;
|
||||||
|
import java.nio.file.NoSuchFileException;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.hirw.game.util.Log;
|
||||||
|
|
||||||
|
public class Shader {
|
||||||
|
private enum ShaderType {
|
||||||
|
FRAG,
|
||||||
|
VERT
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final EnumMap<ShaderType, Integer> SHADERS =
|
||||||
|
new EnumMap<>(
|
||||||
|
Map.of(
|
||||||
|
ShaderType.FRAG, GL_FRAGMENT_SHADER,
|
||||||
|
ShaderType.VERT, GL_VERTEX_SHADER));
|
||||||
|
|
||||||
|
private static final String DEFAULT_FRAG_PATH = "assets/shaders/default.frag.glsl";
|
||||||
|
private static final String DEFAULT_VERT_PATH = "assets/shaders/default.vert.glsl";
|
||||||
|
|
||||||
|
@Getter private String vertexSource;
|
||||||
|
@Getter private String fragmentSource;
|
||||||
|
@Getter @Setter private int vertexID;
|
||||||
|
@Getter @Setter private int fragmentID;
|
||||||
|
@Getter @Setter private int shaderProgramID;
|
||||||
|
|
||||||
|
public Shader(String fragPath, String vertPath) {
|
||||||
|
this.fragmentSource = readFromFile(fragPath);
|
||||||
|
this.vertexSource = readFromFile(vertPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Shader() {
|
||||||
|
this(DEFAULT_FRAG_PATH, DEFAULT_VERT_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
compileShader(ShaderType.FRAG);
|
||||||
|
compileShader(ShaderType.VERT);
|
||||||
|
createProgram();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void compileShader(ShaderType shaderType) {
|
||||||
|
int shaderID = glCreateShader(SHADERS.get(shaderType));
|
||||||
|
|
||||||
|
switch (shaderType) {
|
||||||
|
case ShaderType.FRAG -> {
|
||||||
|
setFragmentID(shaderID);
|
||||||
|
glShaderSource(shaderID, getFragmentSource());
|
||||||
|
}
|
||||||
|
case ShaderType.VERT -> {
|
||||||
|
setVertexID(shaderID);
|
||||||
|
glShaderSource(shaderID, getVertexSource());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glCompileShader(shaderID);
|
||||||
|
|
||||||
|
if (glGetShaderi(shaderID, GL_COMPILE_STATUS) == GL_FALSE) {
|
||||||
|
int len = glGetShaderi(shaderID, GL_INFO_LOG_LENGTH);
|
||||||
|
Log.error(
|
||||||
|
"Shader initialisation",
|
||||||
|
String.format(
|
||||||
|
"Failed to compile %s shader: %s",
|
||||||
|
shaderType.toString(), glGetShaderInfoLog(shaderID, len)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createProgram() {
|
||||||
|
setShaderProgramID(glCreateProgram());
|
||||||
|
glAttachShader(shaderProgramID, getVertexID());
|
||||||
|
glAttachShader(shaderProgramID, getFragmentID());
|
||||||
|
glLinkProgram(shaderProgramID);
|
||||||
|
|
||||||
|
int success = glGetProgrami(getShaderProgramID(), GL_LINK_STATUS);
|
||||||
|
if (success == GL_FALSE) {
|
||||||
|
int len = glGetProgrami(getShaderProgramID(), GL_INFO_LOG_LENGTH);
|
||||||
|
|
||||||
|
Log.error(
|
||||||
|
"Shader initialisation",
|
||||||
|
String.format(
|
||||||
|
"Failed to create Shader Program: %s",
|
||||||
|
glGetShaderInfoLog(getShaderProgramID(), len)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String readFromFile(String stringFilePath) {
|
||||||
|
String source = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
Path filePath = Paths.get(stringFilePath);
|
||||||
|
source = Files.readString(filePath);
|
||||||
|
|
||||||
|
} catch (NoSuchFileException | InvalidPathException e) {
|
||||||
|
Log.error(
|
||||||
|
"Shader initialisation", "Couldn't open file (probably a bad path): " + stringFilePath);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.error(
|
||||||
|
"Shader initialisation",
|
||||||
|
"An IO Exception occured while reading from file: " + stringFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/main/java/org/hirw/game/SplashScene.java
Normal file
19
src/main/java/org/hirw/game/SplashScene.java
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package org.hirw.game;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL11.*;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import org.hirw.game.util.Time;
|
||||||
|
|
||||||
|
public class SplashScene extends Scene {
|
||||||
|
private float ramp = 0.0f;
|
||||||
|
|
||||||
|
public void update() {
|
||||||
|
if (Objects.isNull(Window.get().getGlfwWindow())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glClearColor(this.ramp, this.ramp, this.ramp, 0.0f);
|
||||||
|
this.ramp += 0.5f * Time.deltaTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,19 +3,18 @@ package org.hirw.game;
|
|||||||
import static org.lwjgl.glfw.Callbacks.*;
|
import static org.lwjgl.glfw.Callbacks.*;
|
||||||
import static org.lwjgl.glfw.GLFW.*;
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
import static org.lwjgl.opengl.GL11.*;
|
import static org.lwjgl.opengl.GL11.*;
|
||||||
import static org.lwjgl.system.MemoryStack.*;
|
|
||||||
import static org.lwjgl.system.MemoryUtil.*;
|
import static org.lwjgl.system.MemoryUtil.*;
|
||||||
|
|
||||||
import java.nio.*;
|
import lombok.Getter;
|
||||||
|
import org.hirw.game.util.Time;
|
||||||
import org.lwjgl.Version;
|
import org.lwjgl.Version;
|
||||||
import org.lwjgl.glfw.*;
|
import org.lwjgl.glfw.*;
|
||||||
import org.lwjgl.opengl.*;
|
import org.lwjgl.opengl.*;
|
||||||
import org.lwjgl.system.*;
|
|
||||||
|
|
||||||
public class Window {
|
public class Window {
|
||||||
private int width, height;
|
private int width, height;
|
||||||
private final String title;
|
private final String title;
|
||||||
private long glfwWindow;
|
@Getter private long glfwWindow;
|
||||||
|
|
||||||
private static Window window = null;
|
private static Window window = null;
|
||||||
|
|
||||||
@@ -34,7 +33,6 @@ public class Window {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void blastOff() {
|
public void blastOff() {
|
||||||
logVersion();
|
|
||||||
setup();
|
setup();
|
||||||
loop();
|
loop();
|
||||||
cleanUp();
|
cleanUp();
|
||||||
@@ -45,6 +43,8 @@ public class Window {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setup() {
|
private void setup() {
|
||||||
|
logVersion();
|
||||||
|
|
||||||
GLFWErrorCallback.createPrint(System.err).set();
|
GLFWErrorCallback.createPrint(System.err).set();
|
||||||
if (!glfwInit()) throw new IllegalStateException("Unable to initialize GLFW");
|
if (!glfwInit()) throw new IllegalStateException("Unable to initialize GLFW");
|
||||||
|
|
||||||
@@ -69,18 +69,25 @@ public class Window {
|
|||||||
// GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
|
// GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
glfwSetCursorPosCallback(glfwWindow, Mouse::cursorPositionCallback);
|
||||||
|
glfwSetMouseButtonCallback(glfwWindow, Mouse::mouseButtonCallback);
|
||||||
|
glfwSetKeyCallback(glfwWindow, Keyboard::keyCallback);
|
||||||
|
|
||||||
glfwSetWindowTitle(glfwWindow, this.title);
|
glfwSetWindowTitle(glfwWindow, this.title);
|
||||||
glfwMakeContextCurrent(glfwWindow);
|
glfwMakeContextCurrent(glfwWindow);
|
||||||
glfwSwapInterval(1);
|
glfwSwapInterval(1);
|
||||||
glfwShowWindow(glfwWindow);
|
glfwShowWindow(glfwWindow);
|
||||||
|
|
||||||
GL.createCapabilities();
|
GL.createCapabilities();
|
||||||
|
glClearColor(0.0f, 0.0f, 2.0f, 0.0f);
|
||||||
|
Shader someShader = new Shader();
|
||||||
|
someShader.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loop() {
|
private void loop() {
|
||||||
// GL.createCapabilities(); // Does this maybe go in here?
|
|
||||||
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
|
|
||||||
|
|
||||||
while (!glfwWindowShouldClose(glfwWindow)) {
|
while (!glfwWindowShouldClose(glfwWindow)) {
|
||||||
|
Time.update();
|
||||||
|
SceneManager.getScene().update();
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
glfwSwapBuffers(glfwWindow);
|
glfwSwapBuffers(glfwWindow);
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
|||||||
35
src/main/java/org/hirw/game/util/Log.java
Normal file
35
src/main/java/org/hirw/game/util/Log.java
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package org.hirw.game.util;
|
||||||
|
|
||||||
|
public final class Log {
|
||||||
|
private interface Colours {
|
||||||
|
final String BLACK = "\u001B[30m";
|
||||||
|
final String BLACK_BG = "\u001B[40m";
|
||||||
|
final String RED = "\u001B[31m";
|
||||||
|
final String RED_BG = "\u001B[41m";
|
||||||
|
final String GREEN = "\u001B[32m";
|
||||||
|
final String GREEN_BG = "\u001B[42m";
|
||||||
|
final String YELLOW = "\u001B[33m";
|
||||||
|
final String YELLOW_BG = "\u001B[43m";
|
||||||
|
final String BLUE = "\u001B[34m";
|
||||||
|
final String PURPLE_BG = "\u001B[45m";
|
||||||
|
final String CYAN = "\u001B[36m";
|
||||||
|
final String CYAN_BG = "\u001B[46m";
|
||||||
|
final String WHITE = "\u001B[37m";
|
||||||
|
final String WHITE_BG = "\u001B[47m";
|
||||||
|
final String ANSI_RESET = "\u001B[0m";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void error(String errorStage, String errorDescription) {
|
||||||
|
String fancyError = String.format("[%s] ", colourisedString(Colours.RED, "ERROR"));
|
||||||
|
String fancyErrorStage = colourisedString(Colours.YELLOW, String.format("<%s> ", errorStage));
|
||||||
|
System.err.println(fancyError + fancyErrorStage + errorDescription);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String colourisedString(String colour, String string) {
|
||||||
|
return colour + string + Colours.ANSI_RESET;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String colourisedString(String colour, String otherColour, String string) {
|
||||||
|
return colour + otherColour + string + Colours.ANSI_RESET;
|
||||||
|
}
|
||||||
|
}
|
||||||
31
src/main/java/org/hirw/game/util/Time.java
Normal file
31
src/main/java/org/hirw/game/util/Time.java
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package org.hirw.game.util;
|
||||||
|
|
||||||
|
public final class Time {
|
||||||
|
private static long lastTime = NanoTimer.system().nanoTime();
|
||||||
|
private static long currentTime = NanoTimer.system().nanoTime();
|
||||||
|
private static NanoTimer nanoTimer = NanoTimer.system();
|
||||||
|
|
||||||
|
public interface NanoTimer {
|
||||||
|
long nanoTime();
|
||||||
|
|
||||||
|
static NanoTimer system() {
|
||||||
|
return System::nanoTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setNanoTimer(NanoTimer timer) {
|
||||||
|
nanoTimer = timer;
|
||||||
|
lastTime = nanoTimer.nanoTime();
|
||||||
|
currentTime = nanoTimer.nanoTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void update() {
|
||||||
|
lastTime = currentTime;
|
||||||
|
currentTime = nanoTimer.nanoTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float deltaTime() {
|
||||||
|
final float ONE_SECOND = 1_000_000_000f;
|
||||||
|
return (currentTime - lastTime) / ONE_SECOND;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
package org.hirw.game;
|
|
||||||
|
|
||||||
import junit.framework.Test;
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
import junit.framework.TestSuite;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unit test for simple App.
|
|
||||||
*/
|
|
||||||
public class AppTest
|
|
||||||
extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Create the test case
|
|
||||||
*
|
|
||||||
* @param testName name of the test case
|
|
||||||
*/
|
|
||||||
public AppTest( String testName )
|
|
||||||
{
|
|
||||||
super( testName );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the suite of tests being tested
|
|
||||||
*/
|
|
||||||
public static Test suite()
|
|
||||||
{
|
|
||||||
return new TestSuite( AppTest.class );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rigourous Test :-)
|
|
||||||
*/
|
|
||||||
public void testApp()
|
|
||||||
{
|
|
||||||
assertTrue( true );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
64
src/test/java/org/hirw/game/util/TimeTest.java
Normal file
64
src/test/java/org/hirw/game/util/TimeTest.java
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package org.hirw.game.util;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
class TimeTest {
|
||||||
|
final float ONE_SECOND = 1_000_000_000f;
|
||||||
|
final long ONE_MILLISECOND = 1_000_000L;
|
||||||
|
final float MOE = 0.00000001f; // Margin of error
|
||||||
|
|
||||||
|
private Time.NanoTimer nanoTimer;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
nanoTimer = Mockito.mock(Time.NanoTimer.class);
|
||||||
|
when(nanoTimer.nanoTime()).thenReturn(0L);
|
||||||
|
Time.setNanoTimer(nanoTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeltaTimeInitialState() {
|
||||||
|
float deltaTime = Time.deltaTime();
|
||||||
|
assertEquals(deltaTime, 0f, MOE, "should be 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeltaTimeAfterUpdate() {
|
||||||
|
when(nanoTimer.nanoTime()).thenReturn(ONE_MILLISECOND);
|
||||||
|
|
||||||
|
Time.update();
|
||||||
|
float deltaTime = Time.deltaTime();
|
||||||
|
|
||||||
|
assertEquals(deltaTime, ONE_MILLISECOND / ONE_SECOND, MOE, "should reflect time difference");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testMultipleUpdates() {
|
||||||
|
when(nanoTimer.nanoTime()).thenReturn(ONE_MILLISECOND).thenReturn(ONE_MILLISECOND * 4);
|
||||||
|
|
||||||
|
Time.update();
|
||||||
|
float delta1 = Time.deltaTime();
|
||||||
|
|
||||||
|
Time.update();
|
||||||
|
float delta2 = Time.deltaTime();
|
||||||
|
|
||||||
|
assertEquals(delta1, ONE_MILLISECOND / ONE_SECOND, MOE, "should be 1/1000th second");
|
||||||
|
assertEquals(delta2, (ONE_MILLISECOND * 3) / ONE_SECOND, MOE, "should be 3/1000th second");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testConsistentStateAcrossCalls() {
|
||||||
|
when(nanoTimer.nanoTime()).thenReturn(ONE_MILLISECOND);
|
||||||
|
|
||||||
|
Time.update();
|
||||||
|
float delta1 = Time.deltaTime();
|
||||||
|
float delta2 = Time.deltaTime();
|
||||||
|
|
||||||
|
assertEquals(delta1, delta2, MOE, "should be equal delta time");
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user