Canvas JS游戏,可以使角色触及地面后仅一次跳跃一次

发布于 2025-02-07 07:31:59 字数 3447 浏览 0 评论 0原文

这是我的画布游戏的代码,我的角色能够向右走并跳跃。问题是我想让角色只跳一次,然后再次触摸地面,现在可以再次跳跃。在我的代码中,如果我多次按W将永远跳动。

const canvas = document.querySelector("canvas");
const c = canvas.getContext('2d')

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

const gravity = 0.5;
let isGrounded;

class Player {
  constructor() {
    this.position = {
      x: 100,
      y: 100
    }
    this.width = 100
    this.height = 100
    this.velocity = {
      x: 0,
      y: 1
    }
  }
  draw() {
    c.fillStyle = 'black'
    c.fillRect(this.position.x, this.position.y,
      this.width, this.height)
  }

  update() {
    this.draw();
    this.position.x += this.velocity.x;
    this.position.y += this.velocity.y;

    if (this.position.y + this.height + this.velocity.y >= canvas.height)
      this.velocity.y = 0
    else this.velocity.y += gravity;
  }
}

class Platform {
  constructor({
    x,
    y
  }) {
    this.position = {
      x: x,
      y: y
    }
    this.width = 400
    this.height = 20
  }

  draw() {
    c.fillStyle = 'black'
    c.fillRect(this.position.x, this.position.y,
      this.width, this.height)
  }
}

const player = new Player()
const platforms = [
  new Platform({
    x: 150,
    y: 800,
  }),
  new Platform({
    x: 700,
    y: 900
  }),
];

const keys = {
  right: {
    pressed: false
  },
  left: {
    pressed: false
  },
  up: {
    pressed: false
  }
}

let scrollOffset = 0

function animate() {
  const JUMP_SPEED = 5
  requestAnimationFrame(animate)
  c.clearRect(0, 0, canvas.width, canvas.height)
  player.update();
  platforms.forEach(platform => {
    platform.draw()
  })

  if (keys.right.pressed && player.position.x < 400) {
    player.velocity.x = 5
  } else if (keys.left.pressed && player.position.x > 100) {
    player.velocity.x = -5
  } else {
    player.velocity.x = 0

    if (keys.right.pressed) {
      scrollOffset += 5;
      platforms.forEach((platform) => {
        platform.position.x -= 5;
      });
    } else if (keys.left.pressed) {
      scrollOffset -= 5
      platforms.forEach((platform) => {
        platform.position.x += 5;
      });
    }
  }
  //platform collision detection
  platforms.forEach(platform => {
    if (player.position.y + player.height <= platform.position.y &&
      player.position.y + player.height + player.velocity.y >= platform.position.y &&
      player.position.x + player.width >= platform.position.x &&
      player.position.x <= platform.position.x + platform.width) {
      player.velocity.y = 0
    }
  })
  if (scrollOffset > 300) {
    console.log('u win')
  }
}

animate()

window.addEventListener('keydown', ({keyCode}) => {
  switch (keyCode) {
    case 65:
      keys.left.pressed = true;
      break;
    case 83:
      break;
    case 68:
      keys.right.pressed = true;
      break;
    case 87:
      keys.up.pressed = true;
      player.velocity.y = -10
      break;
  }
})

window.addEventListener("keyup", ({keyCode}) => {
  switch (keyCode) {
    case 65:
      keys.left.pressed = false;
      break;
    case 83:
      break;
    case 68:
      keys.right.pressed = false;
      break;
    case 87:
      keys.up.pressed = false;
      break;
  }
});
<canvas></canvas>

this is my code for a canvas game, my character is able to go left right and jump. The problem is that i want to make the character jump only once, then touch the ground again and now, to be able to jump again. In my code if i press w multiple times will jump forever.

const canvas = document.querySelector("canvas");
const c = canvas.getContext('2d')

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

const gravity = 0.5;
let isGrounded;

class Player {
  constructor() {
    this.position = {
      x: 100,
      y: 100
    }
    this.width = 100
    this.height = 100
    this.velocity = {
      x: 0,
      y: 1
    }
  }
  draw() {
    c.fillStyle = 'black'
    c.fillRect(this.position.x, this.position.y,
      this.width, this.height)
  }

  update() {
    this.draw();
    this.position.x += this.velocity.x;
    this.position.y += this.velocity.y;

    if (this.position.y + this.height + this.velocity.y >= canvas.height)
      this.velocity.y = 0
    else this.velocity.y += gravity;
  }
}

class Platform {
  constructor({
    x,
    y
  }) {
    this.position = {
      x: x,
      y: y
    }
    this.width = 400
    this.height = 20
  }

  draw() {
    c.fillStyle = 'black'
    c.fillRect(this.position.x, this.position.y,
      this.width, this.height)
  }
}

const player = new Player()
const platforms = [
  new Platform({
    x: 150,
    y: 800,
  }),
  new Platform({
    x: 700,
    y: 900
  }),
];

const keys = {
  right: {
    pressed: false
  },
  left: {
    pressed: false
  },
  up: {
    pressed: false
  }
}

let scrollOffset = 0

function animate() {
  const JUMP_SPEED = 5
  requestAnimationFrame(animate)
  c.clearRect(0, 0, canvas.width, canvas.height)
  player.update();
  platforms.forEach(platform => {
    platform.draw()
  })

  if (keys.right.pressed && player.position.x < 400) {
    player.velocity.x = 5
  } else if (keys.left.pressed && player.position.x > 100) {
    player.velocity.x = -5
  } else {
    player.velocity.x = 0

    if (keys.right.pressed) {
      scrollOffset += 5;
      platforms.forEach((platform) => {
        platform.position.x -= 5;
      });
    } else if (keys.left.pressed) {
      scrollOffset -= 5
      platforms.forEach((platform) => {
        platform.position.x += 5;
      });
    }
  }
  //platform collision detection
  platforms.forEach(platform => {
    if (player.position.y + player.height <= platform.position.y &&
      player.position.y + player.height + player.velocity.y >= platform.position.y &&
      player.position.x + player.width >= platform.position.x &&
      player.position.x <= platform.position.x + platform.width) {
      player.velocity.y = 0
    }
  })
  if (scrollOffset > 300) {
    console.log('u win')
  }
}

animate()

window.addEventListener('keydown', ({keyCode}) => {
  switch (keyCode) {
    case 65:
      keys.left.pressed = true;
      break;
    case 83:
      break;
    case 68:
      keys.right.pressed = true;
      break;
    case 87:
      keys.up.pressed = true;
      player.velocity.y = -10
      break;
  }
})

window.addEventListener("keyup", ({keyCode}) => {
  switch (keyCode) {
    case 65:
      keys.left.pressed = false;
      break;
    case 83:
      break;
    case 68:
      keys.right.pressed = false;
      break;
    case 87:
      keys.up.pressed = false;
      break;
  }
});
<canvas></canvas>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

执妄 2025-02-14 07:31:59

您可以为播放器提供跳跃标志,然后检查该标志:

class Player {
  constructor() {
    this.position = {
      x: 100,
      y: 100
    }
    this.jumping = false;
    ...
  }
  ...
  jump() {
    if (!this.jumping) {
      this.jumping = true;
      this.velocity.y -= 10; // you want relative velocity, not absolute.
    }
  }
}

然后,您可以使用简单的,如果(!this.yumping)跳转键时跳跃

const keyDownHandlers = {
  "a": () => {
     keys.left.pressed = true;
   },
   "d": () => {
     keys.left.pressed = true;
   },
   "w": () => {
     keys.up.pressed = true;
     player.jump();
   }
};

window.addEventListener('keydown', ({ key } => {
  keyDownHandlers[key]?.();
})

。这也将使玩家跌落时跳跃(每当您添加时),因此您想要的是检查玩家当前是否处于碰撞状态。特别是如果这些固定装置移动(例如,您希望在电梯上站立时能够跳跃,尽管您的速度向量已经具有非零y值)。

class Player {
  constructor() {
    this.position = {
      x: 100,
      y: 100
    }
    ...
  }
  ...
  jump() {
    if (this.isOnFixture()) {
      this.velocity.y -= 10;
    }
  }
  isOnFixture() {
    // you get to implement this one
  }
}

而且,由于您已经编写了碰撞检测代码,因此onfixture()功能的功能主要是移动您当前在Anime中运行的代码的问题。进入播放器类中,作为一个专用函数,您可以在isonFixture()中调用该功能。

You could give the player a jumping flag, and check for that flag:

class Player {
  constructor() {
    this.position = {
      x: 100,
      y: 100
    }
    this.jumping = false;
    ...
  }
  ...
  jump() {
    if (!this.jumping) {
      this.jumping = true;
      this.velocity.y -= 10; // you want relative velocity, not absolute.
    }
  }
}

Then you can use a simple if (!this.jumping) jump when the jump keydown happens:

const keyDownHandlers = {
  "a": () => {
     keys.left.pressed = true;
   },
   "d": () => {
     keys.left.pressed = true;
   },
   "w": () => {
     keys.up.pressed = true;
     player.jump();
   }
};

window.addEventListener('keydown', ({ key } => {
  keyDownHandlers[key]?.();
})

But that will also allow the player to jump when they're falling (whenever you add that), so really what you want is a check to see if the player is currently in a collision state with a fixture or not. especially if those fixtures move (e.g. you want to be able to jump while standing on an elevator, despite your velocity vector already having a non-zero y value).

class Player {
  constructor() {
    this.position = {
      x: 100,
      y: 100
    }
    ...
  }
  ...
  jump() {
    if (this.isOnFixture()) {
      this.velocity.y -= 10;
    }
  }
  isOnFixture() {
    // you get to implement this one
  }
}

And since you already have collision detection code written, the onFixture() function for a player should mostly be a matter of moving the code that you're currently running in anime either into the player class, as into a dedicate function that you can then call inside isOnFixture().

风启觞 2025-02-14 07:31:59
addEventListener('keydown', ({ keyCode }) => {
    // console.log(keyCode)
    switch (keyCode) {
        case 37:
            console.log("left")
            keys.left.pressed = true
            break
        case 38:
            if(player.velocity.y == 0) {
                player.velocity.y += -14
            }
            else {
                console.log("not ready")
            }

            break
        case 40:
            console.log('down')
            break
        case 39:
            console.log('right')
            keys.right.pressed = true
            break;

    }

})

只需检查播放器y速度是否为零,如果这样,他们可以再次跳跃,也可以在第一个ActionListener中添加它:

addEventListener('keyup', ({ keyCode }) => {
    //console.log(keyCode)
    switch (keyCode) {
        case 37:
            console.log("left")
            keys.left.pressed = false
            break
        case 38:
            console.log('up')
            player.velocity.y += +15
            if (event.repeat) { return }
            player.velocity.y += -14
            break
        case 40:
            console.log('down')
            break
        case 39:
            console.log('right')
            keys.right.pressed = false

    }

});
addEventListener('keydown', ({ keyCode }) => {
    // console.log(keyCode)
    switch (keyCode) {
        case 37:
            console.log("left")
            keys.left.pressed = true
            break
        case 38:
            if(player.velocity.y == 0) {
                player.velocity.y += -14
            }
            else {
                console.log("not ready")
            }

            break
        case 40:
            console.log('down')
            break
        case 39:
            console.log('right')
            keys.right.pressed = true
            break;

    }

})

just check if the player y velocity is zero and if so they are able to jump again and also add this instead on the first actionlistener:

addEventListener('keyup', ({ keyCode }) => {
    //console.log(keyCode)
    switch (keyCode) {
        case 37:
            console.log("left")
            keys.left.pressed = false
            break
        case 38:
            console.log('up')
            player.velocity.y += +15
            if (event.repeat) { return }
            player.velocity.y += -14
            break
        case 40:
            console.log('down')
            break
        case 39:
            console.log('right')
            keys.right.pressed = false

    }

});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文