Compare commits

..

8 Commits

19 changed files with 378 additions and 64 deletions

View File

@@ -0,0 +1,10 @@
#version 330 core
in vec4 fColour;
out vec4 colour;
uniform float u_alpha;
void main() {
colour = vec4(fColour.xyz, 1.0 - u_alpha);
}

View File

@@ -0,0 +1,19 @@
#version 330 core
out vec4 FragColour;
in vec4 ourColour;
in vec2 TexCoord;
uniform sampler2D texture1;
uniform sampler2D texture2;
void main()
{
vec4 tex1Color = texture(texture1, TexCoord);
vec4 tex2Color = texture(texture2, TexCoord);
if (tex2Color.a < 0.1)
tex2Color = tex1Color;
FragColour = mix(tex1Color, tex2Color, 0.4f);
}

View File

@@ -0,0 +1,15 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec4 aColour;
layout (location = 2) in vec2 aTexCoord;
out vec4 ourColour;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(aPos, 1.0);
ourColour = aColour;
TexCoord = aTexCoord;
}

BIN
assets/textures/flames.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

BIN
assets/textures/plink.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
assets/textures/plink.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View File

@@ -10,7 +10,6 @@
<name>game</name> <name>game</name>
<description>A simple game.</description> <description>A simple game.</description>
<!-- FIXME change it to the project's website -->
<url>http://www.hirw.org</url> <url>http://www.hirw.org</url>
<properties> <properties>

View File

@@ -0,0 +1,58 @@
package org.hirw.game;
import static org.lwjgl.opengl.GL20.*;
import lombok.Getter;
import lombok.Setter;
import org.hirw.game.util.Log;
import org.hirw.game.util.Time;
public class FaderShader extends Shader {
private static final String FADER_SHADER_FRAG_PATH = "assets/shaders/fader.frag.glsl";
private static final float DEFAULT_ALPHA_INCREASE_STEP = 1.0f / 3;
private final float INITIAL_ALPHA = 0.0f;
@Getter private final float alphaIncreaseStep;
@Getter @Setter private float alpha;
@Getter @Setter private int alphaUniformLocation;
public FaderShader(float alphaIncreaseStep) {
super(FADER_SHADER_FRAG_PATH, DEFAULT_VERT_PATH);
this.alpha = INITIAL_ALPHA;
this.alphaIncreaseStep = alphaIncreaseStep;
}
public FaderShader() {
this(DEFAULT_ALPHA_INCREASE_STEP);
}
public void init() {
super.init();
findAlphaUniformLocation();
}
public void update() {
super.update();
increaseAlpha();
}
private void findAlphaUniformLocation() {
int location = glGetUniformLocation(getShaderProgramID(), "u_alpha");
if (location == -1) {
Log.warning("FaderShader", "Failed to get 'u_alpha' uniform location, trying to continue...");
} else {
setAlphaUniformLocation(location);
}
}
private void increaseAlpha() {
if (getAlphaUniformLocation() == -1) return;
if (getAlpha() >= 1.0f) return;
setAlpha(getAlpha() + (getAlphaIncreaseStep() * Time.deltaTime()));
glUseProgram(getShaderProgramID());
glUniform1f(getAlphaUniformLocation(), getAlpha());
glUseProgram(0);
}
}

View File

@@ -12,18 +12,22 @@ import org.lwjgl.BufferUtils;
public class Mesh { public class Mesh {
@Getter @Setter private int vaoID, vboID, eboID; @Getter @Setter private int vaoID, vboID, eboID;
@Getter private Shader shader; @Getter protected Shader shader;
@Getter float[] vertices; @Getter float[] vertices;
@Getter int[] elements; @Getter int[] elements;
private static final float[] defaultVertexArray = { protected final int POSITION_SIZE = 3;
protected final int RGBA_SIZE = 4;
protected final int FLOAT_SIZE_IN_BYTES = Float.SIZE / Byte.SIZE;
protected static final float[] DEFAULT_VERTEX_ARRAY = {
0.5f, -0.5f, 0.0f, /* */ 1.0f, 0.0f, 0.0f, 1.0f, 0.5f, -0.5f, 0.0f, /* */ 1.0f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.0f, /* */ 0.0f, 1.0f, 0.0f, 1.0f, -0.5f, 0.5f, 0.0f, /* */ 0.0f, 1.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.0f, /* */ 0.0f, 0.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.0f, /* */ 0.0f, 0.0f, 1.0f, 1.0f,
-0.5f, -0.5f, 0.0f, /* */ 1.0f, 1.0f, 0.0f, 1.0f, -0.5f, -0.5f, 0.0f, /* */ 1.0f, 1.0f, 0.0f, 1.0f,
}; };
private static final int[] defaultElementArray = { protected static final int[] DEFAULT_ELEMENT_ARRAY = {
2, 1, 0, 2, 1, 0,
0, 1, 3 0, 1, 3
}; };
@@ -38,7 +42,7 @@ public class Mesh {
} }
public Mesh(Shader shader) { public Mesh(Shader shader) {
this(shader, defaultVertexArray, defaultElementArray); this(shader, DEFAULT_VERTEX_ARRAY, DEFAULT_ELEMENT_ARRAY);
} }
public void init() { public void init() {
@@ -61,7 +65,7 @@ public class Mesh {
getEboID(), getVboID(), getEboID(), getShader().getShaderProgramID()); getEboID(), getVboID(), getEboID(), getShader().getShaderProgramID());
} }
private void glDraw() { protected void glDraw() {
glBindVertexArray(this.vaoID); glBindVertexArray(this.vaoID);
glDrawElements(GL_TRIANGLES, getElements().length, GL_UNSIGNED_INT, 0); glDrawElements(GL_TRIANGLES, getElements().length, GL_UNSIGNED_INT, 0);
glBindVertexArray(0); glBindVertexArray(0);
@@ -74,16 +78,24 @@ public class Mesh {
initialiseVertexBufferObject(); initialiseVertexBufferObject();
initialiseElementBufferObject(); initialiseElementBufferObject();
int positionsSize = 3; initialiseAttribPointers();
int colourSize = 4; }
int floatSizeBytes = 4;
int vertexSizeBytes = (positionsSize + colourSize) * floatSizeBytes; protected int initialiseAttribPointers() {
glVertexAttribPointer(0, positionsSize, GL_FLOAT, false, vertexSizeBytes, 0); int vertexSizeInBytes = calculateVertexSizeInBytes();
glVertexAttribPointer(0, POSITION_SIZE, GL_FLOAT, false, vertexSizeInBytes, 0);
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glVertexAttribPointer( glVertexAttribPointer(
1, colourSize, GL_FLOAT, false, vertexSizeBytes, positionsSize * floatSizeBytes); 1, RGBA_SIZE, GL_FLOAT, false, vertexSizeInBytes, POSITION_SIZE * FLOAT_SIZE_IN_BYTES);
glEnableVertexAttribArray(1); glEnableVertexAttribArray(1);
return vertexSizeInBytes;
}
protected int calculateVertexSizeInBytes() {
return (POSITION_SIZE + RGBA_SIZE) * FLOAT_SIZE_IN_BYTES;
} }
private void initialiseVertexBufferObject() { private void initialiseVertexBufferObject() {

View File

@@ -1,15 +1,19 @@
package org.hirw.game; package org.hirw.game;
public abstract class Scene { import lombok.Getter;
public final SceneType SCENE_TYPE = SceneType.UNDEFINED;
public Scene() {} public abstract class Scene {
@Getter private final SceneType sceneType;
public Scene(SceneType sceneType) {
this.sceneType = sceneType;
}
public abstract void init(); public abstract void init();
public abstract void update(); public abstract void update();
public String toString() { public String toString() {
return SCENE_TYPE.toString(); return getSceneType().toString();
} }
} }

View File

@@ -15,32 +15,42 @@ public final class SceneManager {
SceneType.MENU, new SplashScene(), SceneType.MENU, new SplashScene(),
SceneType.GAME, new SplashScene())); SceneType.GAME, new SplashScene()));
@Getter private static Scene scene = SCENES.get(DEFAULT_SCENE_TYPE); @Getter private static Scene scene;
public static void init() { public static void init() {
setScene(DEFAULT_SCENE_TYPE); setScene(DEFAULT_SCENE_TYPE);
} }
public static void setScene(SceneType sceneType) { public static void setScene(SceneType sceneType) {
scene = SCENES.get(sceneType); Scene newScene = SCENES.get(sceneType);
if (scene == newScene) {
Log.warning("SceneManager", sameSceneWarningString());
return;
} else {
scene = newScene;
}
scene.init(); scene.init();
logSceneChange(); logSceneChange();
} }
public static void update() { public static void update() {
if (scene.SCENE_TYPE == SceneType.UNDEFINED) return; if (scene.getSceneType() == null) return;
getScene().update(); getScene().update();
} }
private static void logSceneChange() { private static void logSceneChange() {
SceneType newSceneType = getScene().SCENE_TYPE; SceneType newSceneType = getScene().getSceneType();
String loadedSceneMessage = String.format("Changed to scene '%s'", newSceneType.toString()); String loadedSceneMessage = String.format("Changed to scene '%s'", newSceneType.toString());
if (newSceneType == SceneType.UNDEFINED) {
Log.warning("SceneManager", loadedSceneMessage);
} else {
Log.success("SceneManager", loadedSceneMessage); Log.success("SceneManager", loadedSceneMessage);
} }
private static String sameSceneWarningString() {
return String.format(
"Tried to switch to scene '%s' but that scene is already loaded",
scene.getSceneType().toString());
} }
} }

View File

@@ -1,7 +1,6 @@
package org.hirw.game; package org.hirw.game;
public enum SceneType { public enum SceneType {
UNDEFINED,
SPLASH, SPLASH,
MENU, MENU,
GAME, GAME,

View File

@@ -26,8 +26,8 @@ public class Shader {
ShaderType.FRAG, GL_FRAGMENT_SHADER, ShaderType.FRAG, GL_FRAGMENT_SHADER,
ShaderType.VERT, GL_VERTEX_SHADER)); ShaderType.VERT, GL_VERTEX_SHADER));
private static final String DEFAULT_FRAG_PATH = "assets/shaders/default.frag.glsl"; protected static final String DEFAULT_FRAG_PATH = "assets/shaders/default.frag.glsl";
private static final String DEFAULT_VERT_PATH = "assets/shaders/default.vert.glsl"; protected static final String DEFAULT_VERT_PATH = "assets/shaders/default.vert.glsl";
@Getter private String vertexSource; @Getter private String vertexSource;
@Getter private String fragmentSource; @Getter private String fragmentSource;
@@ -40,6 +40,10 @@ public class Shader {
this.vertexSource = readFromFile(vertPath); this.vertexSource = readFromFile(vertPath);
} }
public Shader(String path) {
this(path + ".frag.glsl", path + ".vert.glsl");
}
public Shader() { public Shader() {
this(DEFAULT_FRAG_PATH, DEFAULT_VERT_PATH); this(DEFAULT_FRAG_PATH, DEFAULT_VERT_PATH);
} }
@@ -58,6 +62,8 @@ public class Shader {
glUseProgram(0); glUseProgram(0);
} }
public void update() {}
private void compileShader(ShaderType shaderType) { private void compileShader(ShaderType shaderType) {
int shaderID = glCreateShader(SHADERS.get(shaderType)); int shaderID = glCreateShader(SHADERS.get(shaderType));

View File

@@ -1,53 +1,72 @@
package org.hirw.game; package org.hirw.game;
import static org.lwjgl.opengl.GL11.*;
import java.util.Objects;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.hirw.game.util.Time;
public class SplashScene extends Scene { public class SplashScene extends Scene {
@Getter public final SceneType SCENE_TYPE = SceneType.SPLASH; @Getter public final SceneType SCENE_TYPE = SceneType.SPLASH;
private final float INITIAL_BRIGHTNESS = 0.0f;
private final float FADE_RATE = 0.5f;
private float brightness;
@Getter @Setter private Mesh screenCover; @Getter @Setter private Mesh screenCover;
@Getter @Setter private FaderShader screenCoverFaderShader;
@Getter @Setter private Mesh logo;
public SplashScene() { public SplashScene() {
this.brightness = INITIAL_BRIGHTNESS; super(SceneType.SPLASH);
} }
public void init() { public void init() {
Shader faderShader = new Shader(); createScreenCover();
faderShader.init(); createLogo();
Mesh screenCover = new Mesh(faderShader);
screenCover.init();
setScreenCover(screenCover);
} }
public void update() { public void update() {
if (Objects.isNull(Window.get().getGlfwWindow())) { getLogo().draw();
return; getScreenCoverFaderShader().update();
getScreenCover().draw();
} }
screenCover.draw(); private void createScreenCover() {
FaderShader faderShader = new FaderShader();
fadeIn(); faderShader.init();
Mesh screenCover = new Mesh(faderShader, screenCoverRectVertices, screenCoverRectElements);
screenCover.init();
setScreenCoverFaderShader(faderShader);
setScreenCover(screenCover);
} }
private void fadeIn() { private void createLogo() {
glClearColor(this.brightness, this.brightness, this.brightness, 0.0f); Shader texturedShader = new Shader("assets/shaders/texture");
final float fadeAmount = FADE_RATE * Time.deltaTime(); texturedShader.init();
this.brightness += fadeAmount; Texture logoTexture = new Texture(225, 225, "assets/textures/plink.png");
Texture flameTexture = new Texture(2500, 2500, "assets/textures/flames.png");
logoTexture.init();
flameTexture.init();
Mesh logoMesh =
new TexturedMesh(
texturedShader,
new Texture[] {logoTexture, flameTexture},
logoRectVertices,
screenCoverRectElements);
logoMesh.init();
setLogo(logoMesh);
} }
private static final float[] screenCoverRect = { private static final float[] screenCoverRectVertices = {
1.0f, -0.0f, 0.0f, /* */ 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, /* */ 0.0f, 0.0f, 0.0f, 0.0f, // 0 Top Right
-0.0f, 1.0f, 0.0f, /* */ 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 0.0f, /* */ 0.0f, 0.0f, 0.0f, 0.0f, // 1 Bottom Right
1.0f, 1.0f, 0.0f, /* */ 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, -1.0f, 0.0f, /* */ 0.0f, 0.0f, 0.0f, 0.0f, // 2 Bottom Left
-1.0f, -1.0f, 0.0f, /* */ 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, /* */ 0.0f, 0.0f, 0.0f, 0.0f, // 3 Top Left
};
private static final int[] screenCoverRectElements = {
0, 1, 3,
1, 2, 3
};
private static final float[] logoRectVertices = {
0.1f, 0.1f, 0.0f, /* */ 0.0f, 0.0f, 0.0f, 0.0f, /* */ 1.0f, 1.0f, // 0 Top Right
0.1f, -0.1f, 0.0f, /* */ 0.0f, 0.0f, 0.0f, 0.0f, /* */ 1.0f, 0.0f, // 1 Bottom Right
-0.1f, -0.1f, 0.0f, /* */ 0.0f, 0.0f, 0.0f, 0.0f, /* */ 0.0f, 0.0f, // 2 Bottom Left
-0.1f, 0.1f, 0.0f, /* */ 0.0f, 0.0f, 0.0f, 0.0f, /* */ 0.0f, 1.0f, // 3 Top Left
}; };
} }

View File

@@ -0,0 +1,105 @@
package org.hirw.game;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL12.*;
import static org.lwjgl.stb.STBImage.stbi_image_free;
import static org.lwjgl.stb.STBImage.stbi_load;
import static org.lwjgl.stb.STBImage.stbi_set_flip_vertically_on_load;
import java.nio.ByteBuffer;
import lombok.Getter;
import lombok.Setter;
public class Texture {
@Getter private int width;
@Getter private int height;
@Getter private String texturePath;
@Getter @Setter private int textureID;
@Getter @Setter private int channelCount;
@Getter @Setter private int internalFormat;
public Texture(int width, int height, String texturePath) {
this.width = width;
this.height = height;
this.texturePath = texturePath;
guessChannelCountAndInternalFormat();
}
private void guessChannelCountAndInternalFormat() {
int fileExtensionIndex = getTexturePath().lastIndexOf(".");
if (fileExtensionIndex == -1) {
// No file extension, so just assume 4 channels (.png -> RGBA)
setChannelCount(4);
setInternalFormat(GL_RGBA);
return;
}
String fileExtension = getTexturePath().substring(fileExtensionIndex + 1);
switch (fileExtension) {
case "png":
setChannelCount(4);
setInternalFormat(GL_RGBA);
break;
case "jpg":
setChannelCount(3);
setInternalFormat(GL_RGB);
break;
default:
// just pray at this point
setChannelCount(3);
setInternalFormat(GL_RGB);
}
}
public void init() {
ByteBuffer imageBytes = loadImageBytes();
createTexture(imageBytes);
stbi_image_free(imageBytes);
}
private ByteBuffer loadImageBytes() {
stbi_set_flip_vertically_on_load(true);
return stbi_load(
getTexturePath(),
new int[getWidth()],
new int[getHeight()],
new int[getChannelCount()],
getChannelCount());
}
private void createTexture(ByteBuffer imageBytes) {
setTextureID(glGenTextures());
glBindTexture(GL_TEXTURE_2D, getTextureID());
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
setupFilterParameters();
setupWrapParameters();
glTexImage2D(
GL_TEXTURE_2D,
0,
getInternalFormat(),
getWidth(),
getHeight(),
0,
getInternalFormat(),
GL_UNSIGNED_BYTE,
imageBytes);
// glGenerateMipmap(GL_TEXTURE_2D);
}
private void setupFilterParameters() {
// https://github.com/mattdesl/lwjgl-basics/wiki/textures#texture-parameters
// Set the minification and Magnifiation filters:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
private void setupWrapParameters() {
// https://github.com/mattdesl/lwjgl-basics/wiki/textures#texture-parameters
// Each Vertex has many attributes, including Position (x, y) and Texture Coordinates (s, t).
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
}

View File

@@ -0,0 +1,47 @@
package org.hirw.game;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL20.*;
import lombok.Getter;
public class TexturedMesh extends Mesh {
@Getter private Texture[] textures;
private final int TEXTURE_COORDS_SIZE = 2;
public TexturedMesh(Shader shader, Texture[] textures, float[] vertexArray, int[] elementArray) {
super(shader, vertexArray, elementArray);
this.textures = textures;
}
public TexturedMesh(Shader shader, Texture[] textures) {
this(shader, textures, DEFAULT_VERTEX_ARRAY, DEFAULT_ELEMENT_ARRAY);
}
protected int initialiseAttribPointers() {
int vertexSizeInBytes = super.initialiseAttribPointers();
int offset = (POSITION_SIZE + RGBA_SIZE) * FLOAT_SIZE_IN_BYTES;
glVertexAttribPointer(2, TEXTURE_COORDS_SIZE, GL_FLOAT, false, vertexSizeInBytes, offset);
glEnableVertexAttribArray(2);
return vertexSizeInBytes;
}
protected int calculateVertexSizeInBytes() {
return (POSITION_SIZE + RGBA_SIZE + TEXTURE_COORDS_SIZE) * FLOAT_SIZE_IN_BYTES;
}
protected void glDraw() {
for (int i = 0; i < textures.length; i++) {
int textureUnitIndexStart = GL_TEXTURE0;
int textureUnitIndex = textureUnitIndexStart + i;
glActiveTexture(textureUnitIndex);
glBindTexture(GL_TEXTURE_2D, getTextures()[i].getTextureID());
String uniformName = "texture" + Integer.toString(i + 1);
glUniform1i(glGetUniformLocation(getShader().getShaderProgramID(), uniformName), i);
}
super.glDraw();
}
}

View File

@@ -14,7 +14,7 @@ import org.lwjgl.opengl.*;
public class Window { public class Window {
private int width, height; private int width, height;
private final String title; @Getter private String title;
@Getter private long glfwWindow; @Getter private long glfwWindow;
private static Window window = null; private static Window window = null;
@@ -61,7 +61,7 @@ public class Window {
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
glfwWindow = glfwCreateWindow(this.width, this.height, "Hello World!", NULL, NULL); glfwWindow = glfwCreateWindow(this.width, this.height, getTitle(), NULL, NULL);
if (glfwWindow == NULL) throw new RuntimeException("Failed to create the GLFW window"); if (glfwWindow == NULL) throw new RuntimeException("Failed to create the GLFW window");
glfwSetCursorPosCallback(glfwWindow, Mouse::cursorPositionCallback); glfwSetCursorPosCallback(glfwWindow, Mouse::cursorPositionCallback);
@@ -74,7 +74,13 @@ public class Window {
glfwShowWindow(glfwWindow); glfwShowWindow(glfwWindow);
GL.createCapabilities(); GL.createCapabilities();
glClearColor(0.0f, 0.0f, 2.0f, 0.0f);
glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
} }
private void createShader() { private void createShader() {
@@ -87,15 +93,14 @@ public class Window {
Mesh mesh = new Mesh(getShader()); Mesh mesh = new Mesh(getShader());
setMesh(mesh); setMesh(mesh);
mesh.init(); mesh.init();
mesh.log();
} }
private void loop() { private void loop() {
while (!glfwWindowShouldClose(glfwWindow)) { while (!glfwWindowShouldClose(glfwWindow)) {
Time.update(); Time.update();
SceneManager.update();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
getMesh().draw(); getMesh().draw();
SceneManager.update();
glfwSwapBuffers(glfwWindow); glfwSwapBuffers(glfwWindow);
glfwPollEvents(); glfwPollEvents();
} }

View File

@@ -29,7 +29,8 @@ public final class Log {
Map.of( Map.of(
LogType.SUCCESS, Colours.GREEN, LogType.SUCCESS, Colours.GREEN,
LogType.ERROR, Colours.RED, LogType.ERROR, Colours.RED,
LogType.WARNING, Colours.PURPLE)); LogType.WARNING, Colours.PURPLE,
LogType.DEBUG, Colours.WHITE));
public static void error(String errorStage, String errorDescription) { public static void error(String errorStage, String errorDescription) {
System.out.println(formatString(LogType.ERROR, errorStage, errorDescription)); System.out.println(formatString(LogType.ERROR, errorStage, errorDescription));
@@ -43,6 +44,10 @@ public final class Log {
System.out.println(formatString(LogType.WARNING, warningStage, warningDescription)); System.out.println(formatString(LogType.WARNING, warningStage, warningDescription));
} }
public static void debug(String debugMessage) {
System.out.println(formatString(LogType.DEBUG, "DEBUG", debugMessage));
}
private static String formatString(LogType logType, String stage, String description) { private static String formatString(LogType logType, String stage, String description) {
String formattedType = String.format("[%s]", colouriseString(logType, logType.toString())); String formattedType = String.format("[%s]", colouriseString(logType, logType.toString()));
String formattedStage = colouriseString(Colours.YELLOW, String.format("<%s>", stage)); String formattedStage = colouriseString(Colours.YELLOW, String.format("<%s>", stage));

View File

@@ -4,4 +4,5 @@ public enum LogType {
SUCCESS, SUCCESS,
WARNING, WARNING,
ERROR, ERROR,
DEBUG,
} }