Added parallax background, ship, and firing. Collision is WIP

This commit is contained in:
Gnarwhal 2024-08-07 05:04:16 +00:00
parent 79787f6525
commit 0605e4d91b
Signed by: Gnarwhal
GPG key ID: 0989A73D8C421174
28 changed files with 588 additions and 150 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 553 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 543 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 543 B

19
res/shaders/s2b/frag.gls Normal file
View 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
View 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);
}

View file

@ -2,20 +2,12 @@
uniform sampler2D sampler; uniform sampler2D sampler;
uniform vec4 iColor = vec4(1, 1, 1, 1);
uniform float alpha = 1;
uniform float amount = 1;
in vec2 texCoords; in vec2 texCoords;
out vec4 color; out vec4 color;
void main() { void main() {
vec4 texColor = texture(sampler, texCoords); color = texture(sampler, texCoords);
if(texColor.a == 0) if (color.a == 0)
discard; discard;
else {
color = mix(iColor, texColor, amount);
color.a = color.a * alpha;
}
} }

View file

@ -1,39 +1,6 @@
package com.gnarly.engine.display; package com.gnarly.engine.display;
import static org.lwjgl.glfw.GLFW.GLFW_CONTEXT_VERSION_MAJOR; import static org.lwjgl.glfw.GLFW.*;
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.opengl.GL.createCapabilities; import static org.lwjgl.opengl.GL.createCapabilities;
import static org.lwjgl.opengl.GL11.GL_BLEND; 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_COLOR_BUFFER_BIT;
@ -56,11 +23,10 @@ import org.lwjgl.glfw.GLFWVidMode;
public class Window { public class Window {
public static String resolution;
public static int public static int
SCREEN_WIDTH, SCREEN_WIDTH,
SCREEN_HEIGHT; SCREEN_HEIGHT,
REFRESH_RATE;
public static final int public static final int
BUTTON_RELEASED = 0, BUTTON_RELEASED = 0,
@ -115,6 +81,7 @@ public class Window {
SCREEN_WIDTH = vidMode.width(); SCREEN_WIDTH = vidMode.width();
SCREEN_HEIGHT = vidMode.height(); SCREEN_HEIGHT = vidMode.height();
SCALE = SCREEN_HEIGHT / 1080f; SCALE = SCREEN_HEIGHT / 1080f;
REFRESH_RATE = vidMode.refreshRate();
if(lwidth == 0 || lheight == 0) { if(lwidth == 0 || lheight == 0) {
width = vidMode.width(); width = vidMode.width();
height = vidMode.height(); height = vidMode.height();
@ -169,21 +136,12 @@ public class Window {
glEnable(GL_MULTISAMPLE); glEnable(GL_MULTISAMPLE);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
int[] awidth = new int[1], aheight = new int[1]; int[] awidth = new int[1], aheight = new int[1];
glfwGetWindowSize(window, awidth, aheight); glfwGetWindowSize(window, awidth, aheight);
width = awidth[0]; width = awidth[0];
height = aheight[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() { public void update() {
@ -198,7 +156,7 @@ public class Window {
} }
public void activateClearColor() { public void activateClearColor() {
glClearColor(0, 0, 0, 1); glClearColor(0, 0, 0.02f, 1);
} }
public int getWidth() { public int getWidth() {

View file

@ -54,6 +54,10 @@ public class Rect {
return position.y; return position.y;
} }
public Vector2f getPosition() {
return new Vector2f(position.x, position.y);
}
public float getWidth() { public float getWidth() {
return width; return width;
} }
@ -62,6 +66,10 @@ public class Rect {
return height; return height;
} }
public Vector2f getDimensions() {
return new Vector2f(width, height);
}
public void setX(float x) { public void setX(float x) {
position.x = x; position.x = x;
} }

View file

@ -13,12 +13,6 @@ public class TexRect extends Rect {
private Texture texture; private Texture texture;
private Shader2t shader = Shader.SHADER2T; private Shader2t shader = Shader.SHADER2T;
protected float direction = 1; 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) { 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); super(camera, x, y, z, width, height, rotation, gui);
@ -35,8 +29,6 @@ public class TexRect extends Rect {
shader.enable(); shader.enable();
Matrix4f cmat = gui ? camera.getProjection() : camera.getMatrix(); 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.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(); vao.render();
shader.disable(); shader.disable();
texture.unbind(); texture.unbind();
@ -50,20 +42,4 @@ public class TexRect extends Rect {
public void setTexture(Texture texture) { public void setTexture(Texture texture) {
this.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;
}
} }

View file

@ -29,6 +29,7 @@ public abstract class Shader {
public static Shader2c SHADER2C; public static Shader2c SHADER2C;
public static Shader2t SHADER2T; public static Shader2t SHADER2T;
public static Shader2b SHADER2B;
protected int program; protected int program;
@ -95,5 +96,6 @@ public abstract class Shader {
public static void init() { public static void init() {
SHADER2C = new Shader2c(); SHADER2C = new Shader2c();
SHADER2T = new Shader2t(); SHADER2T = new Shader2t();
SHADER2B = new Shader2b();
} }
} }

View 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);
}
}

View file

@ -1,33 +1,12 @@
package com.gnarly.engine.shaders; 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 { public class Shader2t extends Shader {
private int alphaLoc;
private int colorLoc;
private int amountLoc;
protected Shader2t() { protected Shader2t() {
super("res/shaders/s2t/vert.gls", "res/shaders/s2t/frag.gls"); super("res/shaders/s2t/vert.gls", "res/shaders/s2t/frag.gls");
getUniforms(); 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 @Override
protected void getUniforms() { protected void getUniforms() {}
alphaLoc = glGetUniformLocation(program, "alpha");
colorLoc = glGetUniformLocation(program, "iColor");
amountLoc = glGetUniformLocation(program, "amount");
}
} }

View file

@ -1,20 +1,5 @@
package com.gnarly.engine.texture; 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.awt.image.BufferedImage;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -26,21 +11,25 @@ import org.lwjgl.BufferUtils;
import com.gnarly.engine.display.Window; 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 { public class Texture {
protected int id, width, height; protected int id, width, height;
public Texture(String name) { public Texture(String name) {
this(name, GL_CLAMP);
}
public Texture(String name, int wrap) {
BufferedImage bi = null; BufferedImage bi = null;
try { try {
bi = ImageIO.read(new File("res/img/" + Window.resolution + "/" + name)); bi = ImageIO.read(new File(name));
} catch (IOException e) { } catch (IOException e) {
try {
bi = ImageIO.read(new File("res/img/const/" + name));
} catch (IOException ex) {
e.printStackTrace(); e.printStackTrace();
} }
}
if (bi != null) { if (bi != null) {
width = bi.getWidth(); width = bi.getWidth();
height = bi.getHeight(); height = bi.getHeight();
@ -60,10 +49,10 @@ public class Texture {
id = glGenTextures(); id = glGenTextures();
bind(); bind();
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 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); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
unbind(); unbind();
} }
@ -84,6 +73,11 @@ public class Texture {
} }
public void bind() { public void bind() {
bind(0);
}
public void bind(int activeTexture) {
glActiveTexture(GL_TEXTURE0 + activeTexture);
glBindTexture(GL_TEXTURE_2D, id); glBindTexture(GL_TEXTURE_2D, id);
} }

View 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];
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View file

@ -2,25 +2,53 @@ package com.gnarly.game;
import com.gnarly.engine.display.Camera; import com.gnarly.engine.display.Camera;
import com.gnarly.engine.display.Window; 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 { public class GamePanel extends Panel {
private Window window; private Window window;
private Camera camera; 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) { public GamePanel(Window window, Camera camera) {
this.window = window; this.window = window;
this.camera = camera; 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; state = Main.GAME_PANEL;
} }
public void update() { 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() { public void render() {
testRect.render();
bullets.render();
background.render();
player.render();
} }
public void reset() { public void reset() {

View file

@ -4,10 +4,13 @@ import com.gnarly.engine.audio.ALManagement;
import com.gnarly.engine.display.Camera; import com.gnarly.engine.display.Camera;
import com.gnarly.engine.display.Window; import com.gnarly.engine.display.Window;
import com.gnarly.engine.shaders.Shader; import com.gnarly.engine.shaders.Shader;
import org.joml.Vector2f;
import java.io.IOException;
public class Main { public class Main {
public static long FPS = 999; public static int fps;
public static double dtime; public static double dtime;
public static final int public static final int
@ -23,16 +26,29 @@ public class Main {
private int panel; private int panel;
public void start() { public void start() {
long curTime, pastTime, nspf = 1000000000 / FPS;
init(); init();
int frames = 0;
long curTime, pastTime, pastSec, nspf = 1000000000 / Window.REFRESH_RATE;
pastTime = System.nanoTime(); pastTime = System.nanoTime();
pastSec = pastTime;
while(!window.shouldClose()) { while(!window.shouldClose()) {
curTime = System.nanoTime(); curTime = System.nanoTime();
if (curTime - pastTime > nspf) { if (curTime - pastTime > nspf) {
dtime = (curTime - pastTime) / 1000000000d; dtime = nspf / 1000000000d;
update(); update();
render(); 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(); al.destroy();
@ -41,9 +57,9 @@ public class Main {
private void init() { private void init() {
al = new ALManagement(); al = new ALManagement();
window = new Window("Gamer Time", true); //window = new Window("Gamer Time", true);
//window = new Window(100, 100, "Gamer Time", true, true, true); window = new Window(768, 432, "Gamer Time", true, true, true);
camera = new Camera(1920, 1080); camera = new Camera(768, 432);
Shader.init(); Shader.init();
panels = new Panel[NUM_PANELS]; panels = new Panel[NUM_PANELS];

View 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]);
}
}
}