Project as is

This commit is contained in:
Gnarwhal 2024-08-07 04:26:50 +00:00
commit 085ca8b7ee
Signed by: Gnarwhal
GPG key ID: 0989A73D8C421174
15 changed files with 744 additions and 0 deletions

BIN
res/img/Spring 1.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

BIN
res/img/Spring 2.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B

BIN
res/img/Spring 3.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

BIN
res/img/Spring 4.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 B

BIN
res/img/Stone Block.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

11
res/shaders/frag.fs Executable file
View file

@ -0,0 +1,11 @@
#version 330
uniform sampler2D sampler;
in vec2 tex;
layout (location = 0) out vec4 color;
void main() {
color = texture(sampler, tex);
}

14
res/shaders/vert.vs Executable file
View file

@ -0,0 +1,14 @@
# version 330
uniform mat4 pr_matrix;
uniform mat4 vw_matrix;
in vec3 verts;
in vec2 texts;
out vec2 tex;
void main() {
tex = texts;
gl_Position = pr_matrix * vw_matrix * vec4(verts, 1.0);
}

View file

@ -0,0 +1,118 @@
package com.gnarly.engine;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import com.gnarly.engine.graphics.*;
import com.gnarly.game.Main;
public class GameObject {
float velX = 0.0f;
float velY = 0.0f;
float accelX = 0.0f;
float accelY = 0.0f;
boolean solid;
Vector3f position;
Vector3f size;
float rotation;
float mass;
float friction;
Animation anim;
public static Matrix4f projection;
public GameObject(String texPath, Shader shader) {
anim = new Animation(texPath, shader, 1, 0, false);
}
public GameObject(String texPath, Shader shader, int numFrames, int numberUpdates, boolean loop) {
anim = new Animation(texPath, shader, numFrames, numberUpdates, loop);
}
public GameObject(Animation anim) {
this.anim = anim;
}
public GameObject newInstanceOf(float x, float y, float z, float rotation, float scale, float mass, float friction, boolean solid) {
GameObject ret = new GameObject(anim);
ret.setVars(x, y, z, rotation, scale, mass, friction, solid);
return ret;
}
public void setVars(float x, float y, float z, float rotation, float scale, float mass, float friction, boolean solid) {
position = new Vector3f(x, y, z);
this.rotation = rotation;
size = new Vector3f(scale, scale, 0.0f);
this.solid = solid;
this.mass = mass > 0 ? mass : 1.0f;
this.friction = friction;
}
public void setScale(float scale) {
size.x = scale;
size.y = scale;
}
public void setX(float x) {
position.x = x;
}
public void setY(float y) {
position.y = y;
}
public void setVelocityX(float velX) {
this.velX = velX;
}
public void setVelocityY(float velY) {
this.velY = velY;
}
public void setMass(float mass) {
this.mass = mass;
}
public void setFriction(float friction) {
this.friction = friction;
}
public void addForce(float angle, float force) {
float xComp = (float)Math.cos(Math.toRadians(angle)) * force;
float yComp = (float)Math.sin(Math.toRadians(angle)) * force;
accelX += xComp / mass;
accelY += yComp / mass;
}
public void update() {
anim.update();
if(velX != 0 || velY != 0) {
float zeroStrength = mass * (float) Math.sqrt(accelX * accelX + accelY * accelY);
System.out.println(zeroStrength + ", " + friction);
addForce(getAngle() + 180, (float) Math.min(friction, zeroStrength));
}
position.x += velX;
position.y += velY;
velX += accelX;
velY += accelY;
}
public float getAngle() {
float hyp = (float) Math.sqrt(velX * velX + velY * velY);
float angle = (float) ((velY / (float) Math.abs(velY)) * (float) Math.acos(velX / hyp));
System.out.println((float) Math.toDegrees(angle));
return (float) Math.toDegrees(angle);
}
public void render() {
int x = (int) position.x;
int y = (int) position.y;
int z = (int) position.z;
position = new Vector3f(x, y, z);
Matrix4f translate = new Matrix4f().translate(position);
Matrix4f rotate = new Matrix4f().rotateZ((float)Math.toRadians(rotation));
Matrix4f scale = new Matrix4f().scale(size);
anim.getMesh().getShader().setUniformMat4f("vw_matrix", translate.mul(rotate).mul(scale));
anim.getMesh().render();
}
}

119
src/com/gnarly/engine/Window.java Executable file
View file

@ -0,0 +1,119 @@
package com.gnarly.engine;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.NULL;
import org.joml.Vector3f;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.GL;
public class Window {
private long window;
private int width, height, mx, my;
private boolean vSync;
public Window(int width, int height, boolean vSync) {
this.width = width;
this.height = height;
this.vSync = vSync;
init();
}
public void init() {
glfwSetErrorCallback(GLFWErrorCallback.createPrint(System.err));
if(!glfwInit())
throw new IllegalStateException("Could not initalize GLFW!");
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
GLFWVidMode vidMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
if(width == NULL || height == NULL) {
window = glfwCreateWindow(vidMode.width(), vidMode.height(), "One Room", glfwGetPrimaryMonitor(), NULL);
width = vidMode.width();
height = vidMode.height();
}
else {
window = glfwCreateWindow(width, height, "One Room", NULL, NULL);
glfwSetWindowPos(window, (vidMode.width() - width) / 2, (vidMode.height() - height) / 2);
}
glfwSetCursorPosCallback(window, (long window, double xpos, double ypos) -> {
mx = (int)xpos;
my = (int)ypos;
});
glfwMakeContextCurrent(window);
GL.createCapabilities();
if(vSync)
glfwSwapInterval(1);
glfwShowWindow(window);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
System.out.println("OpenGL Version: " + glGetString(GL_VERSION));
}
public void update() {
glfwPollEvents();
}
public void clear() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
public void swap() {
glfwSwapBuffers(window);
}
public void cleanup() {
glfwDestroyWindow(window);
glfwTerminate();
}
public Vector3f getMouseCoords() {
return new Vector3f(mx, my, 0);
}
public boolean isMousePressed(int button) {
return glfwGetMouseButton(window, button) == GLFW_PRESS;
}
public boolean isKeyPressed(int keyCode) {
return glfwGetKey(window, keyCode) == GLFW_PRESS;
}
public void close() {
glfwSetWindowShouldClose(window, true);
}
public boolean shouldClose() {
return glfwWindowShouldClose(window);
}
public long getWindow() {
return window;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
}

View file

@ -0,0 +1,61 @@
package com.gnarly.engine.graphics;
import com.gnarly.game.Main;
public class Animation {
Mesh[] meshes;
int frame = 0;
int max;
int inc = 1;
int curUps;
int needUps;
boolean reverse;
public Animation(String texPath, Shader shader, int numFrames, int numUpdates, boolean reverse) {
this.reverse = reverse;
max = numFrames;
needUps = numUpdates;
shader.setUniformMat4f("pr_matrix", Main.projection);
meshes = new Mesh[numFrames];
Texture tex = new Texture(texPath + (numFrames > 1 ? " 1.png" : ".png"));
if(numFrames > 1)
for (int i = 0; i < meshes.length; i++)
meshes[i] = new Mesh(constructVBO(tex.getWidth(), tex.getHeight()), new Texture(texPath + " " + (i+1) + ".png"), shader);
else
meshes[0] = new Mesh(constructVBO(tex.getWidth(), tex.getHeight()), tex, shader);
}
public void update() {
if(max > 1) {
if(curUps == needUps) {
frame += inc;
if((frame == -1 || frame == max) && reverse)
frame += (inc = -inc);
else if(frame == max)
frame = 0;
curUps = 1;
}
else
++curUps;
}
}
public void render() {
meshes[frame].render();
}
private float[] constructVBO(float width, float height) {
float[] vbo = new float[] {
0.0f, 0.0f, 0.0f, //TOP LEFT
0.0f, -height, 0.0f, //BOTTOM LEFT
width, -height, 0.0f, //BOTTOM RIGHT
width, 0.0f, 0.0f //TOP RIGHT
};
return vbo;
}
public Mesh getMesh() {
return meshes[frame];
}
}

View file

@ -0,0 +1,124 @@
package com.gnarly.engine.graphics;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.*;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import org.lwjgl.BufferUtils;
public class Mesh {
private Shader shader;
private Texture texture;
private int count;
private int vaoID, vboID, iboID, tcboID;
private float[] vbo, tcbo;
private byte[] ibo;
public Mesh(float[] vbo, byte[] ibo, float[] tcbo, Texture texture, Shader shader) {
this.vbo = vbo;
this.ibo = ibo;
this.tcbo = tcbo;
this.texture = texture;
this.shader = shader;
count = ibo.length;
init();
}
public Mesh(float[] vbo, Texture texture, Shader shader) {
this.vbo = vbo;
this.ibo = defaultIBO();
this.tcbo = defaultTCBO();
this.texture = texture;
this.shader = shader;
count = ibo.length;
init();
}
public Mesh(float[] vbo, String texPath, String vertPath, String fragPath) {
this.vbo = vbo;
this.ibo = defaultIBO();
this.tcbo = defaultTCBO();
this.texture = new Texture(texPath);
this.shader = new Shader(vertPath, fragPath);
count = ibo.length;
init();
}
private void init() {
vaoID = glGenVertexArrays();
glBindVertexArray(vaoID);
vboID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, createFloatBuffer(vbo), GL_STATIC_DRAW);
glVertexAttribPointer(Shader.VERT_ATTRIB, 3, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(Shader.VERT_ATTRIB);
iboID = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, createByteBuffer(ibo), GL_STATIC_DRAW);
tcboID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, tcboID);
glBufferData(GL_ARRAY_BUFFER, createFloatBuffer(tcbo), GL_STATIC_DRAW);
glVertexAttribPointer(Shader.TEX_COORD_ATTRIB, 2, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(Shader.TEX_COORD_ATTRIB);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
public void render() {
shader.enable();
texture.bind();
glBindVertexArray(vaoID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID);
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_BYTE, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
texture.unbind();
shader.enable();
}
public byte[] defaultIBO() {
return new byte[] {
0, 1, 2,
0, 2, 3
};
}
public float[] defaultTCBO() {
return new float[] {
1, 0,
1, 1,
0, 1,
0, 0,
};
}
public Shader getShader() {
return shader;
}
public FloatBuffer createFloatBuffer(float[] data) {
FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
buffer.put(data);
buffer.flip();
return buffer;
}
public ByteBuffer createByteBuffer(byte[] data) {
ByteBuffer buffer = BufferUtils.createByteBuffer(data.length);
buffer.put(data);
buffer.flip();
return buffer;
}
}

View file

@ -0,0 +1,120 @@
package com.gnarly.engine.graphics;
import static org.lwjgl.opengl.GL20.*;
import org.lwjgl.BufferUtils;
import java.io.*;
import java.nio.FloatBuffer;
import java.util.HashMap;
import java.util.Map;
import org.joml.Matrix4f;
import org.joml.Vector3f;
public class Shader {
private int program, vs, fs;
public static int VERT_ATTRIB = 0, TEX_COORD_ATTRIB = 1;
boolean enabled;
Map<String, Integer> uniforms;
public Shader(String vertPath, String fragPath) {
uniforms = new HashMap<>();
String vert = load(vertPath);
String frag = load(fragPath);
create(vert, frag);
}
private String load(String path) {
StringBuilder file = new StringBuilder();
try {
BufferedReader reader = new BufferedReader(new FileReader(new File("res/shaders/" + path)));
String line;
while((line = reader.readLine()) != null)
file.append(line + '\n');
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
return file.toString();
}
public void create(String vert, String frag) {
program = glCreateProgram();
vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, vert);
glCompileShader(vs);
if(glGetShaderi(vs, GL_COMPILE_STATUS) != 1)
throw new RuntimeException("Failed to compile shader! " + glGetShaderInfoLog(vs));
fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, frag);
glCompileShader(fs);
if(glGetShaderi(fs, GL_COMPILE_STATUS) != 1)
throw new RuntimeException("Failed to compile shader! " + glGetShaderInfoLog(fs));
glAttachShader(program, vs);
glAttachShader(program, fs);
glBindAttribLocation(program, VERT_ATTRIB, "verts");
glBindAttribLocation(program, TEX_COORD_ATTRIB, "texts");
glLinkProgram(program);
glValidateProgram(program);
}
public int getLocation(String name) {
if(uniforms.containsKey(name))
return uniforms.get(name);
int location = glGetUniformLocation(program, name);
uniforms.put(name, location);
if(location != -1)
return location;
else
throw new RuntimeException("Could not find uniform: " + name);
}
public void setUniform1i(String name, int value) {
if(!enabled) enable();
glUniform1i(getLocation(name), value);
disable();
}
public void setUniform1f(String name, float value) {
if(!enabled) enable();
glUniform1f(getLocation(name), value);
disable();
}
public void setUniform2f(String name, float x, float y) {
if(!enabled) enable();
glUniform2f(getLocation(name), x, y);
disable();
}
public void setUniform3f(String name, Vector3f vector) {
if(!enabled) enable();
glUniform3f(getLocation(name), vector.x, vector.y, vector.z);
disable();
}
public void setUniformMat4f(String name, Matrix4f matrix) {
if(!enabled) enable();
FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
matrix.get(buffer);
glUniformMatrix4fv(getLocation(name), false, buffer);
disable();
}
public void enable() {
enabled = true;
glUseProgram(program);
}
public void disable() {
enabled = false;
glUseProgram(0);
}
}

View file

@ -0,0 +1,34 @@
package com.gnarly.engine.graphics;
import java.util.HashMap;
import java.util.Map;
public class ShaderLibrary {
Map<String, Shader> shaders;
public ShaderLibrary() {
shaders = new HashMap<>();
init();
}
private void init() {
shaders.put("default", new Shader("vert.vs", "frag.fs"));
}
public void add(String name, Shader shader) {
if(!shaders.containsKey(name))
shaders.put(name, shader);
}
public Shader get(String name) {
if(shaders.containsKey(name))
return shaders.get(name);
else
throw new RuntimeException("Shader of name '" + name + "' has not been create yet!");
}
public Shader getDefault() {
return shaders.get("default");
}
}

View file

@ -0,0 +1,71 @@
package com.gnarly.engine.graphics;
import static org.lwjgl.opengl.GL11.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import javax.imageio.ImageIO;
import org.lwjgl.BufferUtils;
public class Texture {
private int width, height;
private int ID;
public Texture(String path) {
BufferedImage bi;
try {
bi = ImageIO.read(new File("res/img/" + path));
width = bi.getWidth();
height = bi.getHeight();
int[] pixelsRaw = new int[width * height];
pixelsRaw = bi.getRGB(0, 0, width, height, null, 0, width);
ByteBuffer pixels = BufferUtils.createByteBuffer(width * height * 4);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int pixel = pixelsRaw[i * width + j];
pixels.put((byte)((pixel >> 16) & 0xFF));
pixels.put((byte)((pixel >> 8 ) & 0xFF));
pixels.put((byte)((pixel ) & 0xFF));
pixels.put((byte)((pixel >> 24) & 0xFF));
}
}
pixels.flip();
ID = glGenTextures();
glBindTexture(GL_TEXTURE_2D, ID);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
} catch (IOException e) {
e.printStackTrace();
}
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public void bind() {
glBindTexture(GL_TEXTURE_2D, ID);
}
public void unbind() {
glBindTexture(GL_TEXTURE_2D, 0);
}
}

72
src/com/gnarly/game/Main.java Executable file
View file

@ -0,0 +1,72 @@
package com.gnarly.game;
import static org.lwjgl.glfw.GLFW.*;
import java.util.HashMap;
import java.util.Map;
import org.joml.Matrix4f;
import com.gnarly.engine.GameObject;
import com.gnarly.engine.Window;
import com.gnarly.engine.graphics.ShaderLibrary;
public class Main {
Window window;
ShaderLibrary shaders;
boolean running = true;
Map<String, GameObject> objects = new HashMap<>();
GameObject block1;
GameObject block2;
public static Matrix4f projection;
public Main() {
window = new Window(1000, 700, true);
shaders = new ShaderLibrary();
projection = new Matrix4f().ortho2D(-window.getWidth() / 2, window.getWidth() / 2, -window.getHeight() / 2, window.getHeight() / 2);
run();
}
public void run() {
objects.put("Stone Block", new GameObject("Stone Block", shaders.getDefault()));
objects.put("Spring", new GameObject("Spring", shaders.getDefault(), 4, 2, true));
block1 = objects.get("Stone Block").newInstanceOf(0.0f, 0.0f, 0.0f, 0.0f, 8.0f, 1.0f, 0.1f, false);
while(running) {
input();
update(block1);
render(block1);
running = !window.shouldClose();
}
}
public void input() {
float force = 0.05f;
if(window.isKeyPressed(GLFW_KEY_D)) block1.addForce(0, force);
if(window.isKeyPressed(GLFW_KEY_W)) block1.addForce(90, force);
else if(window.isKeyPressed(GLFW_KEY_A)) block1.addForce(180, force);
else if(window.isKeyPressed(GLFW_KEY_S)) block1.addForce(270, force);
if(window.isKeyPressed(GLFW_KEY_RIGHT)) block2.addForce(0, force);
if(window.isKeyPressed(GLFW_KEY_UP)) block2.addForce(90, force);
else if(window.isKeyPressed(GLFW_KEY_LEFT)) block2.addForce(180, force);
else if(window.isKeyPressed(GLFW_KEY_DOWN)) block2.addForce(270, force);
if(window.isKeyPressed(GLFW_KEY_ESCAPE)) window.close();
}
public void update(GameObject... gameObjects) {
window.update();
for (int i = 0; i < gameObjects.length; i++)
gameObjects[i].update();
}
public void render(GameObject... gameObjects) {
window.clear();
for (int i = 0; i < gameObjects.length; i++)
gameObjects[i].render();
window.swap();
}
public static void main(String[] args) {
new Main();
}
}