commit 80c9e2d168462f8440346c94adef0c5032f7e4b9 Author: Gnarwhal Date: Wed Aug 7 04:28:53 2024 +0000 Project as is diff --git a/res/hitboxes/stages/mountain.shb b/res/hitboxes/stages/mountain.shb new file mode 100755 index 0000000..be3fc28 Binary files /dev/null and b/res/hitboxes/stages/mountain.shb differ diff --git a/res/img/characters/blue stick/fall/blue stick fall 1.png b/res/img/characters/blue stick/fall/blue stick fall 1.png new file mode 100755 index 0000000..4ebfd5f Binary files /dev/null and b/res/img/characters/blue stick/fall/blue stick fall 1.png differ diff --git a/res/img/characters/blue stick/fall/blue stick fall 2.png b/res/img/characters/blue stick/fall/blue stick fall 2.png new file mode 100755 index 0000000..9de87d1 Binary files /dev/null and b/res/img/characters/blue stick/fall/blue stick fall 2.png differ diff --git a/res/img/characters/blue stick/fall/blue stick fall 3.png b/res/img/characters/blue stick/fall/blue stick fall 3.png new file mode 100755 index 0000000..4646885 Binary files /dev/null and b/res/img/characters/blue stick/fall/blue stick fall 3.png differ diff --git a/res/img/characters/blue stick/fall/blue stick fall 4.png b/res/img/characters/blue stick/fall/blue stick fall 4.png new file mode 100755 index 0000000..056bbf1 Binary files /dev/null and b/res/img/characters/blue stick/fall/blue stick fall 4.png differ diff --git a/res/img/characters/blue stick/fall/blue stick fall 5.png b/res/img/characters/blue stick/fall/blue stick fall 5.png new file mode 100755 index 0000000..7a30e41 Binary files /dev/null and b/res/img/characters/blue stick/fall/blue stick fall 5.png differ diff --git a/res/img/characters/blue stick/fall/blue stick fall 6.png b/res/img/characters/blue stick/fall/blue stick fall 6.png new file mode 100755 index 0000000..a7184a6 Binary files /dev/null and b/res/img/characters/blue stick/fall/blue stick fall 6.png differ diff --git a/res/img/characters/blue stick/idle/blue stick idle 1.png b/res/img/characters/blue stick/idle/blue stick idle 1.png new file mode 100755 index 0000000..7521b9a Binary files /dev/null and b/res/img/characters/blue stick/idle/blue stick idle 1.png differ diff --git a/res/img/characters/blue stick/idle/blue stick idle 2.png b/res/img/characters/blue stick/idle/blue stick idle 2.png new file mode 100755 index 0000000..ef9e6bc Binary files /dev/null and b/res/img/characters/blue stick/idle/blue stick idle 2.png differ diff --git a/res/img/characters/blue stick/idle/blue stick idle 3.png b/res/img/characters/blue stick/idle/blue stick idle 3.png new file mode 100755 index 0000000..e5aab66 Binary files /dev/null and b/res/img/characters/blue stick/idle/blue stick idle 3.png differ diff --git a/res/img/characters/blue stick/idle/blue stick idle 4.png b/res/img/characters/blue stick/idle/blue stick idle 4.png new file mode 100755 index 0000000..c4e4470 Binary files /dev/null and b/res/img/characters/blue stick/idle/blue stick idle 4.png differ diff --git a/res/img/characters/blue stick/idle/blue stick idle 5.png b/res/img/characters/blue stick/idle/blue stick idle 5.png new file mode 100755 index 0000000..e5aab66 Binary files /dev/null and b/res/img/characters/blue stick/idle/blue stick idle 5.png differ diff --git a/res/img/characters/blue stick/idle/blue stick idle 6.png b/res/img/characters/blue stick/idle/blue stick idle 6.png new file mode 100755 index 0000000..ef9e6bc Binary files /dev/null and b/res/img/characters/blue stick/idle/blue stick idle 6.png differ diff --git a/res/img/characters/blue stick/idle/blue stick idle 7.png b/res/img/characters/blue stick/idle/blue stick idle 7.png new file mode 100755 index 0000000..7521b9a Binary files /dev/null and b/res/img/characters/blue stick/idle/blue stick idle 7.png differ diff --git a/res/img/characters/blue stick/idle/blue stick idle 8.png b/res/img/characters/blue stick/idle/blue stick idle 8.png new file mode 100755 index 0000000..82c6e9d Binary files /dev/null and b/res/img/characters/blue stick/idle/blue stick idle 8.png differ diff --git a/res/img/characters/blue stick/jump/blue stick jump 1.png b/res/img/characters/blue stick/jump/blue stick jump 1.png new file mode 100755 index 0000000..0dd4998 Binary files /dev/null and b/res/img/characters/blue stick/jump/blue stick jump 1.png differ diff --git a/res/img/characters/blue stick/jump/blue stick jump 2.png b/res/img/characters/blue stick/jump/blue stick jump 2.png new file mode 100755 index 0000000..558c677 Binary files /dev/null and b/res/img/characters/blue stick/jump/blue stick jump 2.png differ diff --git a/res/img/characters/blue stick/jump/blue stick jump 3.png b/res/img/characters/blue stick/jump/blue stick jump 3.png new file mode 100755 index 0000000..39c9144 Binary files /dev/null and b/res/img/characters/blue stick/jump/blue stick jump 3.png differ diff --git a/res/img/characters/blue stick/jump/blue stick jump 4.png b/res/img/characters/blue stick/jump/blue stick jump 4.png new file mode 100755 index 0000000..6825c50 Binary files /dev/null and b/res/img/characters/blue stick/jump/blue stick jump 4.png differ diff --git a/res/img/characters/blue stick/jump/blue stick jump 5.png b/res/img/characters/blue stick/jump/blue stick jump 5.png new file mode 100755 index 0000000..33e2248 Binary files /dev/null and b/res/img/characters/blue stick/jump/blue stick jump 5.png differ diff --git a/res/img/characters/blue stick/jump/blue stick jump 6.png b/res/img/characters/blue stick/jump/blue stick jump 6.png new file mode 100755 index 0000000..1464c2e Binary files /dev/null and b/res/img/characters/blue stick/jump/blue stick jump 6.png differ diff --git a/res/img/characters/blue stick/run/blue stick run 1.png b/res/img/characters/blue stick/run/blue stick run 1.png new file mode 100755 index 0000000..0f87c04 Binary files /dev/null and b/res/img/characters/blue stick/run/blue stick run 1.png differ diff --git a/res/img/characters/blue stick/run/blue stick run 2.png b/res/img/characters/blue stick/run/blue stick run 2.png new file mode 100755 index 0000000..040dca4 Binary files /dev/null and b/res/img/characters/blue stick/run/blue stick run 2.png differ diff --git a/res/img/characters/blue stick/run/blue stick run 3.png b/res/img/characters/blue stick/run/blue stick run 3.png new file mode 100755 index 0000000..9c267aa Binary files /dev/null and b/res/img/characters/blue stick/run/blue stick run 3.png differ diff --git a/res/img/characters/blue stick/run/blue stick run 4.png b/res/img/characters/blue stick/run/blue stick run 4.png new file mode 100755 index 0000000..d8c2925 Binary files /dev/null and b/res/img/characters/blue stick/run/blue stick run 4.png differ diff --git a/res/img/characters/blue stick/run/blue stick run 5.png b/res/img/characters/blue stick/run/blue stick run 5.png new file mode 100755 index 0000000..406be65 Binary files /dev/null and b/res/img/characters/blue stick/run/blue stick run 5.png differ diff --git a/res/img/characters/blue stick/walk/blue stick walk 1.png b/res/img/characters/blue stick/walk/blue stick walk 1.png new file mode 100755 index 0000000..30fec4f Binary files /dev/null and b/res/img/characters/blue stick/walk/blue stick walk 1.png differ diff --git a/res/img/characters/blue stick/walk/blue stick walk 2.png b/res/img/characters/blue stick/walk/blue stick walk 2.png new file mode 100755 index 0000000..293b2fd Binary files /dev/null and b/res/img/characters/blue stick/walk/blue stick walk 2.png differ diff --git a/res/img/characters/blue stick/walk/blue stick walk 3.png b/res/img/characters/blue stick/walk/blue stick walk 3.png new file mode 100755 index 0000000..58c9311 Binary files /dev/null and b/res/img/characters/blue stick/walk/blue stick walk 3.png differ diff --git a/res/img/characters/blue stick/walk/blue stick walk 4.png b/res/img/characters/blue stick/walk/blue stick walk 4.png new file mode 100755 index 0000000..ee1ac63 Binary files /dev/null and b/res/img/characters/blue stick/walk/blue stick walk 4.png differ diff --git a/res/img/characters/blue stick/walk/blue stick walk 5.png b/res/img/characters/blue stick/walk/blue stick walk 5.png new file mode 100755 index 0000000..7977c79 Binary files /dev/null and b/res/img/characters/blue stick/walk/blue stick walk 5.png differ diff --git a/res/img/characters/blue stick/walk/blue stick walk 6.png b/res/img/characters/blue stick/walk/blue stick walk 6.png new file mode 100755 index 0000000..49949d7 Binary files /dev/null and b/res/img/characters/blue stick/walk/blue stick walk 6.png differ diff --git a/res/img/characters/blue stick/walk/blue stick walk 7.png b/res/img/characters/blue stick/walk/blue stick walk 7.png new file mode 100755 index 0000000..56e5f95 Binary files /dev/null and b/res/img/characters/blue stick/walk/blue stick walk 7.png differ diff --git a/res/img/characters/blue stick/walk/blue stick walk 8.png b/res/img/characters/blue stick/walk/blue stick walk 8.png new file mode 100755 index 0000000..0a42c40 Binary files /dev/null and b/res/img/characters/blue stick/walk/blue stick walk 8.png differ diff --git a/res/img/characters/blue stick/walk/blue stick walk 9.png b/res/img/characters/blue stick/walk/blue stick walk 9.png new file mode 100755 index 0000000..1920e1c Binary files /dev/null and b/res/img/characters/blue stick/walk/blue stick walk 9.png differ diff --git a/res/img/stages/mountain/mountain 1.png b/res/img/stages/mountain/mountain 1.png new file mode 100755 index 0000000..e9c9499 Binary files /dev/null and b/res/img/stages/mountain/mountain 1.png differ diff --git a/res/shaders/default/default.fs b/res/shaders/default/default.fs new file mode 100755 index 0000000..1c1e008 --- /dev/null +++ b/res/shaders/default/default.fs @@ -0,0 +1,9 @@ +#version 450 + +uniform sampler2D sampler; + +in vec2 textureCoords; + +void main() { + gl_FragColor = texture2D(sampler, textureCoords); +} \ No newline at end of file diff --git a/res/shaders/default/default.vs b/res/shaders/default/default.vs new file mode 100755 index 0000000..213e572 --- /dev/null +++ b/res/shaders/default/default.vs @@ -0,0 +1,13 @@ +#version 450 + +uniform mat4 projection; + +in vec3 vertices; +in vec2 texCoords; + +out vec2 textureCoords; + +void main() { + textureCoords = texCoords; + gl_Position = projection * vec4(vertices, 1); +} \ No newline at end of file diff --git a/res/shaders/shapes/shapes.fs b/res/shaders/shapes/shapes.fs new file mode 100755 index 0000000..7cef706 --- /dev/null +++ b/res/shaders/shapes/shapes.fs @@ -0,0 +1,5 @@ +#version 450 + +void main() { + gl_FragColor = vec4(0, 1, 1, 0.5); +} \ No newline at end of file diff --git a/res/shaders/shapes/shapes.vs b/res/shaders/shapes/shapes.vs new file mode 100755 index 0000000..e9fde75 --- /dev/null +++ b/res/shaders/shapes/shapes.vs @@ -0,0 +1,9 @@ +#version 450 + +uniform mat4 projection; + +in vec3 vertices; + +void main() { + gl_Position = projection * vec4(vertices, 1); +} \ No newline at end of file diff --git a/src/com/gnarly/engine/components/Animation.java b/src/com/gnarly/engine/components/Animation.java new file mode 100755 index 0000000..fb295a9 --- /dev/null +++ b/src/com/gnarly/engine/components/Animation.java @@ -0,0 +1,74 @@ +package com.gnarly.engine.components; + +import com.gnarly.engine.utils.Library; + +public class Animation { + + int curFrame, numFrames; + float pastTime, curTime, mspf; + boolean play, loop; + Texture[] frames; + + public Animation(String name, String type, int numFrames, int fps, boolean loop) { + this.numFrames = numFrames; + this.loop = loop; + play = true; + mspf = 1000.0f / (float) fps; + pastTime = System.nanoTime() / 1000000.0f; + frames = new Texture[numFrames]; + for (int i = 0; i < frames.length; i++) + frames[i] = Library.getTexture(name + " " + (i + 1) + "." + type); + } + + public Animation(String name) { + frames = new Texture[1]; + frames[0] = Library.getTexture(name); + } + + public void update() { + if(frames.length > 1) { + curTime = System.nanoTime() / 1000000.0f; + while(play && curTime - pastTime > mspf) { + if(curFrame != frames.length - 1) + ++curFrame; + else if(loop) + curFrame = 0; + else + pause(); + pastTime += mspf; + } + } + } + + public int getWidth() { + return frames[curFrame].getWidth(); + } + + public int getHeight() { + return frames[curFrame].getHeight(); + } + + public void pause() { + play = false; + } + + public void play() { + if(!play) { + pastTime = System.nanoTime() / 1000000.0f; + play = true; + } + } + + public void reset() { + curFrame = 0; + pastTime = System.nanoTime() / 1000000.0f; + } + + public void bind() { + frames[curFrame].bind(); + } + + public void unbind() { + frames[curFrame].unbind(); + } +} diff --git a/src/com/gnarly/engine/components/Shader.java b/src/com/gnarly/engine/components/Shader.java new file mode 100755 index 0000000..e7a4bf5 --- /dev/null +++ b/src/com/gnarly/engine/components/Shader.java @@ -0,0 +1,153 @@ +package com.gnarly.engine.components; + +import static com.gnarly.engine.utils.MemoryUtils.GL_PROGRAM; +import static com.gnarly.engine.utils.MemoryUtils.GL_SHADER; +import static com.gnarly.engine.utils.MemoryUtils.add; +import static org.lwjgl.opengl.GL20.GL_COMPILE_STATUS; +import static org.lwjgl.opengl.GL20.GL_FRAGMENT_SHADER; +import static org.lwjgl.opengl.GL20.GL_VERTEX_SHADER; +import static org.lwjgl.opengl.GL20.glAttachShader; +import static org.lwjgl.opengl.GL20.glBindAttribLocation; +import static org.lwjgl.opengl.GL20.glCompileShader; +import static org.lwjgl.opengl.GL20.glCreateProgram; +import static org.lwjgl.opengl.GL20.glCreateShader; +import static org.lwjgl.opengl.GL20.glGetShaderInfoLog; +import static org.lwjgl.opengl.GL20.glGetShaderi; +import static org.lwjgl.opengl.GL20.glGetUniformLocation; +import static org.lwjgl.opengl.GL20.glLinkProgram; +import static org.lwjgl.opengl.GL20.glShaderSource; +import static org.lwjgl.opengl.GL20.glUniform1f; +import static org.lwjgl.opengl.GL20.glUniform1i; +import static org.lwjgl.opengl.GL20.glUniform2f; +import static org.lwjgl.opengl.GL20.glUniform3f; +import static org.lwjgl.opengl.GL20.glUniformMatrix4fv; +import static org.lwjgl.opengl.GL20.glUseProgram; +import static org.lwjgl.opengl.GL20.glValidateProgram; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.nio.FloatBuffer; +import java.util.HashMap; +import java.util.Map; + +import org.joml.Matrix4f; +import org.joml.Vector3f; +import org.lwjgl.BufferUtils; + +public class Shader { + + private String name; + private int program, vs, fs; + public static int VERT_ATTRIB = 0, TEX_COORD_ATTRIB = 1; + boolean enabled; + Map uniforms; + + public Shader(String vertPath, String fragPath) { + name = new File(new File(vertPath).getParent()).getName(); + 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(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(); + add(GL_PROGRAM, program); + + vs = glCreateShader(GL_VERTEX_SHADER); + add(GL_SHADER, vs); + 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); + add(GL_SHADER, fs); + 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, "vertices"); + glBindAttribLocation(program, TEX_COORD_ATTRIB, "texCoords"); + + 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) { + enable(); + glUniform1i(getLocation(name), value); + disable(); + } + + public void setUniform1f(String name, float value) { + enable(); + glUniform1f(getLocation(name), value); + disable(); + } + + public void setUniform2f(String name, float x, float y) { + enable(); + glUniform2f(getLocation(name), x, y); + disable(); + } + + public void setUniform3f(String name, Vector3f vector) { + enable(); + glUniform3f(getLocation(name), vector.x, vector.y, vector.z); + disable(); + } + + public void setUniformMat4f(String name, Matrix4f matrix) { + enable(); + FloatBuffer buffer = BufferUtils.createFloatBuffer(16); + matrix.get(buffer); + glUniformMatrix4fv(getLocation(name), false, buffer); + disable(); + } + + public String getName() { + return name; + } + + public void enable() { + enabled = true; + glUseProgram(program); + } + + public void disable() { + enabled = false; + glUseProgram(0); + } +} diff --git a/src/com/gnarly/engine/components/Texture.java b/src/com/gnarly/engine/components/Texture.java new file mode 100755 index 0000000..88d6a3e --- /dev/null +++ b/src/com/gnarly/engine/components/Texture.java @@ -0,0 +1,89 @@ +package com.gnarly.engine.components; + +import static com.gnarly.engine.utils.MemoryUtils.GL_TEXTURE; +import static com.gnarly.engine.utils.MemoryUtils.add; +import static org.lwjgl.opengl.GL11.GL_NEAREST; +import static org.lwjgl.opengl.GL11.GL_RGBA; +import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D; +import static org.lwjgl.opengl.GL11.GL_TEXTURE_MAG_FILTER; +import static org.lwjgl.opengl.GL11.GL_TEXTURE_MIN_FILTER; +import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE; +import static org.lwjgl.opengl.GL11.glBindTexture; +import static org.lwjgl.opengl.GL11.glGenTextures; +import static org.lwjgl.opengl.GL11.glTexImage2D; +import static org.lwjgl.opengl.GL11.glTexParameterf; + +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 String name; + private int id, width, height; + + public Texture(String fileName) { + try { + File file = new File(fileName); + name = file.getName(); + BufferedImage bi = ImageIO.read(file); + 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)); //RED + pixels.put((byte)((pixel >> 8) & 0xFF)); //GREEN + pixels.put((byte)((pixel ) & 0xFF)); //BLUE + pixels.put((byte)((pixel >> 24) & 0xFF)); //ALPHA + } + } + pixels.flip(); + + id = glGenTextures(); + add(GL_TEXTURE, id); + + bind(); + + 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); + + unbind(); + } catch(IOException e) { + e.printStackTrace(); + } + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public String getName() { + return name; + } + + public void bind() { + glBindTexture(GL_TEXTURE_2D, id); + } + + public void unbind() { + glBindTexture(GL_TEXTURE_2D, 0); + } +} diff --git a/src/com/gnarly/engine/components/VAO.java b/src/com/gnarly/engine/components/VAO.java new file mode 100755 index 0000000..64853d1 --- /dev/null +++ b/src/com/gnarly/engine/components/VAO.java @@ -0,0 +1,87 @@ +package com.gnarly.engine.components; + +import static com.gnarly.engine.utils.MemoryUtils.GL_BUFFER; +import static com.gnarly.engine.utils.MemoryUtils.add; +import static org.lwjgl.opengl.GL11.GL_FLOAT; +import static org.lwjgl.opengl.GL11.GL_TRIANGLES; +import static org.lwjgl.opengl.GL11.GL_UNSIGNED_INT; +import static org.lwjgl.opengl.GL11.glDrawElements; +import static org.lwjgl.opengl.GL15.GL_ARRAY_BUFFER; +import static org.lwjgl.opengl.GL15.GL_ELEMENT_ARRAY_BUFFER; +import static org.lwjgl.opengl.GL15.GL_STATIC_DRAW; +import static org.lwjgl.opengl.GL15.glBindBuffer; +import static org.lwjgl.opengl.GL15.glBufferData; +import static org.lwjgl.opengl.GL15.glGenBuffers; +import static org.lwjgl.opengl.GL20.glDisableVertexAttribArray; +import static org.lwjgl.opengl.GL20.glEnableVertexAttribArray; +import static org.lwjgl.opengl.GL20.glVertexAttribPointer; + +import java.nio.FloatBuffer; +import java.nio.IntBuffer; + +import org.lwjgl.BufferUtils; + + +public class VAO { + + private int count, vbo, ibo, tcbo; + + public VAO(float[] vertices, int[] indices, float[] texCoords) { + count = indices.length; + init(vertices, indices, texCoords); + } + + private void init(float[] vertices, int[] indices, float[] texCoords) { + vbo = glGenBuffers(); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, createFloatBuffer(vertices), GL_STATIC_DRAW); + add(GL_BUFFER, vbo); + + ibo = glGenBuffers(); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, createIntBuffer(indices), GL_STATIC_DRAW); + add(GL_BUFFER, ibo); + + tcbo = glGenBuffers(); + glBindBuffer(GL_ARRAY_BUFFER, tcbo); + glBufferData(GL_ARRAY_BUFFER, createFloatBuffer(texCoords), GL_STATIC_DRAW); + add(GL_BUFFER, tcbo); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + + public void render() { + glEnableVertexAttribArray(Shader.VERT_ATTRIB); + glEnableVertexAttribArray(Shader.TEX_COORD_ATTRIB); + + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glVertexAttribPointer(Shader.VERT_ATTRIB, 3, GL_FLOAT, false, 0, 0); + + glBindBuffer(GL_ARRAY_BUFFER, tcbo); + glVertexAttribPointer(Shader.TEX_COORD_ATTRIB, 2, GL_FLOAT, false, 0, 0); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); + glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, 0); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDisableVertexAttribArray(Shader.VERT_ATTRIB); + glDisableVertexAttribArray(Shader.TEX_COORD_ATTRIB); + } + + public FloatBuffer createFloatBuffer(float[] data) { + FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length); + buffer.put(data); + buffer.flip(); + return buffer; + } + + public IntBuffer createIntBuffer(int[] data) { + IntBuffer buffer = BufferUtils.createIntBuffer(data.length); + buffer.put(data); + buffer.flip(); + return buffer; + } +} \ No newline at end of file diff --git a/src/com/gnarly/engine/display/Camera.java b/src/com/gnarly/engine/display/Camera.java new file mode 100755 index 0000000..03490dd --- /dev/null +++ b/src/com/gnarly/engine/display/Camera.java @@ -0,0 +1,82 @@ +package com.gnarly.engine.display; + +import org.joml.Matrix4f; +import org.joml.Vector3f; + +public class Camera { + + private int width, height; + private Vector3f position; + private Matrix4f projection; + + public Camera(int width, int height) { + this.width = width; + this.height = height; + position = new Vector3f(0,0,0); + setProjection(width, height); + } + + public void setProjection(int width, int height) { + projection = new Matrix4f().setOrtho2D(0, width, height, 0); + } + + public void setPosition(Vector3f position) { + this.position.x = -position.x; + this.position.y = -position.y; + this.position.z = -position.z; + } + + public void setPosition(float x, float y, float z) { + position.x = -x; + position.y = -y; + position.z = -z; + } + + public void setCenterPosition(Vector3f position) { + this.position.x = -position.x + width / 2; + this.position.y = -position.y + height / 2; + this.position.z = -position.z; + } + + public void setCenterPosition(float x, float y, float z) { + position.x = -x + width / 2; + position.y = -y + height / 2; + position.z = -z; + } + + public void translate(Vector3f position) { + this.position.x -= position.x; + this.position.y -= position.y; + this.position.z -= position.z; + } + + public void translate(float x, float y, float z) { + position.x -= x; + position.y -= y; + position.z -= z; + } + + public Matrix4f getUnatransformedProjection() { + return new Matrix4f(projection); + } + + public Matrix4f getProjection() { + return projection.translate(position, new Matrix4f()); + } + + public float getX() { + return -position.x; + } + + public float getY() { + return -position.y; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } +} diff --git a/src/com/gnarly/engine/display/Window.java b/src/com/gnarly/engine/display/Window.java new file mode 100755 index 0000000..09c1d7e --- /dev/null +++ b/src/com/gnarly/engine/display/Window.java @@ -0,0 +1,178 @@ +package com.gnarly.engine.display; + +import static org.lwjgl.glfw.GLFW.GLFW_FALSE; +import static org.lwjgl.glfw.GLFW.GLFW_PRESS; +import static org.lwjgl.glfw.GLFW.GLFW_RESIZABLE; +import static org.lwjgl.glfw.GLFW.GLFW_TRUE; +import static org.lwjgl.glfw.GLFW.GLFW_VISIBLE; +import static org.lwjgl.glfw.GLFW.glfwCreateWindow; +import static org.lwjgl.glfw.GLFW.glfwDestroyWindow; +import static org.lwjgl.glfw.GLFW.glfwGetKey; +import static org.lwjgl.glfw.GLFW.glfwGetMouseButton; +import static org.lwjgl.glfw.GLFW.glfwGetPrimaryMonitor; +import static org.lwjgl.glfw.GLFW.glfwGetVideoMode; +import static org.lwjgl.glfw.GLFW.glfwInit; +import static org.lwjgl.glfw.GLFW.glfwMakeContextCurrent; +import static org.lwjgl.glfw.GLFW.glfwPollEvents; +import static org.lwjgl.glfw.GLFW.glfwSetCursorPosCallback; +import static org.lwjgl.glfw.GLFW.glfwSetErrorCallback; +import static org.lwjgl.glfw.GLFW.glfwSetWindowPos; +import static org.lwjgl.glfw.GLFW.glfwSetWindowShouldClose; +import static org.lwjgl.glfw.GLFW.glfwShowWindow; +import static org.lwjgl.glfw.GLFW.glfwSwapBuffers; +import static org.lwjgl.glfw.GLFW.glfwSwapInterval; +import static org.lwjgl.glfw.GLFW.glfwTerminate; +import static org.lwjgl.glfw.GLFW.glfwWindowHint; +import static org.lwjgl.glfw.GLFW.glfwWindowShouldClose; +import static org.lwjgl.opengl.GL11.GL_BLEND; +import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT; +import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT; +import static org.lwjgl.opengl.GL11.GL_ONE_MINUS_SRC_ALPHA; +import static org.lwjgl.opengl.GL11.GL_SRC_ALPHA; +import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D; +import static org.lwjgl.opengl.GL11.GL_VERSION; +import static org.lwjgl.opengl.GL11.glBlendFunc; +import static org.lwjgl.opengl.GL11.glClear; +import static org.lwjgl.opengl.GL11.glClearColor; +import static org.lwjgl.opengl.GL11.glEnable; +import static org.lwjgl.opengl.GL11.glGetString; +import static org.lwjgl.system.MemoryUtil.NULL; + +import java.awt.Dimension; +import java.awt.Toolkit; + +import org.joml.Vector3f; +import org.lwjgl.glfw.GLFWErrorCallback; +import org.lwjgl.glfw.GLFWVidMode; +import org.lwjgl.opengl.GL; + +public class Window { + + private long window; + + private int width, height, mx, my; + private boolean vSync; + + public Window(Camera camera, String name, float scale, boolean vSync, boolean resizable) { + width = camera.getWidth(); + height = camera.getHeight(); + this.vSync = vSync; + init(name, scale, resizable, false); + } + + public Window(float percentWidth, float percentHeight, String name, boolean vSync, boolean resizable) { + this.vSync = vSync; + Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); + width = (int) (percentWidth / 100.0f * screen.getWidth()); + height = (int) (percentHeight / 100.0f * screen.getHeight()); + init(name, 1, resizable, false); + } + + public Window(boolean vSync) { + this.vSync = vSync; + init("null", 1, false, true); + } + + private void init(String name, float scale, boolean resizable, boolean fullscreen) { + glfwSetErrorCallback(GLFWErrorCallback.createPrint(System.err)); + + if(!glfwInit()) + throw new IllegalStateException("Could not initalize GLFW!"); + + if(!fullscreen) + glfwWindowHint(GLFW_RESIZABLE, resizable ? GLFW_TRUE : GLFW_FALSE); + glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); + + GLFWVidMode vidMode = glfwGetVideoMode(glfwGetPrimaryMonitor()); + + if(fullscreen || vidMode.width() < width || vidMode.height() < height) { + width = vidMode.width(); + height = vidMode.height(); + window = glfwCreateWindow(width, height, name, glfwGetPrimaryMonitor(), NULL); + } + else { + window = glfwCreateWindow((int)(width * scale), (int)(height * scale), name, NULL, NULL); + + glfwSetWindowPos(window, (int)((vidMode.width() - (width * scale)) / 2), (int)((vidMode.height() - (height * scale)) / 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); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + 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 Vector3f getMouseCoords() { + return new Vector3f(mx, my, 0); + } + + public int isMousePressed() { + int button = -1; + for (int i = 0; i < 8 && button == -1; i++) + if(glfwGetMouseButton(window, i) == GLFW_PRESS) + button = i; + return button; + } + + public boolean isKeyPressed(int keyCode) { + return glfwGetKey(window, keyCode) == GLFW_PRESS; + } + + public void close() { + glfwSetWindowShouldClose(window, true); + } + + public boolean shouldClose() { + boolean close = glfwWindowShouldClose(window); + if(close) { + glfwDestroyWindow(window); + glfwTerminate(); + } + return close; + } + + public static void cleanup() { + + } + + public long getWindow() { + return window; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } +} diff --git a/src/com/gnarly/engine/utils/CHitbox.java b/src/com/gnarly/engine/utils/CHitbox.java new file mode 100755 index 0000000..8666227 --- /dev/null +++ b/src/com/gnarly/engine/utils/CHitbox.java @@ -0,0 +1,55 @@ +package com.gnarly.engine.utils; + +import org.joml.Vector3f; + +public class CHitbox { + + private Vector3f center; + private float radius; + + public CHitbox(float x, float y, float radius) { + center = new Vector3f(x, y, 0); + this.radius = radius; + } + + public Vector3f collisionAdjust(CHitbox hitbox) { + Vector3f distance = hitbox.center.sub(center, new Vector3f()); + distance.x = (float)Math.abs(distance.x); + distance.y = (float)Math.abs(distance.y); + + if (2 * radius * radius < distance.lengthSquared()) { + float angle = (float) Math.asin((center.x - hitbox.center.x)/(center.y - hitbox.center.y)); + distance.x = (float) Math.cos(angle) * 2 * radius * radius; + distance.y = (float) Math.sin(angle) * 2 * radius * radius; + } + return distance; + } + + public boolean checkCollision(CHitbox hitbox) { + Vector3f distance = hitbox.center.sub(center, new Vector3f()); + distance.x = (float)Math.abs(distance.x); + distance.y = (float)Math.abs(distance.y); + return 2 * radius * radius < distance.lengthSquared(); + } + + public void setPosition(float x, float y) { + center.x = x; + center.y = y; + } + + public float getX() { + return center.x; + } + + public float getY() { + return center.y; + } + + public Vector3f getCenter() { + return center; + } + + public float radius() { + return radius; + } +} diff --git a/src/com/gnarly/engine/utils/Library.java b/src/com/gnarly/engine/utils/Library.java new file mode 100755 index 0000000..2cc873a --- /dev/null +++ b/src/com/gnarly/engine/utils/Library.java @@ -0,0 +1,86 @@ +package com.gnarly.engine.utils; + +import java.io.File; +import java.util.ArrayList; + +import com.gnarly.engine.components.Shader; +import com.gnarly.engine.components.Texture; + +public class Library { + + private static Texture[] textures; + private static Shader[] shaders; + private static File[] hitboxes; + + private Library() {} + + public static void init(String texStart, String shaderStart, String hitboxStart) { + loadTextures(texStart); + loadShaders(shaderStart); + loadHitboxes(hitboxStart); + } + + private static void loadTextures(String texStart) { + String[] paths = loadStructure(texStart); + textures = new Texture[paths.length]; + for (int i = 0; i < paths.length; i++) + textures[i] = new Texture(paths[i]); + } + + private static void loadShaders(String shaderStart) { + String[] paths = loadStructure(shaderStart); + shaders = new Shader[paths.length / 2]; + for (int i = 0; i < paths.length; i += 2) + shaders[i / 2] = new Shader(paths[i + 1], paths[i]); + } + + private static void loadHitboxes(String hitboxStart) { + String[] paths = loadStructure(hitboxStart); + hitboxes = new File[paths.length]; + for (int i = 0; i < paths.length; i++) + hitboxes[i] = new File(paths[i]); + } + + private static String[] loadStructure(String structureStart) { + ArrayList check = new ArrayList<>(); + ArrayList files = new ArrayList<>(); + check.add(structureStart); + while(check.size() > 0) { + File file = new File(check.get(0)); + String path = file.getPath(); + String[] paths = file.list(); + if(paths != null) { + for (int i = 0; i < paths.length; i++) + check.add(path + "/" + paths[i]); + } + else + files.add(path); + check.remove(0); + } + String[] ret = new String[files.size()]; + for (int i = 0; i < ret.length; i++) + ret[i] = files.get(i); + return ret; + } + + public static Texture getTexture(String name) { + for (int i = 0; i < textures.length; i++) + if(textures[i].getName().equals(name)) + return textures[i]; + throw new RuntimeException("Could not find texture: " + name + "!"); + } + + public static Shader getShader(String name) { + for (int i = 0; i < shaders.length; i++) + if(shaders[i].getName().equals(name)) + return shaders[i]; + throw new RuntimeException("Could not find shader: " + name + "!"); + } + + public static File getHitboxes(String name) { + for (int i = 0; i < hitboxes.length; i++) + if(hitboxes[i].getName().equals(name)) + return hitboxes[i]; + throw new RuntimeException("Could not find hitboxes: " + name + "!"); + } +} diff --git a/src/com/gnarly/engine/utils/MemoryUtils.java b/src/com/gnarly/engine/utils/MemoryUtils.java new file mode 100755 index 0000000..21f56ce --- /dev/null +++ b/src/com/gnarly/engine/utils/MemoryUtils.java @@ -0,0 +1,58 @@ +package com.gnarly.engine.utils; + +import static org.lwjgl.openal.AL10.alDeleteBuffers; +import static org.lwjgl.openal.AL10.alDeleteSources; +import static org.lwjgl.opengl.GL11.glDeleteTextures; +import static org.lwjgl.opengl.GL15.glDeleteBuffers; +import static org.lwjgl.opengl.GL20.glDeleteProgram; +import static org.lwjgl.opengl.GL20.glDeleteShader; + +import java.util.ArrayList; + +public class MemoryUtils { + + private static final byte numTypes = 6; + private static boolean init = false; + + public static final byte + AL_BUFFER = 0, + AL_SOURCE = 1, + GL_BUFFER = 2, + GL_PROGRAM = 3, + GL_SHADER = 4, + GL_TEXTURE = 5; + + private static ArrayList[] data; + + private MemoryUtils() {} + + private static void init() { + data = new ArrayList[numTypes]; + for (int i = 0; i < numTypes; i++) + data[i] = new ArrayList(); + init = true; + } + + public static void add(byte type, int num) { + if(!init) + init(); + data[type].add(num); + } + + public static void destroy() { + if(init) { + for (int i : data[AL_BUFFER]) + alDeleteBuffers(i); + for (int i : data[AL_SOURCE]) + alDeleteSources(i); + for (int i : data[GL_BUFFER]) + glDeleteBuffers(i); + for (int i : data[GL_PROGRAM]) + glDeleteProgram(i); + for (int i : data[GL_SHADER]) + glDeleteShader(i); + for (int i : data[GL_TEXTURE]) + glDeleteTextures(i); + } + } +} diff --git a/src/com/gnarly/engine/utils/RHitbox.java b/src/com/gnarly/engine/utils/RHitbox.java new file mode 100755 index 0000000..c00662f --- /dev/null +++ b/src/com/gnarly/engine/utils/RHitbox.java @@ -0,0 +1,99 @@ +package com.gnarly.engine.utils; + +import org.joml.Vector3f; + +public class RHitbox { + + private Vector3f center, halfExtent; + + public RHitbox(float x, float y, float width, float height) { + center = new Vector3f(x + width / 2, y + height / 2, 0); + halfExtent = new Vector3f(width / 2, height / 2, 0); + } + + public Vector3f collisionAdjust(RHitbox hitbox) { + Vector3f ret = new Vector3f(); + Vector3f distance = hitbox.center.sub(center, new Vector3f()); + distance.x = (float)Math.abs(distance.x); + distance.y = (float)Math.abs(distance.y); + + distance.sub(halfExtent.add(hitbox.getHalfExtent(), new Vector3f())); + if (distance.x < 0 && distance.y < 0) { + Vector3f correction = hitbox.getCenter().sub(center, new Vector3f()); + if(distance.x > distance.y) { + if(correction.x > 0) + ret.x = distance.x; + else + ret.x = -distance.x; + } + else if(distance.x < distance.y) { + if(correction.y > 0) + ret.y = distance.y; + else + ret.y = -distance.y; + } + else { + if(correction.x > 0) + ret.x = distance.x; + else + ret.x = -distance.x; + if(correction.y > 0) + ret.y = distance.y; + else + ret.y = -distance.y; + + } + } + return ret; + } + + public boolean checkCollision(RHitbox hitbox) { + Vector3f distance = hitbox.center.sub(center, new Vector3f()); + distance.x = (float)Math.abs(distance.x); + distance.y = (float)Math.abs(distance.y); + + distance.sub(halfExtent.add(hitbox.getHalfExtent(), new Vector3f())); + return (distance.x < 0 && distance.y < 0); + } + + public void setPosition(float x, float y) { + center.x = x + halfExtent.x; + center.y = y + halfExtent.y; + } + + public void translate(Vector3f translate) { + center.x += translate.x; + center.y += translate.y; + } + + public void setBounds(float width, float height) { + halfExtent.x = width / 2; + halfExtent.y = height / 2; + center.x += (width - halfExtent.x) / 2; + center.y += (height - halfExtent.y) / 2; + } + + public float getX() { + return center.x - halfExtent.x; + } + + public float getY() { + return center.y - halfExtent.y; + } + + public float getWidth() { + return halfExtent.x * 2; + } + + public float getHeight() { + return halfExtent.y * 2; + } + + public Vector3f getCenter() { + return center; + } + + public Vector3f getHalfExtent() { + return halfExtent; + } +} diff --git a/src/com/gnarly/game/Main.java b/src/com/gnarly/game/Main.java new file mode 100755 index 0000000..b97f674 --- /dev/null +++ b/src/com/gnarly/game/Main.java @@ -0,0 +1,83 @@ +package com.gnarly.game; + +import com.gnarly.engine.display.Camera; +import com.gnarly.engine.display.Window; +import com.gnarly.engine.utils.Library; +import com.gnarly.engine.utils.MemoryUtils; +import com.gnarly.game.panels.PlayPanel; + +public class Main implements Runnable { + + private final int UPS = 120; + private final int FPS = 120; + + private final int PIXEL = 5; + + private Window window; + private Camera camera; + private Thread gameLoop; + private PlayPanel panel; + + public Main() { + gameLoop = new Thread(this); + gameLoop.start(); + } + + public void run() { + init(); + float pastUTime = (float) System.nanoTime() / 1000000.0f; + float curUTime = 0.0f; + float mspu = 1000.0f / (float)UPS; + float pastFTime = pastUTime; + float curFTime = 0.0f; + float mspf = 1000.0f / (float)FPS; + float pastSec = pastUTime / 1000f; + float curSec = 0.0f; + int frames = 0; + int updates = 0; + while(!window.shouldClose()) { + curUTime = (float) System.nanoTime() / 1000000.0f; + curFTime = curUTime; + if(curUTime - pastUTime > mspu) { + update(); + pastUTime += mspu; + ++updates; + } + if(curFTime - pastFTime > mspf) { + render(); + pastFTime += mspf; + ++frames; + } + curSec = (float) System.nanoTime() / 1000000000.0f; + if(curSec - pastSec > 1.0f) { + System.out.println(frames); + frames = 0; + updates = 0; + pastSec += 1; + } + } + MemoryUtils.destroy(); + } + + private void init() { + camera = new Camera(1920 / PIXEL, 1080 / PIXEL); + window = new Window(true); + Library.init("res/img", "res/shaders", "res/hitboxes"); + panel = new PlayPanel(window, camera); + } + + private void update() { + window.update(); + panel.update(); + } + + private void render() { + window.clear(); + panel.render(); + window.swap(); + } + + public static void main(String[] args) { + new Main(); + } +} diff --git a/src/com/gnarly/game/objects/Character.java b/src/com/gnarly/game/objects/Character.java new file mode 100755 index 0000000..7acc808 --- /dev/null +++ b/src/com/gnarly/game/objects/Character.java @@ -0,0 +1,314 @@ +package com.gnarly.game.objects; + +import static org.lwjgl.glfw.GLFW.GLFW_KEY_A; +import static org.lwjgl.glfw.GLFW.GLFW_KEY_D; +import static org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_SHIFT; +import static org.lwjgl.glfw.GLFW.GLFW_KEY_S; +import static org.lwjgl.glfw.GLFW.GLFW_KEY_SPACE; + +import com.gnarly.engine.components.Animation; +import com.gnarly.engine.components.Shader; +import com.gnarly.engine.components.VAO; +import com.gnarly.engine.display.Camera; +import com.gnarly.engine.display.Window; +import com.gnarly.engine.utils.Library; +import com.gnarly.engine.utils.RHitbox; + +public class Character { + + private final boolean + LEFT = true, + RIGHT = false; + + private final int + IDLE = 0, + WALK = 1, + RUN = 2, + JUMP = 3, + FALL = 4; + + private final float + WALK_ACCEL = 1, + SPRINT_ACCEL = 2, + STRAFE_ACCEL = 0.05f, + WALK_SPEED = 1, + SPRINT_SPEED = 2, + STRAFE_SPEED = 0.8f, + GROUND_DECAY = 0.15f, + AERIAL_DECAY = 0.01f, + FASTFALL = 2.0f, + BOUNCE_SPEED = 6.0f, + BOUNCE_SCALE = 0.8f; + + private final float + GRAVITY = 0.1f, + MAX_GRAV = 8.0f; + + private final float + SHORT_HOP = 0.65f, + LONG_JUMP = 0.35f, + AERIAL_JUMP = 3.0f; + + private final int + NUM_JUMPS = 50, + MIN_JUMP = 4, + MAX_JUMP = 7; + + private float fallSpeed; + + private int state = 0; + + private float x, y, width, height, dx, dy; + + private boolean airborne = false; + private boolean dir = false; + + private int jump = 0; + private int jumps = 0; + private int jumpFrames = 0; + + private Animation anims[]; + private Shader shader; + private VAO right; + private VAO left; + private Camera camera; + private Window window; + private RHitbox rHitbox; + + public Character(Window window, Camera camera, String name, float x, float y) { + this.camera = camera; + this.window = window; + anims = new Animation[5]; + anims[IDLE] = new Animation(name + " idle", "png", 8, 10, true); + anims[WALK] = new Animation(name + " walk", "png", 9, 10, true); + anims[RUN] = new Animation(name + " run", "png", 4, 10, true); + anims[JUMP] = new Animation(name + " jump", "png", 6, 20, true); + anims[FALL] = new Animation(name + " fall", "png", 6, 20, true); + this.x = x; + this.y = y - anims[0].getHeight(); + width = anims[0].getWidth(); + height = anims[0].getHeight(); + shader = Library.getShader("default"); + rHitbox = new RHitbox(this.x, this.y, width, height); + float[] vertices = new float[] { + 0.0f, 0.0f, 0.5f, //TOP LEFT + 0.0f, height, 0.5f, //BOTTOM LEFT + width, height, 0.5f, //BOTTOM RIGHT + width, 0.0f, 0.5f //TOP RIGHT + }; + int[] indices = new int[] { + 0, 1, 3, + 1, 2, 3 + }; + float[] texCoords = new float[] { + 0, 0, + 0, 1, + 1, 1, + 1, 0 + }; + right = new VAO(vertices, indices, texCoords); + texCoords = new float[] { + 1, 0, + 1, 1, + 0, 1, + 0, 0 + }; + left = new VAO(vertices, indices, texCoords); + } + + public void update() { + boolean move = false; + if(window.isKeyPressed(GLFW_KEY_D)) { + move = true; + if(window.isKeyPressed(GLFW_KEY_LEFT_SHIFT) && !airborne && dx < 2) { + if(dx > 0) + dx += SPRINT_ACCEL; + else + dx += SPRINT_ACCEL / 20; + if(dx > SPRINT_SPEED) + dx = SPRINT_SPEED; + } + else if(!airborne && dx < 1) { + if(dx > 0) + dx += WALK_ACCEL; + else + dx += WALK_ACCEL / 20; + if(dx > WALK_SPEED) + dx = WALK_SPEED; + } + else if(dx < STRAFE_SPEED) + dx += STRAFE_ACCEL; + } + if(window.isKeyPressed(GLFW_KEY_A)) { + move = true; + if(window.isKeyPressed(GLFW_KEY_LEFT_SHIFT) && !airborne && dx > -2) { + if(dx < 0) + dx -= SPRINT_ACCEL; + else + dx -= SPRINT_ACCEL / 20; + if(dx < -SPRINT_SPEED) + dx = -SPRINT_SPEED; + } + else if(!airborne && dx > -1) { + if(dx < 0) + dx -= WALK_ACCEL; + else + dx -= WALK_ACCEL / 20; + if(dx < -WALK_SPEED) + dx = -WALK_SPEED; + } + else if(dx > -STRAFE_SPEED) + dx -= STRAFE_ACCEL; + } + if(window.isKeyPressed(GLFW_KEY_S) && airborne) { + if(dy > 0) + fallSpeed = FASTFALL; + dy += fallSpeed; + } + jump(); + updateAnim(); + if(dy < MAX_GRAV) { + if(dy + GRAVITY > MAX_GRAV) + dy = MAX_GRAV; + else + dy += GRAVITY; + } + x += dx; + y += dy; + anims[state].update(); + rHitbox.setPosition(x, y); + if(!move) { + if(!airborne && dx > 0) { + dx -= GROUND_DECAY; + if(dx < 0) + dx = 0; + } + else if(!airborne && dx < 0) { + dx += GROUND_DECAY; + if(dx > 0) + dx = 0; + } + } + else if(dx > 0) { + dx -= AERIAL_DECAY; + if(dx < 0) + dx = 0; + } + else if(dx < 0) { + dx += AERIAL_DECAY; + if(dx > 0) + dx = 0; + } + if(window.isKeyPressed(GLFW_KEY_S) && airborne) { + dy -= fallSpeed; + } + } + + public void render() { + shader.setUniformMat4f("projection", camera.getProjection().translate(x, y, 0)); + anims[state].bind(); + shader.enable(); + if(dir == RIGHT) + right.render(); + else if(dir == LEFT) + left.render(); + shader.disable(); + anims[state].unbind(); + } + + private void jump() { + if(airborne && jumps < 2) + jumps = 2; + if((window.isKeyPressed(GLFW_KEY_SPACE) || (jump > 0 && jump < 3)) && jumpFrames < MIN_JUMP) { + if(jump == 0) { + jump = 1; + if(dx > 1) + dx = 1; + else if(dx < -1) + dx = -1; + } + dy -= SHORT_HOP; + airborne = true; + } + else if(window.isKeyPressed(GLFW_KEY_SPACE) && jumpFrames < MAX_JUMP) + dy -= LONG_JUMP; + if(jump % 2 == 1 && !window.isKeyPressed(GLFW_KEY_SPACE)) + ++jump; + else if(jump % 2 == 0 && jump > 1 && window.isKeyPressed(GLFW_KEY_SPACE) && jumps < NUM_JUMPS) { + ++jump; + ++jumps; + dy = -AERIAL_JUMP; + if(window.isKeyPressed(GLFW_KEY_A)) + dx = -1f; + if(window.isKeyPressed(GLFW_KEY_D)) + dx = 1f; + } + if(jumps == 1) + jumpFrames = MAX_JUMP; + else if(jumpFrames < MAX_JUMP && jump > 0) + ++jumpFrames; + } + + private void updateAnim() { + int tAnim = 0; + if(!airborne) { + if(dx > 1 || dx < -1) + tAnim = RUN; + else if(dx > 0 || dx < 0) + tAnim = WALK; + else + tAnim = IDLE; + if(dx > 0) + dir = RIGHT; + else if(dx < 0) + dir = LEFT; + } + else if(airborne && dy <= 0) + tAnim = JUMP; + else if(airborne && dy > 0) + tAnim = FALL; + if(tAnim != state) { + anims[state].pause(); + anims[state].reset(); + anims[tAnim].play(); + state = tAnim; + } + } + + public void hitStage(boolean hit) { + if(!hit) + airborne = true; + else { + if(rHitbox.getX() != x) { + if(Math.abs(dx) < BOUNCE_SPEED) + dx = 0; + else + dx = -dx * BOUNCE_SCALE; + } + else if(rHitbox.getY() < y) { + if(Math.abs(dy) < BOUNCE_SPEED) { + fallSpeed = 0.2f; + dy = 0; + jump = 0; + jumpFrames = 0; + jumps = 0; + airborne = false; + } + else + dy = -dy * BOUNCE_SCALE; + } + else if(rHitbox.getY() > y) { + if(Math.abs(dy) < BOUNCE_SPEED) + dy = 0; + else + dy = -dy * BOUNCE_SCALE; + } + x = rHitbox.getX(); + y = rHitbox.getY(); + } + } + + public RHitbox getRHitbox() { + return rHitbox; + } +} diff --git a/src/com/gnarly/game/objects/Rectangle.java b/src/com/gnarly/game/objects/Rectangle.java new file mode 100755 index 0000000..d8e488f --- /dev/null +++ b/src/com/gnarly/game/objects/Rectangle.java @@ -0,0 +1,48 @@ +package com.gnarly.game.objects; + +import com.gnarly.engine.components.Shader; +import com.gnarly.engine.components.VAO; +import com.gnarly.engine.display.Camera; +import com.gnarly.engine.utils.Library; + +public class Rectangle { + + private float x, y, width, height; + + private Camera camera; + private Shader shader; + private VAO vao; + + public Rectangle(Camera camera, float x, float y, float width, float height) { + this.camera = camera; + this.x = x; + this.y = y; + this.width = width; + this.height = height; + shader = Library.getShader("shapes"); + float[] vertices = { + 0.0f, 0.0f, 1.0f, //TOP LEFT + 0.0f, height, 1.0f, //BOTTOM LEFT + width, height, 1.0f, //BOTTOM RIGHT + width, 0.0f, 1.0f //TOP RIGHT + }; + int[] indices = { + 0, 1, 3, + 1, 2, 3 + }; + float[] texCoords = { + 0, 0, + 0, 1, + 1, 1, + 1, 0 + }; + vao = new VAO(vertices, indices, texCoords); + } + + public void render() { + shader.setUniformMat4f("projection", camera.getProjection().translate(x, y, 0)); + shader.enable(); + vao.render(); + shader.disable(); + } +} diff --git a/src/com/gnarly/game/objects/Stage.java b/src/com/gnarly/game/objects/Stage.java new file mode 100755 index 0000000..d42b1b9 --- /dev/null +++ b/src/com/gnarly/game/objects/Stage.java @@ -0,0 +1,99 @@ +package com.gnarly.game.objects; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.ObjectInputStream; + +import org.joml.Matrix4f; +import org.joml.Vector3f; + +import com.gnarly.engine.components.Animation; +import com.gnarly.engine.components.Shader; +import com.gnarly.engine.components.VAO; +import com.gnarly.engine.display.Camera; +import com.gnarly.engine.utils.Library; +import com.gnarly.engine.utils.RHitbox; + +public class Stage { + + private float width, height, floor; + private Vector3f center; + + private VAO vao; + private Shader shader; + private Animation stage; + private RHitbox[] hitboxes; + private Camera camera; + + public Stage(Camera camera, String stageName) { + this.camera = camera; + stage = new Animation("mountain", "png", 1, 10, true); + shader = Library.getShader("default"); + width = stage.getWidth(); + height = stage.getHeight(); + try { + File hitboxFile = Library.getHitboxes(stageName + ".shb"); + ObjectInputStream input = new ObjectInputStream(new FileInputStream(hitboxFile)); + center = new Vector3f(input.readFloat(), input.readFloat(), 0); + hitboxes = new RHitbox[input.readInt()]; + for (int i = 0; i < hitboxes.length; i++) + hitboxes[i] = new RHitbox(input.readFloat(), input.readFloat(), input.readFloat(), input.readFloat()); + input.close(); + } catch(IOException e) { + e.printStackTrace(); + } + floor = hitboxes[0].getY(); + float[] vertices = { + 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 + }; + int[] indices = { + 0, 1, 3, + 1, 2, 3 + }; + float[] texCoords = { + 0, 0, + 0, 1, + 1, 1, + 1, 0 + }; + vao = new VAO(vertices, indices, texCoords); + } + + public void update() { + stage.update(); + } + + public void render() { + shader.setUniformMat4f("projection", camera.getProjection()); + stage.bind(); + shader.enable(); + vao.render(); + shader.disable(); + stage.unbind(); + } + + public boolean checkPlayer(RHitbox character) { + Vector3f translate = new Vector3f(); + for (int i = 0; i < hitboxes.length && translate.x == 0 && translate.y == 0; i++) + translate = character.collisionAdjust(hitboxes[i]); + if(translate.x != 0 || translate.y != 0) { + character.translate(translate); + checkPlayer(character); + return true; + } + else + return false; + } + + public float getFloor() { + return floor; + } + + public Vector3f getCenter() { + return center; + } +} diff --git a/src/com/gnarly/game/panels/PlayPanel.java b/src/com/gnarly/game/panels/PlayPanel.java new file mode 100755 index 0000000..c6ad528 --- /dev/null +++ b/src/com/gnarly/game/panels/PlayPanel.java @@ -0,0 +1,32 @@ +package com.gnarly.game.panels; + +import com.gnarly.engine.display.Camera; +import com.gnarly.engine.display.Window; +import com.gnarly.game.objects.Character; +import com.gnarly.game.objects.Stage; + +public class PlayPanel { + + private Stage stage; + private Camera camera; + private Character character; + + public PlayPanel(Window window, Camera camera) { + this.camera = camera; + stage = new Stage(camera, "mountain"); + character = new Character(window, camera, "blue stick", stage.getCenter().x, stage.getFloor()); + camera.setCenterPosition(stage.getCenter()); + } + + public void update() { + stage.update(); + character.update(); + boolean hit = stage.checkPlayer(character.getRHitbox()); + character.hitStage(hit); + } + + public void render() { + stage.render(); + character.render(); + } +}