首页 > 解决方案 > Html5画布动画留下痕迹

问题描述

我正在尝试制作一个小游戏来玩画布。我决定选择Flappy Bird,因为网上有很多例子。我的目标是让游戏对所有设备都“响应”。如果您在手机或任何屏幕中打开它,您应该可以正常播放它。

为此,我在画布中绘制了一个背景图像,它将使高度适应屏幕的高度,并通过 x 轴重复它。

飞扬的鸟

我遇到的问题是,当我为这只鸟设置动画时,它会在它身后留下一条痕迹。

就像这样:

                                           https://i.stack.imgur.com/xu0Vzm.png

如本文所述,一个简单的解决方法是清除画布:

向左移动时画布图像留下奇怪的痕迹

但这是不可能的,因为我画背景的方式(我画了一次,如果调整大小就重新画)。

问题

如何避免这种带有静态背景的图像轨迹?是否有可能拥有不需要重新绘制的虚假静态背景?

我显然想在画布上做,而不需要在 html 中有图像。

这是具有主要功能的代码,您可以看一下:

const cvs = document.getElementById("canvas");
const ctx = cvs.getContext("2d");

cvs.style.height = "100vh";
cvs.style.width = "100vw";

var bird = new Image();
var bg = new Image();

bird.src = "https://lh3.googleusercontent.com/prntPuix7QxlhKXx6IBtTxv7PrdEJtmzFJ4mopScNS1_klze86BVNy3PqHbQn2UQ4JyJdix3XQ=w128-h128-e365";
bg.src = "https://opengameart.org/sites/default/files/bg_5.png";

let gravity = 1;
birdPositionY = 10;
birdPositionX = 50;

const draw = () => {
  ctx.drawImage(bird, birdPositionX, birdPositionY);

  birdPositionY += gravity;
  birdPositionX += 3;

  requestAnimationFrame(draw);
};

const resizeCanvas = () => {
  const {
    width,
    height
  } = cvs.getBoundingClientRect();
  cvs.height = height;
  cvs.width = width;

  let x = 0,
    y = 0;
  while (x < cvs.width && y < cvs.height) {
    ctx.drawImage(bg, x, y, 360, cvs.height);
    x += bg.width;
  }
};

bg.onload = () => {
  resizeCanvas();
};

window.addEventListener("resize", resizeCanvas, false);

draw();
<!DOCTYPE html>
<html>

<head>
  <title>Flappy Bird</title>
  <meta name="viewport" content="width=device-width, user-scalable=no" />
  <style>
    html {
      overflow: hidden;
    }
    
    body {
      margin: 0;
    }
    
    canvas {
      width: 100vw;
      height: 100vh;
    }
  </style>
</head>

<body>
  <canvas id="canvas"></canvas>
  <script src="index.js"></script>
</body>

</html>

希望它确实有意义!

提前致谢!

标签: javascripthtmlcsscanvashtml5-canvas

解决方案


在您将保持在屏幕外的画布上绘制背景,然后在绘制移动部件之前在可见帧上绘制每一帧。

const cvs = document.getElementById("canvas");
const ctx = cvs.getContext("2d");
// our backround canvas that we won't append in the doc ("off-screen")
const background = cvs.cloneNode();
const bg_ctx = background.getContext('2d');

cvs.style.height = "100vh";
cvs.style.width = "100vw";

var bird = new Image();
var bg = new Image();

bird.src = "https://lh3.googleusercontent.com/prntPuix7QxlhKXx6IBtTxv7PrdEJtmzFJ4mopScNS1_klze86BVNy3PqHbQn2UQ4JyJdix3XQ=w128-h128-e365";
bg.src = "https://opengameart.org/sites/default/files/bg_5.png";

let gravity = 1;
birdPositionY = 10;
birdPositionX = 50;

const draw = () => {
  // first draw the background canvas
  ctx.drawImage(background, 0,0);
  // then your persona
  ctx.drawImage(bird, birdPositionX, birdPositionY);

  birdPositionY += gravity;
  birdPositionX += 3;

  requestAnimationFrame(draw);
};

const resizeCanvas = () => {
  const {
    width,
    height
  } = cvs.getBoundingClientRect();
  // resize both canvases
  cvs.height = background.height = height;
  cvs.width = background.width = width;

  let x = 0,
    y = 0;
  while (x < cvs.width && y < cvs.height) {
    // draw on the off-screen canvas
    bg_ctx.drawImage(bg, x, y, 360, cvs.height);
    x += bg.width;
  }
};

bg.onload = () => {
  resizeCanvas();
  draw();
};

window.addEventListener("resize", resizeCanvas, false);
<!DOCTYPE html>
<html>

<head>
  <title>Flappy Bird</title>
  <meta name="viewport" content="width=device-width, user-scalable=no" />
  <style>
    html {
      overflow: hidden;
    }
    
    body {
      margin: 0;
    }
    
    canvas {
      width: 100vw;
      height: 100vh;
    }
  </style>
</head>

<body>
  <canvas id="canvas"></canvas>
  <script src="index.js"></script>
</body>

</html>


推荐阅读