Platform collision works

This commit is contained in:
Gnarwhal 2024-08-07 05:02:56 +00:00
parent a0cc4ac0be
commit 24c7a78ae6
Signed by: Gnarwhal
GPG key ID: 0989A73D8C421174
14 changed files with 1003 additions and 833 deletions

BIN
Ludum Dare (Slab).zip Normal file

Binary file not shown.

Binary file not shown.

BIN
LudumDare46.jar Normal file

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View file

@ -1,13 +1,18 @@
#version 330 core #version 330 core
uniform sampler2D sampler; uniform sampler2D sampler;
uniform vec3 iColor;
uniform float time;
in vec2 texCoords; in vec2 texCoords;
out vec4 color; out vec4 color;
void main() { void main() {
color = texture(sampler, texCoords); vec4 sample = texture(sampler, texCoords);
if (color.a == 0) float x = sample.r + time;
color = vec4(iColor * mod(floor(x), 2) * (-x + 2), sample.a);
if (color.a == 0) {
discard; discard;
} }
}

View file

@ -1,25 +1,37 @@
package com.gnarwhal.ld46.engine.shaders; package com.gnarwhal.ld46.engine.shaders;
import org.joml.Vector2f; import org.joml.Vector2f;
import org.joml.Vector3f;
import static org.lwjgl.opengl.GL20.glGetUniformLocation; import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL20.glUniform4f;
public class Shader2t extends Shader { public class Shader2e extends Shader {
private int subtextureLoc; private int subtextureLoc;
private int colorLoc;
private int timeLoc;
public Shader2t() { public Shader2e() {
super("res/shaders/s2t/vert.gls", "res/shaders/s2t/frag.gls"); super("res/shaders/s2e/vert.gls", "res/shaders/s2e/frag.gls");
getUniforms(); getUniforms();
} }
@Override @Override
protected void getUniforms() { protected void getUniforms() {
subtextureLoc = glGetUniformLocation(program, "subtexture"); subtextureLoc = glGetUniformLocation(program, "subtexture");
colorLoc = glGetUniformLocation(program, "iColor");
timeLoc = glGetUniformLocation(program, "time");
} }
public void setSubtexture(Vector2f position, Vector2f dimensions) { public void setSubtexture(Vector2f position, Vector2f dimensions) {
glUniform4f(subtextureLoc, position.x, position.y, dimensions.x, dimensions.y); glUniform4f(subtextureLoc, position.x, position.y, dimensions.x, dimensions.y);
} }
public void setColor(Vector3f color) {
glUniform3f(colorLoc, color.x, color.y, color.z);
}
public void setTime(float time) {
glUniform1f(timeLoc, time);
}
} }

View file

@ -10,18 +10,27 @@ public class GamePanel {
private Player player; private Player player;
private Platform[] platforms;
public GamePanel(Window window, Camera camera) { public GamePanel(Window window, Camera camera) {
this.window = window; this.window = window;
this.camera = camera; this.camera = camera;
player = new Player(window, camera); player = new Player(window, camera);
platforms = new Platform[] {
new Platform(camera, 800, 800, 320)
};
} }
public void update() { public void update() {
player.update(); player.update(platforms);
} }
public void render() { public void render() {
for (int i = 0; i < platforms.length; ++i) {
platforms[i].render();
}
player.render(); player.render();
} }
} }

View file

@ -52,8 +52,8 @@ public class Main {
al = new ALManagement(); al = new ALManagement();
final int WIN_WIDTH = 1920, WIN_HEIGHT = 1080; final int WIN_WIDTH = 1920, WIN_HEIGHT = 1080;
//window = new Window("Ludum Dare 46", true); window = new Window("Ludum Dare 46", true);
window = new Window(WIN_WIDTH * 3/4, WIN_HEIGHT * 3/4, "Ludum Dare 46", true, true, true); //window = new Window(WIN_WIDTH * 3/4, WIN_HEIGHT * 3/4, "Ludum Dare 46", true, true, true);
camera = new Camera(WIN_WIDTH, WIN_HEIGHT); camera = new Camera(WIN_WIDTH, WIN_HEIGHT);
Shader.init(); Shader.init();

View file

@ -1,4 +1,33 @@
package com.gnarwhal.ld46.game; package com.gnarwhal.ld46.game;
import com.gnarwhal.ld46.engine.display.Camera;
import com.gnarwhal.ld46.engine.model.ColRect;
import org.joml.Vector3f;
public class Platform { public class Platform {
private Camera camera;
private ColRect rect;
public Platform(Camera camera, float x, float y, float width) {
this.camera = camera;
this.rect = new ColRect(camera, x, y, -0.05f, width, 12, 1, 1, 1, 1, false);
}
public void update() {
}
public void render() {
rect.render();
}
public Vector3f getOrigin() {
return new Vector3f(rect.getX(), rect.getY(), 0);
}
public Vector3f getTranslation() {
return new Vector3f(rect.getWidth(), 0, 0);
}
} }

View file

@ -3,12 +3,14 @@ package com.gnarwhal.ld46.game;
import com.gnarwhal.ld46.engine.display.Camera; import com.gnarwhal.ld46.engine.display.Camera;
import com.gnarwhal.ld46.engine.display.Window; import com.gnarwhal.ld46.engine.display.Window;
import com.gnarwhal.ld46.engine.model.Rect; import com.gnarwhal.ld46.engine.model.Rect;
import com.gnarwhal.ld46.engine.shaders.Shader2e;
import com.gnarwhal.ld46.engine.shaders.Shader2t; import com.gnarwhal.ld46.engine.shaders.Shader2t;
import com.gnarwhal.ld46.engine.texture.Texture; import com.gnarwhal.ld46.engine.texture.Texture;
import jdk.jfr.Percentage;
import org.joml.Vector2f; import org.joml.Vector2f;
import org.joml.Vector3d;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.joml.Vector4f;
import java.util.Vector;
import static com.gnarwhal.ld46.engine.display.Window.BUTTON_PRESSED; import static com.gnarwhal.ld46.engine.display.Window.BUTTON_PRESSED;
import static com.gnarwhal.ld46.game.Main.dtime; import static com.gnarwhal.ld46.game.Main.dtime;
@ -16,6 +18,30 @@ import static org.lwjgl.glfw.GLFW.*;
public class Player extends Rect { public class Player extends Rect {
private static final int
STATE_REST = 0x00,
STATE_LEFT = 0x02,
STATE_RIGHT = 0x01,
STATE_UP = 0x03,
STATE_DOWN = 0x04;
private static final Vector2f TEXTURE_DIMS = new Vector2f(0.5f, 0.2f);
private static final Vector3f[] COLORS = new Vector3f[] {
new Vector3f(1, 0, 0 ),
new Vector3f(0.1f, 1, 0.5f),
new Vector3f(0, 1, 1 ),
new Vector3f(1, 0, 1 )
};
private static final Vector4f COLLISION_OFFSETS = new Vector4f(6.0f, 6.0f, 5.0f, 3.5f).div(24.0f);
// LEFT, RIGHT, TOP, BOTTOM
private Vector4f scaledCollisionOffsets;
private int state;
private Vector2f sprite;
private Texture[] textures; private Texture[] textures;
private Shader2t shader; private Shader2t shader;
@ -29,10 +55,16 @@ public class Player extends Rect {
private boolean grounded = false; private boolean grounded = false;
private Shader2e effectShader;
private float attackTimer;
private float effectTime;
public Player(Window window, Camera camera) { public Player(Window window, Camera camera) {
super(camera, 0, 0, -0.1f, 200, 200, 0, false); super(camera, 0, 0, -0.1f, 256, 256, 0, false);
this.window = window; this.window = window;
scaledCollisionOffsets = new Vector4f(COLLISION_OFFSETS).mul(width, width, height, height);
textures = new Texture[] { textures = new Texture[] {
new Texture("res/img/player/player_legs.png"), new Texture("res/img/player/player_legs.png"),
new Texture("res/img/player/player_head.png"), new Texture("res/img/player/player_head.png"),
@ -49,42 +81,90 @@ public class Player extends Rect {
idleTime = 0; idleTime = 0;
shader = new Shader2t(); shader = new Shader2t();
effectShader = new Shader2e();
velocity = new Vector3f(); velocity = new Vector3f();
sprite = new Vector2f();
attackTimer = 10000;
} }
public void update() { public void update(Platform[] platforms) {
final float ATTACK_RESET = 0.0f;
if (state == STATE_REST && attackTimer >= ATTACK_RESET) {
if (window.keyPressed(GLFW_KEY_LEFT) == BUTTON_PRESSED) {
state = STATE_LEFT;
} else if (window.keyPressed(GLFW_KEY_RIGHT) == BUTTON_PRESSED) {
state = STATE_RIGHT;
} else if (window.keyPressed(GLFW_KEY_UP) == BUTTON_PRESSED) {
state = STATE_UP;
} else if (window.keyPressed(GLFW_KEY_DOWN) == BUTTON_PRESSED) {
state = STATE_DOWN;
}
if (state != STATE_REST) {
attackTimer = 0;
}
}
if (state != STATE_REST) {
final float ATTACK_BEGIN = 0.05f;
final float ATTACK_ACTIVE = 0.35f;
final float ATTACK_HOLD = 0.4f;
final float ATTACK_END = 0.5f;
if (attackTimer < ATTACK_BEGIN) {
sprite.set(0, 0.2f * state);
effectTime = 0;
} else if (attackTimer < ATTACK_ACTIVE) {
sprite.set(0.5f, 0.2f * state);
effectTime = Math.min((attackTimer - ATTACK_BEGIN) / (ATTACK_ACTIVE - ATTACK_BEGIN) * 4, 1);
} else if (attackTimer < ATTACK_HOLD) {
sprite.set(0.5f, 0.2f * state);
effectTime = 1;
} else if (attackTimer < ATTACK_END) {
sprite.set(0.5f, 0.2f * state);
effectTime = 1 + (attackTimer - ATTACK_ACTIVE) / (ATTACK_END - ATTACK_ACTIVE);
} else {
state = STATE_REST;
attackTimer = 0;
idleTime = 0;
}
offset.set(0, 0, 0);
} else {
sprite.set(0, 0);
}
final float JUMP_SPEED = 812; final float JUMP_SPEED = 812;
final float DECELERATION = 1762; final float DECELERATION = 1024;
final float HIGH_SPEED_DECELERATION = 2048; final float DIRECTIONAL_ACCELERATION = 2960;
final float HIGH_SPEED_DECELERATION = 1762;
final float TERMINAL_VELOCITY = 1762; final float TERMINAL_VELOCITY = 1762;
final float GRAVITY = 1762; final float GRAVITY = 1762;
final float SPEED = 768;
final float speed = 768;
float friction = 0; float friction = 0;
float floor = 0; float floor = 0;
Vector3f acceleration = new Vector3f(0, GRAVITY, 0); Vector3f acceleration = new Vector3f(0, GRAVITY, 0);
if (window.keyPressed(GLFW_KEY_A) >= BUTTON_PRESSED) { attackTimer += dtime;
floor = -speed;
if (velocity.x > -speed)
velocity.x = -speed;
else
friction = HIGH_SPEED_DECELERATION;
if (window.keyPressed(GLFW_KEY_A) >= BUTTON_PRESSED) {
floor = -SPEED;
if (velocity.x > -SPEED) {
velocity.x -= DIRECTIONAL_ACCELERATION * dtime;
if (velocity.x < -SPEED) {
velocity.x = -SPEED;
}
}
} else if (window.keyPressed(GLFW_KEY_D) >= BUTTON_PRESSED) {
floor = SPEED;
if (velocity.x < SPEED) {
velocity.x += DIRECTIONAL_ACCELERATION * dtime;
if (velocity.x > SPEED) {
velocity.x = SPEED;
} }
else if (window.keyPressed(GLFW_KEY_D) >= BUTTON_PRESSED) {
floor = speed;
if (velocity.x < speed) {
velocity.x = speed;
} else {
friction = -HIGH_SPEED_DECELERATION;
} }
} else if (velocity.x != 0) { } else if (velocity.x != 0) {
float absVelX = Math.abs(velocity.x); float absVelX = Math.abs(velocity.x);
if (absVelX > speed) { if (absVelX > SPEED) {
friction = -HIGH_SPEED_DECELERATION * (velocity.x / absVelX); friction = -HIGH_SPEED_DECELERATION * (velocity.x / absVelX);
} else { } else {
friction = -DECELERATION * (velocity.x / absVelX); friction = -DECELERATION * (velocity.x / absVelX);
@ -100,13 +180,25 @@ public class Player extends Rect {
} }
} }
final float HORIZONTAL_JUMP_INFLUENCE = 512;
if ((window.keyPressed(GLFW_KEY_W) == BUTTON_PRESSED if ((window.keyPressed(GLFW_KEY_W) == BUTTON_PRESSED
|| window.keyPressed(GLFW_KEY_SPACE) == BUTTON_PRESSED)) { || window.keyPressed(GLFW_KEY_SPACE) == BUTTON_PRESSED)) {
velocity.y = -JUMP_SPEED; velocity.y = -JUMP_SPEED;
if (window.keyPressed(GLFW_KEY_A) >= BUTTON_PRESSED) {
velocity.x -= HORIZONTAL_JUMP_INFLUENCE;
if (velocity.x < -SPEED) {
velocity.x = -SPEED;
}
} else if (window.keyPressed(GLFW_KEY_D) >= BUTTON_PRESSED) {
velocity.x += HORIZONTAL_JUMP_INFLUENCE;
if (velocity.x > SPEED) {
velocity.x = SPEED;
}
}
} }
if (velocity.x == 0 && grounded) { if (velocity.x == 0 && grounded) {
final float SCALE = 10; final float SCALE = 15;
final float RATE = (float) (2 * Math.PI / 2.5); // Last number is seconds per loop final float RATE = (float) (2 * Math.PI / 2.5); // Last number is seconds per loop
offset.y = (float) (SCALE * Math.sin(RATE * idleTime)); offset.y = (float) (SCALE * Math.sin(RATE * idleTime));
idleTime += dtime; idleTime += dtime;
@ -126,10 +218,7 @@ public class Player extends Rect {
velocity.x = degradedVelocity; velocity.x = degradedVelocity;
} }
position.add(velocity.mul((float) dtime, new Vector3f())); /*if (state == STATE_GROUNDED) {
/*
if (state == STATE_GROUNDED) {
final float MAX_HORZ_VELOCITY = 1024; final float MAX_HORZ_VELOCITY = 1024;
final float HORZ_ACCELERATION = 4096; final float HORZ_ACCELERATION = 4096;
if (window.keyPressed(GLFW_KEY_A) >= BUTTON_PRESSED) { if (window.keyPressed(GLFW_KEY_A) >= BUTTON_PRESSED) {
@ -154,54 +243,111 @@ public class Player extends Rect {
position.add(velocity.mul((float) Main.dtime, new Vector3f()));*/ position.add(velocity.mul((float) Main.dtime, new Vector3f()));*/
// --- C O L L I S I O N --- //
Vector3f translation = velocity.mul((float) dtime, new Vector3f());
Vector3f translationCopy = new Vector3f(translation);
if (window.keyPressed(GLFW_KEY_LEFT_SHIFT) < BUTTON_PRESSED && window.keyPressed(GLFW_KEY_RIGHT_SHIFT) < BUTTON_PRESSED && translation.y > 0) {
Vector3f bottomLeft = new Vector3f(position).add( scaledCollisionOffsets.x, height - scaledCollisionOffsets.w, 0);
Vector3f bottomRight = new Vector3f(position).add(width - scaledCollisionOffsets.y, height - scaledCollisionOffsets.w, 0);
for (int i = 0; i < platforms.length; ++i) {
Vector3f porigin = platforms[i].getOrigin();
Vector3f ptranslation = platforms[i].getTranslation();
float s1, t1, s2, t2;
if (translation.x != 0) {
s1 = ((porigin.y - bottomLeft.y) / translation.y - (porigin.x - bottomLeft.x) / translation.x) / (ptranslation.x / translation.x - ptranslation.y / translation.y);
s2 = ((porigin.y - bottomRight.y) / translation.y - (porigin.x - bottomRight.x) / translation.x) / (ptranslation.x / translation.x - ptranslation.y / translation.y);
} else {
s1 = (bottomLeft.x - porigin.x) / ptranslation.x;
s2 = (bottomRight.x - porigin.x) / ptranslation.x;
}
t1 = (ptranslation.y * s1 + porigin.y - bottomLeft.y) / translation.y;
t2 = (ptranslation.y * s1 + porigin.y - bottomRight.y) / translation.y;
if (s1 >= 0 && s1 <= 1 && t1 >= 0 && t1 <= 1) {
if (t2 < t1 && s2 >= 0 && s2 <= 1 && t2 >= 0 && t2 <= 1) {
translation.y *= t2;
} else {
translation.y *= t1;
}
} else if (s2 >= 0 && s2 <= 1 && t2 >= 0 && t2 <= 1) {
translation.y *= t2;
}
}
}
grounded = false;
if (!translation.equals(translationCopy, 0)) {
velocity.y = 0;
grounded = true;
}
position.add(translation);
// Check y bounds // Check y bounds
if (position.y + height > camera.getHeight()) { if (position.y + height - scaledCollisionOffsets.w > camera.getHeight()) {
position.y = camera.getHeight() - height; position.y = camera.getHeight() - height + scaledCollisionOffsets.w;
velocity.y = 0; velocity.y = 0;
grounded = true; grounded = true;
} else { } else {
grounded = false; if (position.y + scaledCollisionOffsets.y < 0) {
if (position.y < 0) { position.y = -scaledCollisionOffsets.y;
position.y = 0;
velocity.y = 0; velocity.y = 0;
} }
} }
// Check X bounds // Check X bounds
if (position.x < 0) { if (position.x + scaledCollisionOffsets.x < 0) {
position.x = 0; position.x = -scaledCollisionOffsets.x;
velocity.x = 0; velocity.x = 0;
} else if (position.x + width > camera.getWidth()) { } else if (position.x + width - scaledCollisionOffsets.z > camera.getWidth()) {
position.x = camera.getWidth() - width; position.x = camera.getWidth() - width + scaledCollisionOffsets.z;
velocity.x = 0; velocity.x = 0;
} }
// --- E N D C O L L I S I O N --- //
if (state == STATE_REST) {
// Stretch physics --- FRAME INDEPENDENT??? MAYBBBBE????????
final float MAX_DISTANCE = 10; final float MAX_DISTANCE = 10;
final float ELASTICITY = 0.5f; final float ELASTICITY = idleTime == 0 ? 0.6f : 0.15f;
positions[0].set(position).add(offset); positions[0].set(position).add(offset);
Vector3f displacement = positions[2].sub(positions[0], new Vector3f()).mul(1 - ELASTICITY); Vector3f displacement = positions[2].sub(positions[0], new Vector3f()).mul(1 - (ELASTICITY * (float) dtime * 60.0f));
displacement.x = 0; //displacement.x = 0;
float length = displacement.length(); float length = displacement.length();
if (length > MAX_DISTANCE) { if (length > MAX_DISTANCE) {
displacement.div(length).mul(MAX_DISTANCE); displacement.div(length).mul(MAX_DISTANCE);
} }
positions[2].set(positions[0]).add(displacement); positions[2].set(positions[0]).add(displacement);
displacement.set(positions[1]).sub(positions[2]).mul(1 - ELASTICITY); displacement.set(positions[1]).sub(positions[2]).mul(1 - ELASTICITY);
displacement.x = 0; //displacement.x = 0;
length = displacement.length(); length = displacement.length();
if (length > MAX_DISTANCE) { if (length > MAX_DISTANCE) {
displacement.div(length).mul(MAX_DISTANCE); displacement.div(length).mul(MAX_DISTANCE);
} }
System.out.println(displacement);
positions[1].set(positions[2]).add(displacement); positions[1].set(positions[2]).add(displacement);
} else {
for (int i = 0; i < 3; ++i) {
positions[i].set(position);
}
}
} }
public void render() { public void render() {
shader.enable(); shader.enable();
shader.setSubtexture(new Vector2f(0, 0), new Vector2f(0.5f, 0.2f)); shader.setSubtexture(sprite, TEXTURE_DIMS);
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
textures[i].bind(); textures[i].bind();
shader.setMVP(camera.getMatrix().translate(positions[i].add(width * scale / 2, height * scale / 2, 0.01f * i, new Vector3f())).rotateZ(rotation).scale(width * scale, height * scale, 1).translate(-0.5f, -0.5f, 0)); shader.setMVP(camera.getMatrix().translate(positions[i].add(width * scale / 2, height * scale / 2, 0.01f * i, new Vector3f())).rotateZ(rotation).scale(width * scale, height * scale, 1).translate(-0.5f, -0.5f, 0));
vao.render(); vao.render();
} }
if (state != STATE_REST) {
effectShader.enable();
effectShader.setSubtexture(sprite, TEXTURE_DIMS);
effectShader.setTime(effectTime);
effectShader.setColor(COLORS[state - 1]);
effectShader.setMVP(camera.getMatrix().translate(positions[0].add(width * scale / 2, height * scale / 2, 0.03f, new Vector3f())).rotateZ(rotation).scale(width * scale, height * scale, 1).translate(-0.5f, -0.5f, 0));
textures[3].bind();
vao.render();
}
} }
} }