Platform collision works
BIN
Ludum Dare (Slab).zip
Normal file
BIN
LudumDare46.jar
Normal file
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
@ -1,13 +1,18 @@
|
|||
#version 330 core
|
||||
|
||||
uniform sampler2D sampler;
|
||||
uniform vec3 iColor;
|
||||
uniform float time;
|
||||
|
||||
in vec2 texCoords;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
void main() {
|
||||
color = texture(sampler, texCoords);
|
||||
if (color.a == 0)
|
||||
vec4 sample = texture(sampler, texCoords);
|
||||
float x = sample.r + time;
|
||||
color = vec4(iColor * mod(floor(x), 2) * (-x + 2), sample.a);
|
||||
if (color.a == 0) {
|
||||
discard;
|
||||
}
|
||||
}
|
|
@ -1,25 +1,37 @@
|
|||
package com.gnarwhal.ld46.engine.shaders;
|
||||
|
||||
import org.joml.Vector2f;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import static org.lwjgl.opengl.GL20.glGetUniformLocation;
|
||||
import static org.lwjgl.opengl.GL20.glUniform4f;
|
||||
import static org.lwjgl.opengl.GL20.*;
|
||||
|
||||
public class Shader2t extends Shader {
|
||||
public class Shader2e extends Shader {
|
||||
|
||||
private int subtextureLoc;
|
||||
private int colorLoc;
|
||||
private int timeLoc;
|
||||
|
||||
public Shader2t() {
|
||||
super("res/shaders/s2t/vert.gls", "res/shaders/s2t/frag.gls");
|
||||
public Shader2e() {
|
||||
super("res/shaders/s2e/vert.gls", "res/shaders/s2e/frag.gls");
|
||||
getUniforms();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getUniforms() {
|
||||
subtextureLoc = glGetUniformLocation(program, "subtexture");
|
||||
colorLoc = glGetUniformLocation(program, "iColor");
|
||||
timeLoc = glGetUniformLocation(program, "time");
|
||||
}
|
||||
|
||||
public void setSubtexture(Vector2f position, Vector2f dimensions) {
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -10,18 +10,27 @@ public class GamePanel {
|
|||
|
||||
private Player player;
|
||||
|
||||
private Platform[] platforms;
|
||||
|
||||
public GamePanel(Window window, Camera camera) {
|
||||
this.window = window;
|
||||
this.camera = camera;
|
||||
|
||||
player = new Player(window, camera);
|
||||
|
||||
platforms = new Platform[] {
|
||||
new Platform(camera, 800, 800, 320)
|
||||
};
|
||||
}
|
||||
|
||||
public void update() {
|
||||
player.update();
|
||||
player.update(platforms);
|
||||
}
|
||||
|
||||
public void render() {
|
||||
for (int i = 0; i < platforms.length; ++i) {
|
||||
platforms[i].render();
|
||||
}
|
||||
player.render();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,8 +52,8 @@ public class Main {
|
|||
al = new ALManagement();
|
||||
|
||||
final int WIN_WIDTH = 1920, WIN_HEIGHT = 1080;
|
||||
//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("Ludum Dare 46", 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);
|
||||
Shader.init();
|
||||
|
||||
|
|
|
@ -1,4 +1,33 @@
|
|||
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 {
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,12 +3,14 @@ package com.gnarwhal.ld46.game;
|
|||
import com.gnarwhal.ld46.engine.display.Camera;
|
||||
import com.gnarwhal.ld46.engine.display.Window;
|
||||
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.texture.Texture;
|
||||
import jdk.jfr.Percentage;
|
||||
import org.joml.Vector2f;
|
||||
import org.joml.Vector3d;
|
||||
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.game.Main.dtime;
|
||||
|
@ -16,6 +18,30 @@ import static org.lwjgl.glfw.GLFW.*;
|
|||
|
||||
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 Shader2t shader;
|
||||
|
||||
|
@ -29,10 +55,16 @@ public class Player extends Rect {
|
|||
|
||||
private boolean grounded = false;
|
||||
|
||||
private Shader2e effectShader;
|
||||
private float attackTimer;
|
||||
private float effectTime;
|
||||
|
||||
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;
|
||||
|
||||
scaledCollisionOffsets = new Vector4f(COLLISION_OFFSETS).mul(width, width, height, height);
|
||||
|
||||
textures = new Texture[] {
|
||||
new Texture("res/img/player/player_legs.png"),
|
||||
new Texture("res/img/player/player_head.png"),
|
||||
|
@ -49,42 +81,90 @@ public class Player extends Rect {
|
|||
idleTime = 0;
|
||||
|
||||
shader = new Shader2t();
|
||||
effectShader = new Shader2e();
|
||||
|
||||
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 DECELERATION = 1762;
|
||||
final float HIGH_SPEED_DECELERATION = 2048;
|
||||
final float TERMINAL_VELOCITY = 1762;
|
||||
final float GRAVITY = 1762;
|
||||
|
||||
final float speed = 768;
|
||||
final float JUMP_SPEED = 812;
|
||||
final float DECELERATION = 1024;
|
||||
final float DIRECTIONAL_ACCELERATION = 2960;
|
||||
final float HIGH_SPEED_DECELERATION = 1762;
|
||||
final float TERMINAL_VELOCITY = 1762;
|
||||
final float GRAVITY = 1762;
|
||||
final float SPEED = 768;
|
||||
|
||||
float friction = 0;
|
||||
float floor = 0;
|
||||
Vector3f acceleration = new Vector3f(0, GRAVITY, 0);
|
||||
|
||||
if (window.keyPressed(GLFW_KEY_A) >= BUTTON_PRESSED) {
|
||||
floor = -speed;
|
||||
if (velocity.x > -speed)
|
||||
velocity.x = -speed;
|
||||
else
|
||||
friction = HIGH_SPEED_DECELERATION;
|
||||
attackTimer += dtime;
|
||||
|
||||
}
|
||||
else if (window.keyPressed(GLFW_KEY_D) >= BUTTON_PRESSED) {
|
||||
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 (velocity.x != 0) {
|
||||
float absVelX = Math.abs(velocity.x);
|
||||
if (absVelX > speed) {
|
||||
if (absVelX > SPEED) {
|
||||
friction = -HIGH_SPEED_DECELERATION * (velocity.x / absVelX);
|
||||
} else {
|
||||
friction = -DECELERATION * (velocity.x / absVelX);
|
||||
|
@ -100,13 +180,25 @@ public class Player extends Rect {
|
|||
}
|
||||
}
|
||||
|
||||
if ((window.keyPressed(GLFW_KEY_W) == BUTTON_PRESSED
|
||||
final float HORIZONTAL_JUMP_INFLUENCE = 512;
|
||||
if ((window.keyPressed(GLFW_KEY_W) == BUTTON_PRESSED
|
||||
|| window.keyPressed(GLFW_KEY_SPACE) == BUTTON_PRESSED)) {
|
||||
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) {
|
||||
final float SCALE = 10;
|
||||
final float SCALE = 15;
|
||||
final float RATE = (float) (2 * Math.PI / 2.5); // Last number is seconds per loop
|
||||
offset.y = (float) (SCALE * Math.sin(RATE * idleTime));
|
||||
idleTime += dtime;
|
||||
|
@ -126,10 +218,7 @@ public class Player extends Rect {
|
|||
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 HORZ_ACCELERATION = 4096;
|
||||
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()));*/
|
||||
|
||||
// --- 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
|
||||
if (position.y + height > camera.getHeight()) {
|
||||
position.y = camera.getHeight() - height;
|
||||
if (position.y + height - scaledCollisionOffsets.w > camera.getHeight()) {
|
||||
position.y = camera.getHeight() - height + scaledCollisionOffsets.w;
|
||||
velocity.y = 0;
|
||||
grounded = true;
|
||||
} else {
|
||||
grounded = false;
|
||||
if (position.y < 0) {
|
||||
position.y = 0;
|
||||
if (position.y + scaledCollisionOffsets.y < 0) {
|
||||
position.y = -scaledCollisionOffsets.y;
|
||||
velocity.y = 0;
|
||||
}
|
||||
}
|
||||
// Check X bounds
|
||||
if (position.x < 0) {
|
||||
position.x = 0;
|
||||
if (position.x + scaledCollisionOffsets.x < 0) {
|
||||
position.x = -scaledCollisionOffsets.x;
|
||||
velocity.x = 0;
|
||||
} else if (position.x + width > camera.getWidth()) {
|
||||
position.x = camera.getWidth() - width;
|
||||
} else if (position.x + width - scaledCollisionOffsets.z > camera.getWidth()) {
|
||||
position.x = camera.getWidth() - width + scaledCollisionOffsets.z;
|
||||
velocity.x = 0;
|
||||
}
|
||||
|
||||
final float MAX_DISTANCE = 10;
|
||||
final float ELASTICITY = 0.5f;
|
||||
positions[0].set(position).add(offset);
|
||||
Vector3f displacement = positions[2].sub(positions[0], new Vector3f()).mul(1 - ELASTICITY);
|
||||
displacement.x = 0;
|
||||
float length = displacement.length();
|
||||
if (length > MAX_DISTANCE) {
|
||||
displacement.div(length).mul(MAX_DISTANCE);
|
||||
// --- 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 ELASTICITY = idleTime == 0 ? 0.6f : 0.15f;
|
||||
positions[0].set(position).add(offset);
|
||||
Vector3f displacement = positions[2].sub(positions[0], new Vector3f()).mul(1 - (ELASTICITY * (float) dtime * 60.0f));
|
||||
//displacement.x = 0;
|
||||
float length = displacement.length();
|
||||
if (length > MAX_DISTANCE) {
|
||||
displacement.div(length).mul(MAX_DISTANCE);
|
||||
}
|
||||
positions[2].set(positions[0]).add(displacement);
|
||||
displacement.set(positions[1]).sub(positions[2]).mul(1 - ELASTICITY);
|
||||
//displacement.x = 0;
|
||||
length = displacement.length();
|
||||
if (length > MAX_DISTANCE) {
|
||||
displacement.div(length).mul(MAX_DISTANCE);
|
||||
}
|
||||
positions[1].set(positions[2]).add(displacement);
|
||||
} else {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
positions[i].set(position);
|
||||
}
|
||||
}
|
||||
positions[2].set(positions[0]).add(displacement);
|
||||
displacement.set(positions[1]).sub(positions[2]).mul(1 - ELASTICITY);
|
||||
displacement.x = 0;
|
||||
length = displacement.length();
|
||||
if (length > MAX_DISTANCE) {
|
||||
displacement.div(length).mul(MAX_DISTANCE);
|
||||
}
|
||||
System.out.println(displacement);
|
||||
positions[1].set(positions[2]).add(displacement);
|
||||
}
|
||||
|
||||
public void render() {
|
||||
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) {
|
||||
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));
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|