简体   繁体   中英

Jumping, moving, and gravity in my 2D javascript game

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>

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>

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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM