简体   繁体   English

html5 canvas移动元素

[英]html5 canvas move element

I am working on a car racing game in HTML5 and JS. 我正在使用HTML5和JS开发赛车游戏。 I am trying to move car using arrow keys. 我正在尝试使用箭头键移动汽车。 But it's not working. 但这不起作用。

How would you move an element in the canvas and is there any need to clear the entire canvas window before moving an element? 您将如何在画布中移动元素,并且在移动元素之前是否需要清除整个画布窗口?

Code: 码:

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");

var yCoordinate = 115;
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;
var distance = 10;
var speed = 0.5;
var angle = 25;

var car = new Image();
car.src = "./images/p1.png";

startGame();

function startGame(){
  requestAnimationFrame(moveLane);
}

function moveLane(){
  clearCanvas();  
  drawCar();
  drawLane(10 - yCoordinate);
  drawLane(60 - yCoordinate);
  drawLane(110 - yCoordinate);
  //speed of the lane
  yCoordinate = yCoordinate - 0.4;
  //if lane crossed the bottom boundrary then reset the y co-ordinate
  if (yCoordinate <= -145){
    yCoordinate = 115;
  }

  requestAnimationFrame(moveLane);
}

function drawCar(){
  context.drawImage(car, canvasWidth/2, canvasHeight/4, car.width*0.4, car.height*0.13);
  setCarControls();
}

function moveCarLeft(){
  clearCanvas();
  var x = canvasWidth/2 - distance;
  context.drawImage(car, x, canvasHeight/4, car.width*0.4, car.height*0.13);
}

function drawLane(yCoordinate){
  context.fillStyle = "#ffffff";
  context.fillRect(canvasWidth/2, yCoordinate, 10, 20);
}

function clearCanvas(){
  context.clearRect(0, 0, canvasWidth, canvasHeight);
}

function setCarControls() {
  document.addEventListener('keydown', function(e){
    switch(e.keyCode){
      case 37: 
        console.log('left');
        requestAnimationFrame(moveCarLeft);
        break;
      case 38:
        console.log('up');
        break;
      case 39:
        console.log('right');
        break;
      case 40:
        console.log('down');
        break;
    }
  });
}

Live Link: https://jsfiddle.net/jackysatpal/6j4c5dod/6/ 实时链接: https : //jsfiddle.net/jackysatpal/6j4c5dod/6/

I have updated the fiddle. 我已经更新了小提琴。 Check. 校验。 You were not using dynamic x coordinate. 您没有使用动态x坐标。

https://jsfiddle.net/6j4c5dod/7/ https://jsfiddle.net/6j4c5dod/7/

function moveCarLeft(){
 clearCanvas();
 currentX = currentX - 0.1;
 context.drawImage(car, currentX, canvasHeight/4, car.width*0.4, car.height*0.13);
 }

Here is my updated demo of how I would do it: https://jsfiddle.net/mulperi/1daahhap/ 这是我如何做的最新演示https : //jsfiddle.net/mulperi/1daahhap/

The basic idea (usually) for a game is to have an update -function (game loop) and a draw -function. 游戏的基本思想(通常)是具有更新功能(游戏循环)和平局功能。 The update function is the function you call with requestAnimationFrame() and it includes all the different things in your game that needs to be updated, like for example Player.update() etc. The draw function on the other hand takes care of clearing the screen with ctx.clearRect() and after that does Player.draw() and stuff like that. 更新函数是您使用requestAnimationFrame()调用的函数,它包含游戏中所有需要更新的不同内容,例如Player.update()等。另一方面,draw函数负责清除屏幕使用ctx.clearRect(),然后执行Player.draw()以及类似的操作。

In my example the player movement is done by listening keydown and keyup and toggling a variable to be either true / false according to what is happening on the keyboard. 在我的示例中,玩家的移动是通过侦听键盘按下和键盘输入并根据键盘上发生的事情将变量切换为true / false来完成的。 Player.update -function only checks the variable and moves if the key is pressed (ArrowLeft for example). Player.update -function仅检查变量并在按下键时移动(例如,ArrowLeft)。

Below full code: 下面的完整代码:

<!DOCTYPE html>
<html>

  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>World's BEstest Game</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
  </head>

  <body>
    <canvas id="canvas" style="border:1px solid black;">

  </canvas>
    <script>
      const c = document.getElementById("canvas");
      const ctx = c.getContext("2d");

      /*
          TODO: Change player to Class based object
      */
      keyPresses = {};
      player = {
        x: 100,
        y: 100,
        update: () => {
          if (keyPresses['ArrowLeft']) {
            player.x -= 1;
          }
          if (keyPresses['ArrowRight']) {
            player.x += 1;
          }
          if (keyPresses['ArrowUp']) {
            player.y -= 1;
          }
          if (keyPresses['ArrowDown']) {
            player.y += 1;
          }
        },
        draw: () => {
          ctx.fillStyle = "black";
          ctx.beginPath();
          ctx.arc(player.x, player.y, 10, 0, Math.PI * 2, false);
          ctx.closePath();
          ctx.fill();
        }
      };

      function listenKeyboard() {
        document.addEventListener("keyup", keyUp.bind(this));
        document.addEventListener("keydown", keyDown.bind(this));
      };

      function keyUp(e) {
        keyPresses[e.key] = false;
      };

      function keyDown(e) {
        console.log(e.key)
        keyPresses[e.key] = true;
      };

      /*
        Everything drawing and graphics related goes here and also
        clearing the screen before drawing each frame.
      */
      function draw() {
        ctx.clearRect(0, 0, 300, 300);
        player.draw();
      };

      /*
        All the update methods go here
      */
      function update() {
        draw();
        listenKeyboard();
        player.update();
        requestAnimationFrame(update);
      };

      requestAnimationFrame(update);

    </script>
  </body>

</html>

So I hope this helps you to think about the structure of your game functions, makes it easier to read and understand and maybe gives you some inspiration! 因此,我希望这可以帮助您考虑游戏功能的结构,使其更易于阅读和理解,并可能给您带来一些启发! Happy coding :) 快乐的编码:)

I think you have 3 options: 我认为您有3种选择:

I'd really go for multiple canvases (for things that don't change like the background sky, draw it once), because save/restore can also be expensive operation. 我真的会去多张画布(对于那些不会改变的东西,例如背景天空,只需绘制一次),因为保存/恢复也可能是昂贵的操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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