javascript - 在我的 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(增量时间),它可以更轻松地处理重力跳跃(不是唯一的方法)。请记住,重力是一个常数,如果将其设置为 0,则意味着我们无法将玩家拉回地面。重力总是存在的,当我们跳跃时,我们会反击一两秒钟。
如果您想了解更多有关此内容的信息,可以在“2D 游戏物理 + 跳跃”或类似内容上搜索。这是我在该主题上找到的一些链接。
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
对于这些问题,我也推荐 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>
推荐阅读
- android - 是否仅为公共属性创建了支持属性?
- jstl - 我试图在 jstl 的帮助下使用 sql 但遇到异常
- php - 对加密的 PHP 对象进行排序
- ios - 无法从 Spring Boot 向 FCM 和远程用户发送推送通知?
- powershell - 正则表达式替换引号中的字符串路径
- python - python tkinter 没有在框架内创建另一个框架
- math - 算术表达式和大步语义
- vba - 如何使用 for 循环 vba 更改对象的名称?
- c - C 程序在 Apple Silicon macOS 上收到“killed 9”,但在 Intel 上很好
- javascript - Firestore - 从“collectionName/{id}”之类的引用中获取数据并遍历结果列表