Added parallax background, ship, and firing. Collision is WIP
BIN
res/img/background/background-layer-0.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
res/img/background/background-layer-1.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
res/img/bullets/bullet-0/bullet-0.png
Normal file
After Width: | Height: | Size: 177 B |
BIN
res/img/bullets/bullet-0/bullet-1.png
Normal file
After Width: | Height: | Size: 166 B |
BIN
res/img/bullets/bullet-0/bullet-2.png
Normal file
After Width: | Height: | Size: 176 B |
BIN
res/img/bullets/bullet-0/bullet-3.png
Normal file
After Width: | Height: | Size: 161 B |
Before Width: | Height: | Size: 553 B |
BIN
res/img/player-ship/player-ship-0.png
Normal file
After Width: | Height: | Size: 544 B |
BIN
res/img/player-ship/player-ship-1.png
Normal file
After Width: | Height: | Size: 543 B |
BIN
res/img/player-ship/player-ship-2.png
Normal file
After Width: | Height: | Size: 537 B |
BIN
res/img/player-ship/player-ship-3.png
Normal file
After Width: | Height: | Size: 543 B |
19
res/shaders/s2b/frag.gls
Normal file
|
@ -0,0 +1,19 @@
|
|||
#version 330 core
|
||||
|
||||
uniform sampler2D layer0;
|
||||
uniform sampler2D layer1;
|
||||
|
||||
uniform float offset0 = 1;
|
||||
uniform float offset1 = 1;
|
||||
|
||||
in vec2 texCoords;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
void main() {
|
||||
vec4 color0 = texture(layer0, texCoords + vec2(0, offset0));
|
||||
vec4 color1 = texture(layer1, texCoords + vec2(0, offset1));
|
||||
color = mix(color0, color1, 1 - color0.a);
|
||||
if (color.a == 0)
|
||||
discard;
|
||||
}
|
13
res/shaders/s2b/vert.gls
Normal file
|
@ -0,0 +1,13 @@
|
|||
#version 330 core
|
||||
|
||||
uniform mat4 mvp;
|
||||
|
||||
layout (location = 0) in vec3 vertices;
|
||||
layout (location = 1) in vec2 itexCoords;
|
||||
|
||||
out vec2 texCoords;
|
||||
|
||||
void main() {
|
||||
texCoords = itexCoords;
|
||||
gl_Position = mvp * vec4(vertices, 1);
|
||||
}
|
|
@ -2,20 +2,12 @@
|
|||
|
||||
uniform sampler2D sampler;
|
||||
|
||||
uniform vec4 iColor = vec4(1, 1, 1, 1);
|
||||
uniform float alpha = 1;
|
||||
uniform float amount = 1;
|
||||
|
||||
in vec2 texCoords;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
void main() {
|
||||
vec4 texColor = texture(sampler, texCoords);
|
||||
if(texColor.a == 0)
|
||||
discard;
|
||||
else {
|
||||
color = mix(iColor, texColor, amount);
|
||||
color.a = color.a * alpha;
|
||||
}
|
||||
color = texture(sampler, texCoords);
|
||||
if (color.a == 0)
|
||||
discard;
|
||||
}
|
|
@ -1,39 +1,6 @@
|
|||
package com.gnarly.engine.display;
|
||||
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_CONTEXT_VERSION_MAJOR;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_CONTEXT_VERSION_MINOR;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_DECORATED;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_FALSE;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_KEY_LAST;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_MAXIMIZED;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_MOUSE_BUTTON_LAST;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_OPENGL_CORE_PROFILE;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_OPENGL_FORWARD_COMPAT;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_OPENGL_PROFILE;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_PRESS;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_RELEASE;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_REPEAT;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_RESIZABLE;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_SAMPLES;
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_TRUE;
|
||||
import static org.lwjgl.glfw.GLFW.glfwCreateWindow;
|
||||
import static org.lwjgl.glfw.GLFW.glfwGetCursorPos;
|
||||
import static org.lwjgl.glfw.GLFW.glfwGetPrimaryMonitor;
|
||||
import static org.lwjgl.glfw.GLFW.glfwGetVideoMode;
|
||||
import static org.lwjgl.glfw.GLFW.glfwGetWindowSize;
|
||||
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.glfwSetErrorCallback;
|
||||
import static org.lwjgl.glfw.GLFW.glfwSetKeyCallback;
|
||||
import static org.lwjgl.glfw.GLFW.glfwSetMouseButtonCallback;
|
||||
import static org.lwjgl.glfw.GLFW.glfwSetWindowShouldClose;
|
||||
import static org.lwjgl.glfw.GLFW.glfwSetWindowSizeCallback;
|
||||
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.glfw.GLFW.*;
|
||||
import static org.lwjgl.opengl.GL.createCapabilities;
|
||||
import static org.lwjgl.opengl.GL11.GL_BLEND;
|
||||
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
|
||||
|
@ -55,12 +22,11 @@ import org.lwjgl.glfw.GLFWErrorCallback;
|
|||
import org.lwjgl.glfw.GLFWVidMode;
|
||||
|
||||
public class Window {
|
||||
|
||||
public static String resolution;
|
||||
|
||||
public static int
|
||||
SCREEN_WIDTH,
|
||||
SCREEN_HEIGHT;
|
||||
SCREEN_HEIGHT,
|
||||
REFRESH_RATE;
|
||||
|
||||
public static final int
|
||||
BUTTON_RELEASED = 0,
|
||||
|
@ -115,6 +81,7 @@ public class Window {
|
|||
SCREEN_WIDTH = vidMode.width();
|
||||
SCREEN_HEIGHT = vidMode.height();
|
||||
SCALE = SCREEN_HEIGHT / 1080f;
|
||||
REFRESH_RATE = vidMode.refreshRate();
|
||||
if(lwidth == 0 || lheight == 0) {
|
||||
width = vidMode.width();
|
||||
height = vidMode.height();
|
||||
|
@ -168,22 +135,13 @@ public class Window {
|
|||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||
|
||||
int[] awidth = new int[1], aheight = new int[1];
|
||||
glfwGetWindowSize(window, awidth, aheight);
|
||||
width = awidth[0];
|
||||
height = aheight[0];
|
||||
|
||||
if(SCREEN_HEIGHT > 2160)
|
||||
resolution = "8k";
|
||||
else if(SCREEN_HEIGHT > 1440)
|
||||
resolution = "4k";
|
||||
else if(SCREEN_HEIGHT > 1080)
|
||||
resolution = "1440p";
|
||||
else if(SCREEN_HEIGHT > 720)
|
||||
resolution = "1080p";
|
||||
else
|
||||
resolution = "720p";
|
||||
}
|
||||
|
||||
public void update() {
|
||||
|
@ -198,9 +156,9 @@ public class Window {
|
|||
}
|
||||
|
||||
public void activateClearColor() {
|
||||
glClearColor(0, 0, 0, 1);
|
||||
glClearColor(0, 0, 0.02f, 1);
|
||||
}
|
||||
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,11 @@ public class Rect {
|
|||
public float getY() {
|
||||
return position.y;
|
||||
}
|
||||
|
||||
|
||||
public Vector2f getPosition() {
|
||||
return new Vector2f(position.x, position.y);
|
||||
}
|
||||
|
||||
public float getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
@ -61,6 +65,10 @@ public class Rect {
|
|||
public float getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public Vector2f getDimensions() {
|
||||
return new Vector2f(width, height);
|
||||
}
|
||||
|
||||
public void setX(float x) {
|
||||
position.x = x;
|
||||
|
|
|
@ -13,12 +13,6 @@ public class TexRect extends Rect {
|
|||
private Texture texture;
|
||||
private Shader2t shader = Shader.SHADER2T;
|
||||
protected float direction = 1;
|
||||
private float alpha = 1;
|
||||
private float r;
|
||||
private float g;
|
||||
private float b;
|
||||
private float a;
|
||||
private float amount = 1;
|
||||
|
||||
public TexRect(Camera camera, String path, float x, float y, float z, float width, float height, float rotation, boolean gui) {
|
||||
super(camera, x, y, z, width, height, rotation, gui);
|
||||
|
@ -35,8 +29,6 @@ public class TexRect extends Rect {
|
|||
shader.enable();
|
||||
Matrix4f cmat = gui ? camera.getProjection() : camera.getMatrix();
|
||||
shader.setMVP(cmat.translate(position.add(width * scale / 2, height * scale / 2, 0, new Vector3f())).rotateZ(rotation).scale(width * scale * direction, height * scale, 1).translate(-0.5f, -0.5f, 0));
|
||||
shader.setAlpha(alpha);
|
||||
shader.setMixColor(r, g, b, a, amount);
|
||||
vao.render();
|
||||
shader.disable();
|
||||
texture.unbind();
|
||||
|
@ -50,20 +42,4 @@ public class TexRect extends Rect {
|
|||
public void setTexture(Texture texture) {
|
||||
this.texture = texture;
|
||||
}
|
||||
|
||||
public void setMix(float r, float g, float b, float a, float amount) {
|
||||
this.r = r;
|
||||
this.g = g;
|
||||
this.b = b;
|
||||
this.a = a;
|
||||
this.amount = 1 - amount;
|
||||
}
|
||||
|
||||
public void setAlpha(float alpha) {
|
||||
this.alpha = alpha;
|
||||
}
|
||||
|
||||
public float getAlpha() {
|
||||
return alpha;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,8 +27,9 @@ import org.joml.Matrix4f;
|
|||
|
||||
public abstract class Shader {
|
||||
|
||||
public static Shader2c SHADER2C;
|
||||
public static Shader2t SHADER2T;
|
||||
public static Shader2c SHADER2C;
|
||||
public static Shader2t SHADER2T;
|
||||
public static Shader2b SHADER2B;
|
||||
|
||||
protected int program;
|
||||
|
||||
|
@ -93,7 +94,8 @@ public abstract class Shader {
|
|||
}
|
||||
|
||||
public static void init() {
|
||||
SHADER2C = new Shader2c();
|
||||
SHADER2T = new Shader2t();
|
||||
SHADER2C = new Shader2c();
|
||||
SHADER2T = new Shader2t();
|
||||
SHADER2B = new Shader2b();
|
||||
}
|
||||
}
|
||||
|
|
32
src/com/gnarly/engine/shaders/Shader2b.java
Normal file
|
@ -0,0 +1,32 @@
|
|||
package com.gnarly.engine.shaders;
|
||||
|
||||
import static org.lwjgl.opengl.GL20.*;
|
||||
|
||||
public class Shader2b extends Shader {
|
||||
|
||||
private int offset0Loc;
|
||||
private int offset1Loc;
|
||||
|
||||
protected Shader2b() {
|
||||
super("res/shaders/s2b/vert.gls", "res/shaders/s2b/frag.gls");
|
||||
getUniforms();
|
||||
}
|
||||
|
||||
public void setOffset(float offset0, float offset1) {
|
||||
glUniform1f(offset0Loc, offset0);
|
||||
glUniform1f(offset1Loc, offset1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getUniforms() {
|
||||
offset0Loc = glGetUniformLocation(program, "offset0");
|
||||
offset1Loc = glGetUniformLocation(program, "offset1");
|
||||
|
||||
int layer0 = glGetUniformLocation(program, "layer0");
|
||||
int layer1 = glGetUniformLocation(program, "layer1");
|
||||
|
||||
enable();
|
||||
glUniform1i(layer0, 0);
|
||||
glUniform1i(layer1, 1);
|
||||
}
|
||||
}
|
|
@ -1,33 +1,12 @@
|
|||
package com.gnarly.engine.shaders;
|
||||
|
||||
import static org.lwjgl.opengl.GL20.glGetUniformLocation;
|
||||
import static org.lwjgl.opengl.GL20.glUniform1f;
|
||||
import static org.lwjgl.opengl.GL20.glUniform4f;
|
||||
|
||||
public class Shader2t extends Shader {
|
||||
|
||||
private int alphaLoc;
|
||||
private int colorLoc;
|
||||
private int amountLoc;
|
||||
|
||||
protected Shader2t() {
|
||||
super("res/shaders/s2t/vert.gls", "res/shaders/s2t/frag.gls");
|
||||
getUniforms();
|
||||
}
|
||||
|
||||
public void setMixColor(float r, float g, float b, float a, float amount) {
|
||||
glUniform4f(colorLoc, r, g, b, a);
|
||||
glUniform1f(amountLoc, amount);
|
||||
}
|
||||
|
||||
public void setAlpha(float a) {
|
||||
glUniform1f(alphaLoc, a);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getUniforms() {
|
||||
alphaLoc = glGetUniformLocation(program, "alpha");
|
||||
colorLoc = glGetUniformLocation(program, "iColor");
|
||||
amountLoc = glGetUniformLocation(program, "amount");
|
||||
}
|
||||
protected void getUniforms() {}
|
||||
}
|
|
@ -1,20 +1,5 @@
|
|||
package com.gnarly.engine.texture;
|
||||
|
||||
import static org.lwjgl.opengl.GL11.GL_CLAMP;
|
||||
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_TEXTURE_WRAP_S;
|
||||
import static org.lwjgl.opengl.GL11.GL_TEXTURE_WRAP_T;
|
||||
import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE;
|
||||
import static org.lwjgl.opengl.GL11.glBindTexture;
|
||||
import static org.lwjgl.opengl.GL11.glDeleteTextures;
|
||||
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;
|
||||
|
@ -26,20 +11,24 @@ import org.lwjgl.BufferUtils;
|
|||
|
||||
import com.gnarly.engine.display.Window;
|
||||
|
||||
import static org.lwjgl.opengl.GL11.*;
|
||||
import static org.lwjgl.opengl.GL13.GL_TEXTURE0;
|
||||
import static org.lwjgl.opengl.GL13.glActiveTexture;
|
||||
|
||||
public class Texture {
|
||||
|
||||
protected int id, width, height;
|
||||
|
||||
|
||||
public Texture(String name) {
|
||||
this(name, GL_CLAMP);
|
||||
}
|
||||
|
||||
public Texture(String name, int wrap) {
|
||||
BufferedImage bi = null;
|
||||
try {
|
||||
bi = ImageIO.read(new File("res/img/" + Window.resolution + "/" + name));
|
||||
bi = ImageIO.read(new File(name));
|
||||
} catch (IOException e) {
|
||||
try {
|
||||
bi = ImageIO.read(new File("res/img/const/" + name));
|
||||
} catch (IOException ex) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (bi != null) {
|
||||
width = bi.getWidth();
|
||||
|
@ -57,13 +46,13 @@ public class Texture {
|
|||
}
|
||||
}
|
||||
buffer.flip();
|
||||
|
||||
|
||||
id = glGenTextures();
|
||||
bind();
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
|
||||
unbind();
|
||||
}
|
||||
|
@ -82,8 +71,13 @@ public class Texture {
|
|||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
|
||||
public void bind() {
|
||||
bind(0);
|
||||
}
|
||||
|
||||
public void bind(int activeTexture) {
|
||||
glActiveTexture(GL_TEXTURE0 + activeTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, id);
|
||||
}
|
||||
|
||||
|
|
20
src/com/gnarly/engine/texture/TextureSet.java
Normal file
|
@ -0,0 +1,20 @@
|
|||
package com.gnarly.engine.texture;
|
||||
|
||||
public class TextureSet {
|
||||
|
||||
private Texture[] textures;
|
||||
|
||||
public TextureSet(String[] paths) {
|
||||
textures = new Texture[paths.length];
|
||||
for (int i = 0; i < textures.length; ++i)
|
||||
textures[i] = new Texture(paths[i]);
|
||||
}
|
||||
|
||||
public int length() {
|
||||
return textures.length;
|
||||
}
|
||||
|
||||
public Texture get(int index) {
|
||||
return textures[index];
|
||||
}
|
||||
}
|
47
src/com/gnarly/game/Background.java
Normal file
|
@ -0,0 +1,47 @@
|
|||
package com.gnarly.game;
|
||||
|
||||
import com.gnarly.engine.model.Rect;
|
||||
import com.gnarly.engine.shaders.Shader2b;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import com.gnarly.engine.display.Camera;
|
||||
import com.gnarly.engine.shaders.Shader;
|
||||
import com.gnarly.engine.shaders.Shader2t;
|
||||
import com.gnarly.engine.texture.Texture;
|
||||
|
||||
import static org.lwjgl.opengl.GL11.GL_REPEAT;
|
||||
|
||||
public class Background extends Rect {
|
||||
|
||||
private Texture layer0;
|
||||
private Texture layer1;
|
||||
private Shader2b shader = Shader.SHADER2B;
|
||||
private float offset;
|
||||
|
||||
private double speed = -0.25;
|
||||
|
||||
public Background(Camera camera) {
|
||||
super(camera, 0, 0, -0.5f, camera.getWidth(), camera.getHeight(), 0, false);
|
||||
layer0 = new Texture("res/img/background/background-layer-0.png", GL_REPEAT);
|
||||
layer1 = new Texture("res/img/background/background-layer-1.png", GL_REPEAT);
|
||||
}
|
||||
|
||||
public void update() {
|
||||
offset = (float) (offset + speed * Main.dtime) % 2;
|
||||
}
|
||||
|
||||
public void render() {
|
||||
layer0.bind(0);
|
||||
layer1.bind(1);
|
||||
shader.enable();
|
||||
shader.setOffset(offset, offset * 0.5f);
|
||||
shader.setMVP(camera.getMatrix().translate(position).scale(width * scale, height * scale, 1));
|
||||
vao.render();
|
||||
}
|
||||
|
||||
public void setCenter(float x, float y) {
|
||||
position.x = x - width / 2;
|
||||
position.y = y - height / 2;
|
||||
}
|
||||
}
|
188
src/com/gnarly/game/BulletList.java
Normal file
|
@ -0,0 +1,188 @@
|
|||
package com.gnarly.game;
|
||||
|
||||
import com.gnarly.engine.display.Camera;
|
||||
import com.gnarly.engine.model.ColRect;
|
||||
import com.gnarly.engine.model.Rect;
|
||||
import com.gnarly.engine.model.Vao;
|
||||
import com.gnarly.engine.shaders.Shader;
|
||||
import com.gnarly.engine.shaders.Shader2t;
|
||||
import com.gnarly.engine.texture.TextureSet;
|
||||
import org.joml.Vector2f;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class BulletList {
|
||||
|
||||
private static final double SPF = 1.0 / 20.0;
|
||||
|
||||
private static TextureSet[] sprites = null;
|
||||
private static Vao vao;
|
||||
private Shader2t shader = Shader.SHADER2T;
|
||||
|
||||
public static class Bullet {
|
||||
public double lifetime;
|
||||
public int sprite;
|
||||
public Vector2f position;
|
||||
public Vector2f side0;
|
||||
public Vector2f side1;
|
||||
public Vector2f velocity;
|
||||
|
||||
public float width;
|
||||
public float height;
|
||||
public float rotation;
|
||||
|
||||
public Vector2f boundingPosition;
|
||||
public Vector2f bounds;
|
||||
}
|
||||
|
||||
public static final Vector2f[] DIMENSIONS = new Vector2f[] {
|
||||
new Vector2f(4, -8)
|
||||
};
|
||||
|
||||
public static final float[] SPEEDS = new float[] {
|
||||
20
|
||||
};
|
||||
|
||||
public static final int
|
||||
TYPE_PLAYER = 0x00;
|
||||
|
||||
private Camera camera;
|
||||
|
||||
private ArrayList<Bullet> bullets;
|
||||
|
||||
public BulletList(Camera camera) {
|
||||
this.camera = camera;
|
||||
bullets = new ArrayList<>();
|
||||
|
||||
if (sprites == null) {
|
||||
sprites = new TextureSet[1];
|
||||
sprites[0] = new TextureSet(new String[] {
|
||||
"res/img/bullets/bullet-0/bullet-0.png",
|
||||
"res/img/bullets/bullet-0/bullet-1.png",
|
||||
"res/img/bullets/bullet-0/bullet-2.png",
|
||||
"res/img/bullets/bullet-0/bullet-3.png",
|
||||
});
|
||||
float vertices[] = {
|
||||
1, 1, 0, // Top left
|
||||
1, 0, 0, // Bottom left
|
||||
0, 0, 0, // Bottom right
|
||||
0, 1, 0 // Top right
|
||||
};
|
||||
int indices[] = {
|
||||
0, 1, 3,
|
||||
1, 2, 3
|
||||
};
|
||||
float[] texCoords = {
|
||||
1, 0,
|
||||
1, 1,
|
||||
0, 1,
|
||||
0, 0
|
||||
};
|
||||
vao = new Vao(vertices, indices);
|
||||
vao.addAttrib(texCoords, 2);
|
||||
}
|
||||
}
|
||||
|
||||
public void update(Rect rect, Vector2f velocity) {
|
||||
for (int i = 0; i < bullets.size(); ++i) {
|
||||
Bullet bullet = bullets.get(i);
|
||||
Vector2f deltaV = bullet.velocity.mul((float) Main.dtime, new Vector2f());
|
||||
if (Collision.collide(rect.getPosition(), rect.getDimensions(), velocity, bullet))
|
||||
System.out.println("collision");
|
||||
bullet.position.add(deltaV);
|
||||
bullet.boundingPosition.add(deltaV);
|
||||
bullet.lifetime += Main.dtime;
|
||||
|
||||
if (bullet.boundingPosition.x > camera.getWidth() || bullet.boundingPosition.y > camera.getHeight()
|
||||
|| bullet.boundingPosition.x + bullet.bounds.x < 0 || bullet.boundingPosition.y + bullet.bounds.y < 0) {
|
||||
bullets.remove(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void render() {
|
||||
for (int i = 0; i < bullets.size(); ++i) {
|
||||
Bullet bullet = bullets.get(i);
|
||||
sprites[bullet.sprite].get((int) (bullet.lifetime / SPF) % sprites[bullet.sprite].length()).bind();
|
||||
shader.enable();
|
||||
shader.setMVP(camera.getMatrix().translate(bullet.position.x, bullet.position.y, -0.25f).rotateZ(bullet.rotation).scale(bullet.width, bullet.height, 1));
|
||||
vao.render();
|
||||
}
|
||||
}
|
||||
|
||||
public void spawnBullet(Vector2f position, float rotation, int type) {
|
||||
spawnBullet(position, DIMENSIONS[type], rotation, SPEEDS[type], type);
|
||||
}
|
||||
|
||||
private void spawnBullet(Vector2f position, Vector2f dimensions, float rotation, float velocity, int sprite) {
|
||||
float sin = (float) -Math.sin(rotation);
|
||||
float cos = (float) Math.cos(rotation);
|
||||
|
||||
float initialPosition = -dimensions.x / 2;
|
||||
|
||||
/**************************************
|
||||
* *
|
||||
* 2D Rotations *
|
||||
* *
|
||||
**************************************
|
||||
* *
|
||||
* x + yi * cos + sini *
|
||||
* (xcos - ysin) + (xsin + ycos)i *
|
||||
* *
|
||||
**************************************/
|
||||
Bullet bullet = new Bullet();
|
||||
bullet.position = new Vector2f(initialPosition * cos, initialPosition * sin);
|
||||
bullet.position.add(position);
|
||||
bullet.side0 = new Vector2f( dimensions.x * cos, dimensions.x * sin);
|
||||
bullet.side1 = new Vector2f(-dimensions.y * sin, dimensions.y * cos);
|
||||
bullet.velocity = new Vector2f(velocity * sin, -velocity * cos);
|
||||
|
||||
bullet.width = dimensions.x;
|
||||
bullet.height = dimensions.y;
|
||||
bullet.rotation = -rotation;
|
||||
|
||||
bullet.lifetime = 0;
|
||||
bullet.sprite = sprite;
|
||||
|
||||
Vector2f p0 = new Vector2f(bullet.position);
|
||||
Vector2f p1 = new Vector2f(bullet.position).add(bullet.side0);
|
||||
Vector2f p2 = new Vector2f(bullet.position).add(bullet.side1);
|
||||
Vector2f p3 = new Vector2f(bullet.position).add(bullet.side0).add(bullet.side1);
|
||||
|
||||
bullet.boundingPosition = new Vector2f(
|
||||
min(new float[]{ p0.x, p1.x, p2.x, p3.x }),
|
||||
min(new float[]{ p0.y, p1.y, p2.y, p3.y })
|
||||
);
|
||||
bullet.bounds = new Vector2f(
|
||||
max(new float[]{ p0.x, p1.x, p2.x, p3.x }),
|
||||
max(new float[]{ p0.y, p1.y, p2.y, p3.y })
|
||||
).sub(bullet.boundingPosition);
|
||||
|
||||
bullets.add(bullet);
|
||||
}
|
||||
|
||||
public float getWidth(int type) {
|
||||
return DIMENSIONS[type].x;
|
||||
}
|
||||
|
||||
public float getHeight(int type) {
|
||||
return DIMENSIONS[type].y;
|
||||
}
|
||||
|
||||
private float min(float[] nums) {
|
||||
float min = nums[0];
|
||||
for (int i = 1; i < nums.length; ++i)
|
||||
if (nums[i] < min)
|
||||
min = nums[i];
|
||||
return min;
|
||||
}
|
||||
|
||||
private float max(float[] nums) {
|
||||
float max = nums[0];
|
||||
for (int i = 1; i < nums.length; ++i)
|
||||
if (nums[i] > max)
|
||||
max = nums[i];
|
||||
return max;
|
||||
}
|
||||
}
|
103
src/com/gnarly/game/Collision.java
Normal file
|
@ -0,0 +1,103 @@
|
|||
package com.gnarly.game;
|
||||
|
||||
import org.joml.Vector2f;
|
||||
|
||||
public class Collision {
|
||||
public static class Bounds {
|
||||
public Vector2f position;
|
||||
public Vector2f dimensions;
|
||||
|
||||
public Bounds(Vector2f position, Vector2f dimensions) {
|
||||
this.position = new Vector2f(position);
|
||||
this.dimensions = new Vector2f(dimensions);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean collide(Vector2f position, Vector2f dimensions, Vector2f boundVelocity, BulletList.Bullet bullet) {
|
||||
Bounds bounds = getBounds(position, dimensions, boundVelocity);
|
||||
Bounds bulletBounds = getBounds(bullet.boundingPosition, bullet.bounds, bullet.velocity);
|
||||
if (overlap(bounds, bulletBounds)) {
|
||||
Vector2f[] boundsSegments = new Vector2f[] {
|
||||
position,
|
||||
new Vector2f( dimensions.x, 0),
|
||||
new Vector2f( 0, dimensions.y),
|
||||
new Vector2f(-dimensions.x, 0),
|
||||
new Vector2f( 0, -dimensions.y)
|
||||
};
|
||||
Vector2f[] bulletSegments = new Vector2f[] {
|
||||
bullet.position,
|
||||
bullet.side0,
|
||||
bullet.side1,
|
||||
bullet.side0.negate(new Vector2f()),
|
||||
bullet.side1.negate(new Vector2f())
|
||||
};
|
||||
Vector2f curBoundsSegment = new Vector2f();
|
||||
for (int i = 0; i < boundsSegments.length - 1; ++i) {
|
||||
curBoundsSegment.add(boundsSegments[i]);
|
||||
Vector2f curBulletSegment = new Vector2f();
|
||||
for (int j = 0; j < bulletSegments.length - 1; ++j) {
|
||||
curBulletSegment.add(bulletSegments[i]);
|
||||
if (segmentCollision(curBoundsSegment, boundsSegments[i + 1], boundVelocity, curBulletSegment, bulletSegments[j + 1], bullet.velocity))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean overlap(Bounds bounds0, Bounds bounds1) {
|
||||
return bounds0.position.x < bounds1.position.x + bounds1.dimensions.x && bounds0.position.x + bounds0.dimensions.x > bounds1.position.x
|
||||
&& bounds0.position.y < bounds1.position.y + bounds1.dimensions.y && bounds1.position.y + bounds1.dimensions.y > bounds1.position.y;
|
||||
}
|
||||
|
||||
public static Bounds getBounds(Vector2f position, Vector2f dimensions, Vector2f velocity) {
|
||||
Bounds bounds = new Bounds(position, dimensions);
|
||||
if (velocity.x < 0)
|
||||
bounds.position.x += velocity.x;
|
||||
else
|
||||
bounds.dimensions.x += velocity.x;
|
||||
if (velocity.y < 0)
|
||||
bounds.position.y += velocity.y;
|
||||
else
|
||||
bounds.dimensions.y += velocity.y;
|
||||
return bounds;
|
||||
}
|
||||
|
||||
public static boolean segmentCollision(Vector2f P1, Vector2f D1, Vector2f V1, Vector2f P2, Vector2f D2, Vector2f V2) {
|
||||
final float DELTA = 0.00001f;
|
||||
|
||||
if ((V1.length() == 0 && V2.length() > 0)
|
||||
|| (V2.length() == 0 && V1.length() > 0)
|
||||
|| V1.angle(V2) > DELTA) {
|
||||
float b = (P1.y - P2.y - (V2.y - V1.y) * (P1.x + D1.x - P2.x) / (V2.x - V1.x)) / (D2.y + (V2.y - V1.y) / (V2.x - V1.x));
|
||||
if (rangeCheck(b)) {
|
||||
float t = (P1.x - P2.x - D2.x * b) / (V2.x - V1.x);
|
||||
if (rangeCheck(t))
|
||||
return true;
|
||||
}
|
||||
float a = (P2.y - P1.y - (V1.y - V2.y) * (P2.x + D2.x - P1.x) / (V1.x - V2.x)) / (D1.y + (V1.y - V2.y) / (V1.x - V2.x));
|
||||
if (rangeCheck(a)) {
|
||||
float t = (P1.x + D1.x * a - P2.x) / (V2.x - V1.x);
|
||||
if (rangeCheck(t))
|
||||
return true;
|
||||
}
|
||||
b = (P1.y + D1.y - P2.y - (V2.y - V1.y) * (P1.x + D1.x - P2.x) / (V2.x - V1.x)) / (D2.y + (V2.y - V1.y) / (V2.x - V1.x));
|
||||
if (rangeCheck(b)) {
|
||||
float t = (P1.x + D1.x - P2.x - D2.x * b) / (V2.x - V1.x);
|
||||
if (rangeCheck(t))
|
||||
return true;
|
||||
}
|
||||
a = (P2.y + D2.y - P1.y - (V1.y - V2.y) * (P2.x + D2.x - P1.x) / (V1.x - V2.x)) / (D1.y + (V1.y - V2.y) / (V1.x - V2.x));
|
||||
if (rangeCheck(a)) {
|
||||
float t = (P1.x + D1.x * a - P2.x - D2.x) / (V2.x - V1.x);
|
||||
if (rangeCheck(t))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean rangeCheck(float num) {
|
||||
return 0 <= num && num <= 1;
|
||||
}
|
||||
}
|
|
@ -2,25 +2,53 @@ package com.gnarly.game;
|
|||
|
||||
import com.gnarly.engine.display.Camera;
|
||||
import com.gnarly.engine.display.Window;
|
||||
import com.gnarly.engine.model.ColRect;
|
||||
import org.joml.Vector2f;
|
||||
|
||||
import static org.lwjgl.glfw.GLFW.GLFW_KEY_SPACE;
|
||||
|
||||
public class GamePanel extends Panel {
|
||||
|
||||
private Window window;
|
||||
private Camera camera;
|
||||
|
||||
private BulletList bullets;
|
||||
|
||||
private Background background;
|
||||
private Player player;
|
||||
|
||||
private float rotation = 0;
|
||||
|
||||
private ColRect testRect;
|
||||
|
||||
public GamePanel(Window window, Camera camera) {
|
||||
this.window = window;
|
||||
this.camera = camera;
|
||||
|
||||
|
||||
bullets = new BulletList(camera);
|
||||
|
||||
background = new Background(camera);
|
||||
player = new Player(window, camera);
|
||||
|
||||
testRect = new ColRect(camera, 100, 100, 0, 25, 25, 1, 0, 0, 1, false);
|
||||
|
||||
state = Main.GAME_PANEL;
|
||||
}
|
||||
|
||||
public void update() {
|
||||
bullets.update(testRect, new Vector2f(0, 100));
|
||||
background.update();
|
||||
player.update();
|
||||
|
||||
if (window.keyPressed(GLFW_KEY_SPACE) == Window.BUTTON_PRESSED)
|
||||
bullets.spawnBullet(new Vector2f(player.getX() + (player.getWidth()) / 2, player.getY() + bullets.getHeight(BulletList.TYPE_PLAYER)), rotation += Math.PI / 16, BulletList.TYPE_PLAYER);
|
||||
}
|
||||
|
||||
public void render() {
|
||||
|
||||
testRect.render();
|
||||
bullets.render();
|
||||
background.render();
|
||||
player.render();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
|
|
|
@ -4,10 +4,13 @@ import com.gnarly.engine.audio.ALManagement;
|
|||
import com.gnarly.engine.display.Camera;
|
||||
import com.gnarly.engine.display.Window;
|
||||
import com.gnarly.engine.shaders.Shader;
|
||||
import org.joml.Vector2f;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static long FPS = 999;
|
||||
|
||||
public static int fps;
|
||||
public static double dtime;
|
||||
|
||||
public static final int
|
||||
|
@ -23,16 +26,29 @@ public class Main {
|
|||
private int panel;
|
||||
|
||||
public void start() {
|
||||
long curTime, pastTime, nspf = 1000000000 / FPS;
|
||||
init();
|
||||
int frames = 0;
|
||||
long curTime, pastTime, pastSec, nspf = 1000000000 / Window.REFRESH_RATE;
|
||||
pastTime = System.nanoTime();
|
||||
pastSec = pastTime;
|
||||
while(!window.shouldClose()) {
|
||||
curTime = System.nanoTime();
|
||||
if (curTime - pastTime > nspf) {
|
||||
dtime = (curTime - pastTime) / 1000000000d;
|
||||
dtime = nspf / 1000000000d;
|
||||
update();
|
||||
render();
|
||||
pastTime = curTime;
|
||||
pastTime += nspf;
|
||||
++frames;
|
||||
if (curTime - pastSec > 1000000000) {
|
||||
fps = frames;
|
||||
frames = 0;
|
||||
pastSec += 1000000000;
|
||||
}
|
||||
try {
|
||||
Thread.sleep(nspf / 1000000);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
al.destroy();
|
||||
|
@ -41,9 +57,9 @@ public class Main {
|
|||
|
||||
private void init() {
|
||||
al = new ALManagement();
|
||||
window = new Window("Gamer Time", true);
|
||||
//window = new Window(100, 100, "Gamer Time", true, true, true);
|
||||
camera = new Camera(1920, 1080);
|
||||
//window = new Window("Gamer Time", true);
|
||||
window = new Window(768, 432, "Gamer Time", true, true, true);
|
||||
camera = new Camera(768, 432);
|
||||
Shader.init();
|
||||
|
||||
panels = new Panel[NUM_PANELS];
|
||||
|
|
63
src/com/gnarly/game/Player.java
Normal file
|
@ -0,0 +1,63 @@
|
|||
package com.gnarly.game;
|
||||
|
||||
import com.gnarly.engine.display.Camera;
|
||||
import com.gnarly.engine.display.Window;
|
||||
import com.gnarly.engine.model.TexRect;
|
||||
import com.gnarly.engine.texture.Texture;
|
||||
|
||||
import static org.lwjgl.glfw.GLFW.*;
|
||||
|
||||
public class Player extends TexRect {
|
||||
|
||||
private double spf = 1.0 / 14.0;
|
||||
private double time = 0;
|
||||
private int frame = 0;
|
||||
|
||||
private static Texture[] frames = null;
|
||||
|
||||
private Window window;
|
||||
|
||||
public Player(Window window, Camera camera) {
|
||||
super(camera, (Texture) null, 0, 0, -0.1f, 32, 32, 0, false);
|
||||
this.window = window;
|
||||
|
||||
if (frames == null) {
|
||||
frames = new Texture[4];
|
||||
frames[0] = new Texture("res/img/player-ship/player-ship-0.png");
|
||||
frames[1] = new Texture("res/img/player-ship/player-ship-1.png");
|
||||
frames[2] = new Texture("res/img/player-ship/player-ship-2.png");
|
||||
frames[3] = new Texture("res/img/player-ship/player-ship-3.png");
|
||||
}
|
||||
|
||||
setTexture(frames[0]);
|
||||
}
|
||||
|
||||
public void update() {
|
||||
final int SPEED = 150;
|
||||
if (window.keyPressed(GLFW_KEY_W) >= Window.BUTTON_PRESSED)
|
||||
position.y -= SPEED * Main.dtime;
|
||||
if (window.keyPressed(GLFW_KEY_A) >= Window.BUTTON_PRESSED)
|
||||
position.x -= SPEED * Main.dtime;
|
||||
if (window.keyPressed(GLFW_KEY_S) >= Window.BUTTON_PRESSED)
|
||||
position.y += SPEED * Main.dtime;
|
||||
if (window.keyPressed(GLFW_KEY_D) >= Window.BUTTON_PRESSED)
|
||||
position.x += SPEED * Main.dtime;
|
||||
|
||||
if (position.x < 0)
|
||||
position.x = 0;
|
||||
else if (position.x + width >= camera.getWidth())
|
||||
position.x = camera.getWidth() - width;
|
||||
|
||||
if (position.y < 0)
|
||||
position.y = 0;
|
||||
else if (position.y + height >= camera.getHeight())
|
||||
position.y = camera.getHeight() - height;
|
||||
|
||||
time += Main.dtime;
|
||||
while (time >= spf) {
|
||||
time -= spf;
|
||||
frame = (frame + 1) % frames.length;
|
||||
setTexture(frames[frame]);
|
||||
}
|
||||
}
|
||||
}
|