在我的2D javascript游戏中跳跃、移动和重力



我的重力和跳跃有很多问题。我的代码不能按我希望的方式执行,我已经花了一段时间来处理它了。跳跃很麻烦,移动也没有我想要的那么顺利。我希望我的重力在跳跃时发挥作用,所以我把它设置为零,但它看起来不自然。这是我的密码。我希望有人能帮助

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>

迄今为止付出了巨大努力。游戏开发在一开始可能会有点棘手,让事情看起来和感觉像你想要的。我修改了你的主类,使跳跃更流畅。你没有使用dt(delta时间(,这使你更容易处理重力跳跃(不是唯一的方法(。记住,重力是一个常数,如果你把它设置为0,就意味着我们没有什么可以把球员拉回到地面上。重力总是存在的,当我们跳跃时,我们会克服它一两秒钟。

如果你想阅读更多关于这方面的内容,你可以在";2D游戏物理+跳跃";或者类似的东西。以下是我在这个话题上找到的一些链接。

https://gamedev.stackexchange.com/questions/32631/easy-way-to-do-gravity-in-a-simple-gamehttps://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

对于这些问题,我也推荐Stack Overflow上的游戏开发社区https://gamedev.stackexchange.com/

如果您还有其他问题,请随时询问

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>

我会将重力设置为全局变量开始。这将允许您创建的所有对象引用相同的重力值。根据您设置的重力大小,将更改您给出跳跃命令的负值大小。我还在这个例子的类中添加了一个单独的canvasCollision()函数。

还要记住,我为这个例子更改了画布大小。

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>

最新更新