Javascript canvas 动画精灵行走
Javascript canvas animate sprite walking
我正在尝试让精灵在 canvas 的背景图像上行走。理想情况下,我会在一个 canvas 上完成这一切,但使用两个似乎更有效、更容易。
我目前拥有的:
和
来自 fiddle 1 的代码,正在处理最简单的动画形式:
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);
}
我希望能够让它正确行走,并了解它是如何工作的。我看到两者都使用了类似于 sprite.width
和 sprite.height
的东西,我认为应该是 width/columns
和 height/rows
,但它们似乎无法正常工作。
你的坐标全错了。您的 spriteWidth 和 spriteHeight 值与 spritesheet 的所有值都不匹配。
此外,您的逻辑仅更新 x 轴,而您的精灵 sheet 设置在多行上。
您需要更新此逻辑,以便同时更新 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>
我正在尝试让精灵在 canvas 的背景图像上行走。理想情况下,我会在一个 canvas 上完成这一切,但使用两个似乎更有效、更容易。
我目前拥有的:
和
来自 fiddle 1 的代码,正在处理最简单的动画形式:
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);
}
我希望能够让它正确行走,并了解它是如何工作的。我看到两者都使用了类似于 sprite.width
和 sprite.height
的东西,我认为应该是 width/columns
和 height/rows
,但它们似乎无法正常工作。
你的坐标全错了。您的 spriteWidth 和 spriteHeight 值与 spritesheet 的所有值都不匹配。
此外,您的逻辑仅更新 x 轴,而您的精灵 sheet 设置在多行上。
您需要更新此逻辑,以便同时更新 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>