Reputation: 49
I'm having lots of issues with my gravity and jumping. My code doesn't execute how I want it to, and I've been messing around with it for a while. The jumping is bugging and the moving isn't as smooth as I want it. I want my gravity to work while i'm still jumping, so I set it to zero, but it just doesn't look natural. Here's my code. I hope someone can help
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
canvas.width = 800
canvas.height = 600
class Main {
constructor(x, y, w, h) {
this.x = x
this.y = y
this.w = w
this.h = h
this.lives = 3;
this.speedX = 0;
this.speedY = 0;
this.gravity = 0.03;
this.gravitySpeed = 0;
this.dx = 0;
this.dy = 0;
}
draw() {
ctx.beginPath();
ctx.rect(this.x, this.y, this.w, this.h);
ctx.fill()
ctx.closePath();
}
newPos() {
this.gravitySpeed += this.gravity;
this.x += this.speedX;
this.y += this.speedY + this.gravitySpeed;
}
update() {
if(this.y >= canvas.height - 50) {
this.y = canvas.height - 50
}
if (controller1.up) {this.dy -= 2, this.gravity = 0.01};
if (controller1.right) {this.dx += 0.5};
if (controller1.left) {this.dx -= 0.5};
this.x += this.dx;
this.y += this.dy;
this.dx *= 0.9;
this.dy *= 0.9;
this.draw();
}
}
class Controller {
constructor() {
this.up = false;
this.right = false;
this.down = false;
this.left = false;
let keyEvent = (e) => {
if (e.code == "KeyW" || e.code == "ArrowUp") {this.up = e.type == 'keydown'};
if (e.code == "KeyD" || e.code == "ArrowRight") {this.right = e.type == 'keydown'};
if (e.code == "KeyA" || e.code == "ArrowLeft") {this.left = e.type == 'keydown'};
}
addEventListener('keydown', keyEvent);
addEventListener('keyup', keyEvent);
addEventListener('mousemove', keyEvent)
}
}
let main1 = new Main(canvas.width / 2, canvas.height / 2, 50, 50)
let controller1 = new Controller();
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
main1.update();
requestAnimationFrame(animate)
}
function updatePos() {
main1.newPos();
}
animate()
setInterval(updatePos, 10)
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="canvas"></canvas>
<script src="main.js"></script>
</body>
</html>
Upvotes: 0
Views: 1153
Reputation: 2958
I would set your gravity to a global variable to start. This will allow all objects you create to reference the same gravity value. Depending on how much gravity you set will change how much negative value you give your jump command. I also add a separate canvasCollision()
function in the class for this example.
Also keep in mind I changed the canvas size for this example.
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
canvas.width = 400;
canvas.height = 300;
const gravity = 2;
class Main {
constructor(x, y, w, h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.lives = 3;
this.speedX = 0.5;
this.speedY = 35;
this.jumping = false;
this.vx = 0;
this.vy = 0;
}
draw() {
ctx.beginPath();
ctx.rect(this.x, this.y, this.w, this.h);
ctx.fill();
ctx.closePath();
}
canvasCollision() {
if (this.x <= 0) this.x = 0;
if (this.y <= 0) this.y = 0;
if (this.x + this.w >= canvas.width) this.x = canvas.width - this.w;
if (this.y + this.h >= canvas.height) {
this.y = canvas.height - this.h;
this.vy = 0;
this.jumping = false;
}
}
update() {
if (controller1.left) this.vx -= this.speedX;
if (controller1.up && !this.jumping) {
this.vy -= this.speedY;
this.jumping = true;
}
if (controller1.right) this.vx += this.speedX;
this.vy += gravity;
this.x += this.vx;
this.y += this.vy;
this.vx *= 0.9;
this.vy *= 0.9;
this.canvasCollision();
}
}
class Controller {
constructor() {
this.up = false;
this.right = false;
this.down = false;
this.left = false;
let keyEvent = (e) => {
if (e.code == "KeyW" || e.code == "ArrowUp") {
this.up = e.type == "keydown";
}
if (e.code == "KeyD" || e.code == "ArrowRight") {
this.right = e.type == "keydown";
}
if (e.code == "KeyA" || e.code == "ArrowLeft") {
this.left = e.type == "keydown";
}
};
addEventListener("keydown", keyEvent);
addEventListener("keyup", keyEvent);
addEventListener("mousemove", keyEvent);
}
}
let main1 = new Main(canvas.width / 2, canvas.height / 2, 50, 50);
let controller1 = new Controller();
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
main1.update();
main1.draw();
requestAnimationFrame(animate);
}
animate();
<canvas id="canvas"></canvas>
Upvotes: 1
Reputation: 757
Great effort thus far. Game dev can be a bit tricky in the beginning to get things look and feel like you want it. I modified your main class a bit and made the jump a bit smoother. You are not using dt (delta time) which makes it easier to handle jumping with gravity (not the only way to do it). And remember that gravity is a constant, if you set it to 0 it means we have nothing to pull the player back onto the ground. Gravity is always there and when we jump we counter it for a second or two.
If you want to read some more about this you can google on "2D game physics + jumping" or something similar. Here are some links that I found on the topic.
https://gamedev.stackexchange.com/questions/32631/easy-way-to-do-gravity-in-a-simple-game https://www.gamedev.net/tutorials/_/technical/math-and-physics/a-verlet-based-approach-for-2d-game-physics-r2714/ https://gamedev.stackexchange.com/questions/60008/smooth-jumping-in-2d-platformers
I recommend the Game Development community on Stack Overflow for these questions too https://gamedev.stackexchange.com/
Feel free to ask if you have further questions
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
canvas.width = 600
canvas.height = 200
let time; // Current time
let prevTime = Date.now(); // Store previous time
let isGrounded; // Check if player is on the ground
class Main {
constructor(x, y, w, h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.lives = 3;
this.speedX = 0;
this.speedY = 0;
this.gravity = .01;
// this.gravitySpeed = 0;
this.jumpSpeed = -1.5; // How fast to jump upwards
this.dx = 0;
this.dy = 0;
}
draw() {
ctx.beginPath();
ctx.rect(this.x, this.y, this.w, this.h);
ctx.fill()
ctx.closePath();
}
newPos() {
this.gravitySpeed += this.gravity;
this.x += this.speedX;
}
update() {
// Calculate how much time has passed since last update
time = Date.now();
const deltaTime = time - prevTime;
// Update y-position based speed in y-direction
// If we jump this.speed will be set to this.jumpSpeed
this.y += this.speedY * deltaTime;
// Gravity should always affect the player!
// The ground check will make sure we don't fall through the floor
this.y += this.gravity * deltaTime;
// Make sure to reduce our player's speed in y by gravity!
this.speedY += this.gravity * deltaTime;
// Only allow the player to jump if he is on the ground
if (controller1.up && isGrounded) {
// Set the player y-speed to jump speed
this.speedY = this.jumpSpeed;
};
if (controller1.right) {this.dx += 0.5};
if (controller1.left) {this.dx -= 0.5};
this.x += this.dx;
// this.y += this.dy;
this.dx *= 0.9;
this.dy *= 0.9;
// Ground check
if(this.y >= canvas.height - 50) {
this.y = canvas.height - 50;
isGrounded = true;
} else {
isGrounded = false;
}
this.draw();
// Store the current time to use for calculation in next update
prevTime = Date.now();
}
}
class Controller {
constructor() {
this.up = false;
this.right = false;
this.down = false;
this.left = false;
let keyEvent = (e) => {
if (e.code == "KeyW" || e.code == "ArrowUp") {this.up = e.type == 'keydown'};
if (e.code == "KeyD" || e.code == "ArrowRight") {this.right = e.type == 'keydown'};
if (e.code == "KeyA" || e.code == "ArrowLeft") {this.left = e.type == 'keydown'};
}
addEventListener('keydown', keyEvent);
addEventListener('keyup', keyEvent);
addEventListener('mousemove', keyEvent)
}
}
let main1 = new Main(canvas.width / 2, canvas.height / 2, 50, 50)
let controller1 = new Controller();
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
main1.update();
requestAnimationFrame(animate)
}
function updatePos() {
main1.newPos();
}
animate()
setInterval(updatePos, 10)
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
canvas {
background-color: azure;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script src="main.js"></script>
</body>
</html>
Upvotes: 2