我对 Canvas 比较陌生。在找到我的脚的过程中,我正在创建一个简单的街机游戏。
我的问题是关于 CPU 性能/效率。
我在黑色背景上创建 100 个随机放置的白点作为星星。在每个 requestAnimationFrame 上,星星向左移动一个像素,当它们到达最左边时,该像素列将放置在屏幕的最右边。
我正在使用 requestAnimationFrame 调用以下函数:
bgAnimateId = requestAnimationFrame( scrollBg );
function scrollBg() {
var imgData = ctx.getImageData( 0, 0, 1, canvas.height );
var areaToMoveLeft = ctx.getImageData( 1, 0, canvas.width-1, canvas.height );
ctx.putImageData( areaToMoveLeft, 0, 0 );
ctx.putImageData( imgData, canvas.width-1, 0 );
bgAnimateId = requestAnimationFrame( scrollBg );
}
我担心的是 - 创建 100 个小 Canvas 元素(或 100 个 div)并为其设置动画会更好,还是使用我在上面使用的像素方法更好。
非常感谢您提前的帮助/指导:-)
最佳答案
事实证明,context.getImageData
和 context.putImageData
的执行成本非常高,而且拥有 100 个 Canvas 太多了。
所以这里有一个创建高效平移星场的计划:
使用 context.drawImage
非常高效,而且执行起来并不昂贵。
以下是如何在 Canvas 上随机绘制星空,然后将该 Canvas 保存为图像:
// draw a random starfield on the canvas
bkCtx.beginPath();
bkCtx.fillStyle="darkblue";
bkCtx.rect(0,0,background.width,background.height);
bkCtx.fill();
bkCtx.beginPath();
for(var n=0;n<100;n++){
var x=parseInt(Math.random()*canvas.width);
var y=parseInt(Math.random()*canvas.height);
var radius=Math.random()*3;
bkCtx.arc(x,y,radius,0,Math.PI*2,false);
bkCtx.closePath();
}
bkCtx.fillStyle="white";
bkCtx.fill();
// create an new image using the starfield canvas
var img=document.createElement("img");
img.src=background.toDataURL();
您将进行两种绘图:
- 星星的平移背景
- 将在其中绘制游戏对象的前景。
因此创建 2 个彼此对齐的 Canvas 。后面的 Canvas 是星星,前面的 Canvas 是你的游戏对象。
这是平移星空运动图像的背景 Canvas :
这是游戏对象所在的前景 Canvas ——看我俗气的“火箭”
这些是堆叠起来创建背景/前景组合的 2 个 Canvas :
这是堆叠 2 个 Canvas 的 Html+CSS:
<div id="container">
<canvas id="background" class="subcanvs" width=300; height=300;></canvas>
<canvas id="canvas" class="subcanvs" width=300; height=300;></canvas>
</div>
#container{
position:relative;
border:1px solid blue;
width:300px;
height:300px;
}
.subcanvs{
position:absolute;
}
以下是使用星空图像在背景 Canvas 上创建平移星空的方法:
var fps = 60;
var offsetLeft=0;
panStars();
function panStars() {
// increase the left offset
offsetLeft+=1;
if(offsetLeft>backImage.width){ offsetLeft=0; }
// draw the starfield image and
// draw it again to fill the empty space on the right of the first image
bkCtx.clearRect(0,0,background.width,background.height);
bkCtx.drawImage(backImage,-offsetLeft,0);
bkCtx.drawImage(backImage,backImage.width-offsetLeft,0);
setTimeout(function() {
requestAnimationFrame(panStars);
}, 1000 / fps);
}
现在前面的 Canvas 用于所有游戏对象。
您的游戏高效且性能卓越,有 2 个 Canvas 各有用途。
这是代码和 fiddle :http://jsfiddle.net/m1erickson/5vfVb/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{padding:20px;}
#container{
position:relative;
border:1px solid blue;
width:300px;
height:300px;
}
.subcanvs{
position:absolute;
}
</style>
<script>
$(function(){
// Paul Irish's great RAF shim
window.requestAnimFrame = (function(callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var background=document.getElementById("background");
var bkCtx=background.getContext("2d");
// create an image of random stars
var backImage=RandomStarsImage();
// draw on the front canvas
ctx.beginPath();
ctx.fillStyle="red";
ctx.rect(75,100,100,50);
ctx.arc(175,125,25,0,Math.PI*2,false);
ctx.closePath();
ctx.fill();
// start panning the random stars image across the background canvas
var fps = 60;
var offsetLeft=0;
panStars();
function panStars() {
// increase the left offset
offsetLeft+=1;
if(offsetLeft>backImage.width){ offsetLeft=0; }
// draw the starfield image and draw it again
// to fill the empty space on the right of the first image
bkCtx.clearRect(0,0,background.width,background.height);
bkCtx.drawImage(backImage,-offsetLeft,0);
bkCtx.drawImage(backImage,backImage.width-offsetLeft,0);
setTimeout(function() {
requestAnimFrame(panStars);
}, 1000 / fps);
}
function RandomStarsImage(){
// draw a random starfield on the canvas
bkCtx.beginPath();
bkCtx.fillStyle="darkblue";
bkCtx.rect(0,0,background.width,background.height);
bkCtx.fill();
bkCtx.beginPath();
for(var n=0;n<100;n++){
var x=parseInt(Math.random()*canvas.width);
var y=parseInt(Math.random()*canvas.height);
var radius=Math.random()*3;
bkCtx.arc(x,y,radius,0,Math.PI*2,false);
bkCtx.closePath();
}
bkCtx.fillStyle="white";
bkCtx.fill();
// create an new image using the starfield canvas
var img=document.createElement("img");
img.src=background.toDataURL();
return(img);
}
}); // end $(function(){});
</script>
</head>
<body>
<div id="container">
<canvas id="background" class="subcanvs" width=300; height=300;></canvas>
<canvas id="canvas" class="subcanvs" width=300; height=300;></canvas>
</div>
</body>
</html>
关于javascript - Canvas :动画一个简单的星空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17171135/