EDIT: I rewrote a minimal reproducible example in p5.js, so you can see what's happening here:
let keyInput = []
let player
let block
function setup() {
createCanvas(600, 600)
player = new Player(0, height/2)
block = new Block(200, height-100, 100, 1000)
}
function draw() {
background(220);
player.draw()
block.draw()
player.moveX()
block.checkCollisionsX()
player.moveY()
block.checkCollisionsY()
}
function keyPressed() {
keyInput[keyCode] = true;
}
function keyReleased() {
keyInput[keyCode] = false;
}
function rectCollide(x1, y1, w1, h1, x2, y2, w2, h2) {
return x1 + w1 > x2 && x1 < x2 + w2 && y1 + h1 > y2 && y1 < y2 + h2;
}
//BLOCK CONSTRUCTOR
class Block {
constructor(x, y, w, h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.movingSpeed = 3;
this.start = 200
this.stop = 400
}
draw() {
fill(255)
rect(this.x, this.y, this.w, this.h)
this.x += this.movingSpeed;
if (this.x > this.stop) {
this.movingSpeed = -this.movingSpeed;
}
if (this.x < this.start) {
this.movingSpeed = abs(this.movingSpeed);
}
}
checkCollisionsX() {
if (rectCollide(player.pos.x, player.pos.y, player.width, player.height, this.x, this.y, this.w, this.h)) {
if (player.vel.x < 0) { // If the player moved left and collided with the right side of block
player.pos.x = this.x + this.w;
} else { // If the player moved right and collided with the left side of block
player.pos.x = this.x - player.width;
}
player.vel.x = 0;
}
}
checkCollisionsY() {
if (rectCollide(player.pos.x, player.pos.y, player.width, player.height, this.x, this.y, this.w, this.h)) {
if (player.vel.y < 0) {
player.pos.y = this.y + this.h;
player.vel.y *= -yRebound; // Not -1 because collisions are not perfectly elastic
} else {
//player.pos.x += movingSpeed; //Keep player on platform while platform is moving
player.jumps = player.numJumps;
player.pos.y = this.y - player.height;
player.vel.y = 0;
player.acc.y = 0;
}
}
}
}
//PLAYER CONSTRUCTOR
class Player {
constructor(x, y) {
this.width = 50
this.height = 100
// all 3 chars for pretty code
this.pos = new p5.Vector(x, y);
this.vel = new p5.Vector(0, 0);
this.acc = new p5.Vector(0, 0);
this.accSpeed = 0.05;
this.gravity = 0.5;
this.maxVel = 10;
this.jumpForce = 15;
this.friction = 0.15;
this.numJumps = 1;
this.jumps = this.numJumps;
this.isGrounded = false;
this.canMove = true;
this.dir = "DOWN"
}
draw() {
fill(255, 0, 0)
rect(this.pos.x, this.pos.y, this.width, this.height)
}
moveX() {
//MOVE X
if (keyInput[LEFT_ARROW] && this.vel.x > -this.maxVel && this.canMove) {
this.acc.x = -this.accSpeed;
} else if (keyInput[RIGHT_ARROW] && this.vel.x < this.maxVel && this.canMove) {
this.acc.x = this.accSpeed;
} else if (abs(this.vel.x) > 0.2) {
this.acc.x = (this.vel.x < 0) ? this.friction : -this.friction;
} else {
this.vel.x = 0;
this.acc.x = 0;
}
this.vel.x += this.acc.x; // vel += acc
this.pos.x += this.vel.x; // pos += vel
}
moveY() {
//MOVE Y
if (keyInput[UP_ARROW] && this.jumps > 0 && this.canMove) {
this.jumps--;
this.vel.y = -this.jumpForce;
}
this.acc.y += this.gravity;
this.vel.y += this.acc.y;
this.pos.y += this.vel.y;
this.acc.y = 0; // Reset acceleration
if (this.pos.y >= height - this.height) {
this.pos.y = height-this.height
this.jumps = this.numJumps;
}
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/addons/p5.sound.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<main>
</main>
</body>
</html>
I'm making a 2D platformer game, and all block collisions work correctly except for the left side of a horizontally moving block. Here's what the block looks like (ignore the lag):
Here's the code that makes up the moving block:
if (type.equals("moving-horizontal-2x1")) {
image(img2x1, pos.x, pos.y, 200, 100);
pos.x += movingSpeed;
if (pos.x > stop) {
movingSpeed = -movingSpeed;
}
if (pos.x < start) {
movingSpeed = abs(movingSpeed);
}
}
When the player collides with the block, it works for all sides except the left side on the X axis, as shown by the image below.

This video shows what happens when the player collides with the moving block: https://www.youtube.com/watch?v=ewVSYd5h4rg
As you can see, the player gets moved to the other side of the block. I don't know why this is happening, since the collision detection/resolution code is the same as the other static blocks. Why does only one side work?
Here is my collision detection code for the X axis:
if (rectCollide(player.pos.x, player.pos.y, player.width, player.height, pos.x, pos.y, width, height)) {
if (player.vel.x < 0) { // If the player moved left and collided with the right side of block
player.pos.x = pos.x + width;
} else { // If the player moved right and collided with the left side of block (this is the broken side)
player.pos.x = pos.x - player.width;
}
player.vel.x = 0;
}
I've tried fixing this issue by incrementing the player's x pos when it collides with the left side, by doing something like player.pos.x += movingSpeed, but this still doesn't work.
I believe the bug has something to do with how I draw the moving block, since the collision detection/resolution code works perfectly fine with all other static blocks.
Thanks for any help!
