首页 > 解决方案 > 在我的 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>

标签: javascripthtml

解决方案


到目前为止,付出了巨大的努力。游戏开发一开始可能会有点棘手,要让事情看起来和感觉像你想要的那样。我稍微修改了你的主课,使跳跃更顺畅。您没有使用 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>


推荐阅读