首页 > 解决方案 > Javascript canvas animate sprite walking

问题描述

I am trying to get a sprite to walk over a background image with canvas. Ideally, I would do this all on one canvas, but using two seems to be more efficient and easier.

What I have so far:

Fiddle 1

and

Fiddle 2

Code from fiddle 1, working on the simplest form of the animation:

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

var spritePosition = 0;
var spriteWidth = 50;
var spriteHeight = 225;
var spriteCount = 17;
var spritePlayCount = 0;
var maxSpritePlays = 3;

var sheet = new Image();
sheet.onload = function () {
    animate();
}
sheet.src = "https://s33.postimg.cc/dapcxzmvj/sprite_walk.png";

var fps = 15;



function animate() {
    setTimeout(function () {

        if (spritePlayCount < maxSpritePlays) {
            requestAnimationFrame(animate);
        }

        // Drawing code goes here
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.drawImage(sheet,
        spritePosition * spriteWidth, 0, spriteWidth, spriteHeight,
        0, 0, spriteWidth, spriteHeight);

        spritePosition++;
        if (spritePosition > spriteCount - 1) {
            spritePosition = 0;
            spritePlayCount++;
        }

    }, 1000 / fps);
}

I want to be able to get this to walk correctly, and understand how it works. I see both use something along the lines of sprite.width and sprite.height, which I figured would be width/columns and height/rows but those dont seem to work properly.

标签: javascriptanimationcanvassprite

解决方案


你的坐标全错了。您的spriteWidth和 spriteHeight 值与 spritesheet 的所有值都不匹配。

此外,您的逻辑仅更新 x 轴,而您的精灵表设置在多行上。
您需要更新此逻辑,以便更新 x 和 y 源位置。

最后,不要像这样混合 setTimeout 和 requestAnimationFrame 。他们永远不会相处融洽。要达到 15FPS,您可以很容易地运行 requestAnimationFrame 循环,该循环将以 60FPS 触发,并且只需每四帧绘制一次(60FPS / 4 => 15FPS)。

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

var xIndex = 0;
var yIndex = 0;
var cols = 5;
var rows = 4;
var spriteWidth = 265;
var spriteHeight = 200;

var sheet = new Image();
sheet.onload = function() {
  animate();
}
sheet.src = "https://i.stack.imgur.com/eL5yV.png";
var frame = 0;

function animate() {
  requestAnimationFrame(animate);
  // 60FPS / 4 => 15FPS
  if ((++frame) % 4 > 0) return;

  ctx.clearRect(0, 0, canvas.width, canvas.height);
  // update the current column
  xIndex = (xIndex + 1) % cols;
  // update the current row if x is 0
  yIndex = xIndex === 0 ? (yIndex + 1) % rows : yIndex;
  // three cells are empty on the last row...
  if (yIndex === (rows - 1) && xIndex === 2)
    xIndex = yIndex = 0;
  // update both sourceX and sourceY
  ctx.drawImage(sheet,
    xIndex * spriteWidth, yIndex * spriteHeight, spriteWidth, spriteHeight,
    0, 0, spriteWidth, spriteHeight);
}
<canvas id="canvas" width=350 height=350></canvas>


推荐阅读