Project as is
BIN
res/hitboxes/stages/mountain.shb
Executable file
BIN
res/img/characters/blue stick/fall/blue stick fall 1.png
Executable file
After Width: | Height: | Size: 319 B |
BIN
res/img/characters/blue stick/fall/blue stick fall 2.png
Executable file
After Width: | Height: | Size: 342 B |
BIN
res/img/characters/blue stick/fall/blue stick fall 3.png
Executable file
After Width: | Height: | Size: 339 B |
BIN
res/img/characters/blue stick/fall/blue stick fall 4.png
Executable file
After Width: | Height: | Size: 342 B |
BIN
res/img/characters/blue stick/fall/blue stick fall 5.png
Executable file
After Width: | Height: | Size: 328 B |
BIN
res/img/characters/blue stick/fall/blue stick fall 6.png
Executable file
After Width: | Height: | Size: 320 B |
BIN
res/img/characters/blue stick/idle/blue stick idle 1.png
Executable file
After Width: | Height: | Size: 208 B |
BIN
res/img/characters/blue stick/idle/blue stick idle 2.png
Executable file
After Width: | Height: | Size: 202 B |
BIN
res/img/characters/blue stick/idle/blue stick idle 3.png
Executable file
After Width: | Height: | Size: 203 B |
BIN
res/img/characters/blue stick/idle/blue stick idle 4.png
Executable file
After Width: | Height: | Size: 198 B |
BIN
res/img/characters/blue stick/idle/blue stick idle 5.png
Executable file
After Width: | Height: | Size: 203 B |
BIN
res/img/characters/blue stick/idle/blue stick idle 6.png
Executable file
After Width: | Height: | Size: 202 B |
BIN
res/img/characters/blue stick/idle/blue stick idle 7.png
Executable file
After Width: | Height: | Size: 208 B |
BIN
res/img/characters/blue stick/idle/blue stick idle 8.png
Executable file
After Width: | Height: | Size: 199 B |
BIN
res/img/characters/blue stick/jump/blue stick jump 1.png
Executable file
After Width: | Height: | Size: 334 B |
BIN
res/img/characters/blue stick/jump/blue stick jump 2.png
Executable file
After Width: | Height: | Size: 350 B |
BIN
res/img/characters/blue stick/jump/blue stick jump 3.png
Executable file
After Width: | Height: | Size: 353 B |
BIN
res/img/characters/blue stick/jump/blue stick jump 4.png
Executable file
After Width: | Height: | Size: 350 B |
BIN
res/img/characters/blue stick/jump/blue stick jump 5.png
Executable file
After Width: | Height: | Size: 336 B |
BIN
res/img/characters/blue stick/jump/blue stick jump 6.png
Executable file
After Width: | Height: | Size: 328 B |
BIN
res/img/characters/blue stick/run/blue stick run 1.png
Executable file
After Width: | Height: | Size: 288 B |
BIN
res/img/characters/blue stick/run/blue stick run 2.png
Executable file
After Width: | Height: | Size: 300 B |
BIN
res/img/characters/blue stick/run/blue stick run 3.png
Executable file
After Width: | Height: | Size: 303 B |
BIN
res/img/characters/blue stick/run/blue stick run 4.png
Executable file
After Width: | Height: | Size: 308 B |
BIN
res/img/characters/blue stick/run/blue stick run 5.png
Executable file
After Width: | Height: | Size: 292 B |
BIN
res/img/characters/blue stick/walk/blue stick walk 1.png
Executable file
After Width: | Height: | Size: 237 B |
BIN
res/img/characters/blue stick/walk/blue stick walk 2.png
Executable file
After Width: | Height: | Size: 245 B |
BIN
res/img/characters/blue stick/walk/blue stick walk 3.png
Executable file
After Width: | Height: | Size: 249 B |
BIN
res/img/characters/blue stick/walk/blue stick walk 4.png
Executable file
After Width: | Height: | Size: 251 B |
BIN
res/img/characters/blue stick/walk/blue stick walk 5.png
Executable file
After Width: | Height: | Size: 254 B |
BIN
res/img/characters/blue stick/walk/blue stick walk 6.png
Executable file
After Width: | Height: | Size: 252 B |
BIN
res/img/characters/blue stick/walk/blue stick walk 7.png
Executable file
After Width: | Height: | Size: 254 B |
BIN
res/img/characters/blue stick/walk/blue stick walk 8.png
Executable file
After Width: | Height: | Size: 244 B |
BIN
res/img/characters/blue stick/walk/blue stick walk 9.png
Executable file
After Width: | Height: | Size: 236 B |
BIN
res/img/stages/mountain/mountain 1.png
Executable file
After Width: | Height: | Size: 4.5 KiB |
9
res/shaders/default/default.fs
Executable file
|
@ -0,0 +1,9 @@
|
|||
#version 450
|
||||
|
||||
uniform sampler2D sampler;
|
||||
|
||||
in vec2 textureCoords;
|
||||
|
||||
void main() {
|
||||
gl_FragColor = texture2D(sampler, textureCoords);
|
||||
}
|
13
res/shaders/default/default.vs
Executable file
|
@ -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);
|
||||
}
|
5
res/shaders/shapes/shapes.fs
Executable file
|
@ -0,0 +1,5 @@
|
|||
#version 450
|
||||
|
||||
void main() {
|
||||
gl_FragColor = vec4(0, 1, 1, 0.5);
|
||||
}
|
9
res/shaders/shapes/shapes.vs
Executable file
|
@ -0,0 +1,9 @@
|
|||
#version 450
|
||||
|
||||
uniform mat4 projection;
|
||||
|
||||
in vec3 vertices;
|
||||
|
||||
void main() {
|
||||
gl_Position = projection * vec4(vertices, 1);
|
||||
}
|
74
src/com/gnarly/engine/components/Animation.java
Executable file
|
@ -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();
|
||||
}
|
||||
}
|
153
src/com/gnarly/engine/components/Shader.java
Executable file
|
@ -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<String, Integer> 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);
|
||||
}
|
||||
}
|
89
src/com/gnarly/engine/components/Texture.java
Executable file
|
@ -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);
|
||||
}
|
||||
}
|
87
src/com/gnarly/engine/components/VAO.java
Executable file
|
@ -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;
|
||||
}
|
||||
}
|
82
src/com/gnarly/engine/display/Camera.java
Executable file
|
@ -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;
|
||||
}
|
||||
}
|
178
src/com/gnarly/engine/display/Window.java
Executable file
|
@ -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;
|
||||
}
|
||||
}
|
55
src/com/gnarly/engine/utils/CHitbox.java
Executable file
|
@ -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;
|
||||
}
|
||||
}
|
86
src/com/gnarly/engine/utils/Library.java
Executable file
|
@ -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<String> check = new ArrayList<>();
|
||||
ArrayList<String> 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 + "!");
|
||||
}
|
||||
}
|
58
src/com/gnarly/engine/utils/MemoryUtils.java
Executable file
|
@ -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<Integer>[] data;
|
||||
|
||||
private MemoryUtils() {}
|
||||
|
||||
private static void init() {
|
||||
data = new ArrayList[numTypes];
|
||||
for (int i = 0; i < numTypes; i++)
|
||||
data[i] = new ArrayList<Integer>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
99
src/com/gnarly/engine/utils/RHitbox.java
Executable file
|
@ -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;
|
||||
}
|
||||
}
|
83
src/com/gnarly/game/Main.java
Executable file
|
@ -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();
|
||||
}
|
||||
}
|
314
src/com/gnarly/game/objects/Character.java
Executable file
|
@ -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;
|
||||
}
|
||||
}
|
48
src/com/gnarly/game/objects/Rectangle.java
Executable file
|
@ -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();
|
||||
}
|
||||
}
|
99
src/com/gnarly/game/objects/Stage.java
Executable file
|
@ -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;
|
||||
}
|
||||
}
|
32
src/com/gnarly/game/panels/PlayPanel.java
Executable file
|
@ -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();
|
||||
}
|
||||
}
|