我使用canvas
创建了一个星空,它按预期工作:
<!DOCTYPE HTML5>
<html>
<head>
<title>StarField</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
width: 100%;
height: 100%;
}
</style>
</head>
<body onLoad="startGame()"></body>
<script type="text/javascript">
var NO_OF_STARS = 512;
var stars = [];
function startGame() {
gameArea.start(); /* Makes the canvas */
gameRun = requestAnimationFrame(gameArea.update); /* Starts the game and coordinates all the animations */
window.addEventListener("keydown", function(e) {
if(e.keyCode == 27) { /* ESC stops everything */
stopEverything();
}
});
}
var gameArea = {
canvas : document.createElement("canvas"),
start : function() {
document.body.appendChild(this.canvas);
this.canvas.width = document.body.clientWidth;
this.canvas.height = document.body.clientHeight;
},
update : function() {
gameArea.clear(); /* Fills the canvas with #000000 */
gameArea.drawStars(); /* Draws the stars */
gameRun = requestAnimationFrame(gameArea.update); /* Repeat the whole thing */
},
drawStars : function() {
var ctx = gameArea.canvas.getContext("2d");
if(stars.length == 0) {
for(var i = 0; i < NO_OF_STARS; i++) {
var opacity = ((Math.floor(Math.random() * 10) / 10) + .1);
stars.push([getRandomInt(0, gameArea.canvas.width - 1), getRandomInt(0, gameArea.canvas.height - 1),opacity]);
ctx.beginPath();
ctx.strokeStyle = "rgba(255, 255, 255, " + opacity + ")";
ctx.moveTo(stars[i][0], stars[i][1]);
ctx.lineTo(stars[i][0] + 1, stars[i][1] + 1);
ctx.stroke();
}
} else {
for(var i = 0; i < NO_OF_STARS; i++) {
ctx.strokeStyle = "rgba(255, 255, 255, " + stars[i][2] + ")";
stars[i][0] -= ((stars[i][2] == 1.0) ? 5 :
(stars[i][2] >= 0.8) ? 4 :
(stars[i][2] >= 0.5) ? 3 :
(stars[i][2] >= 0.3) ? 2 :
1);
if(stars[i][0] < 0) {
var opacity = ((Math.floor(Math.random() * 10) / 10) + .1);
stars.splice(i, 1, [gameArea.canvas.width, getRandomInt(0, gameArea.canvas.height - 1), opacity]);
}
ctx.beginPath();
ctx.moveTo(stars[i][0], stars[i][1]);
ctx.lineTo(stars[i][0] + 1, stars[i][1] + 1);
ctx.stroke();
}
}
},
clear : function() {
var ctx = this.canvas.getContext("2d");
ctx.fillStyle = "#000000";
ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
}
};
/**
* Returns a random integer between min (inclusive) and max (inclusive)
*/
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function stopEverything() {
cancelAnimationFrame(gameRun);
}
</script>
</html>
问题在于它需要占用大量CPU (在配备AMD A8四核处理器的笔记本电脑上占60%到65%)。我希望这个canvas程序也可以在其他具有低端处理器的计算机上运行。
我尝试过减少NO_OF_STARS
,但这并没有改变CPU使用率。然而,当增加它时,动画会大大减慢并且CPU使用率会降低(我不会认为我会增加它,所以这并不是真的相关)
我还注意到画布的大小在CPU使用中起着重要作用。 (我上面提到的笔记本电脑的分辨率为1366x768)但我希望画布能够拍摄完整的视口。
那么,如何降低CPU使用率?
答案 0 :(得分:2)
为每个星定义路径,描边样式并对其进行栅格化非常昂贵。尝试收集一些操作来减轻负担 - 这都是为了妥协:
我个人会硬编码不透明度级别,但我将调整后的代码留下了随机生成(按下运行按钮几次)。
通常你会在CPU / GPU上受到一些打击,但这些提示应该可以提高性能(或者在这种情况下可以降低负载)。
var NO_OF_STARS = 500; // divisable by 5 (due to num. of opacities - see below)
var stars = [];
function startGame() {
gameArea.start(); /* Makes the canvas */
gameRun = requestAnimationFrame(gameArea.update); /* Starts the game and coordinates all the animations */
window.addEventListener("keydown", function(e) {
if (e.keyCode == 27) { /* ESC stops everything */
stopEverything();
}
});
}
var gameArea = {
canvas: document.createElement("canvas"),
ctx: null,
opacities: [],
start: function() {
document.body.appendChild(this.canvas);
this.canvas.width = document.body.clientWidth;
this.canvas.height = document.body.clientHeight;
// store context once
this.ctx = this.canvas.getContext("2d");
// opacity levels
for (var t = 0; t < 5; t++) this.opacities.push(((Math.floor(Math.random() * 10) / 10) + .1));
},
update: function() {
gameArea.clear(); /* Fills the canvas with #000000 */
gameArea.drawStars(); /* Draws the stars */
gameRun = requestAnimationFrame(gameArea.update); /* Repeat the whole thing */
},
drawStars: function() {
var ctx = this.ctx;
if (!stars.length) {
for (var i = 0; i < NO_OF_STARS; i++) {
stars.push({
x: getRandomInt(0, gameArea.canvas.width - 1)|0,
y: getRandomInt(0, gameArea.canvas.height - 1)|0
});
}
}
for (t = 0, pos = 0; t < 5; t++) {
var opacity = this.opacities[t];
ctx.beginPath();
for (var i = 0; i < NO_OF_STARS / 5; i++) {
stars[pos].x -= opacity * opacity * 4;
if (stars[pos].x < 0) {
stars[pos].x = gameArea.canvas.width;
stars[pos].y = getRandomInt(0, gameArea.canvas.height - 1)|0;
}
ctx.rect(stars[pos].x, stars[pos].y, 1, 1);
pos++; // total position
}
ctx.strokeStyle = "rgba(255, 255, 255, " + opacity + ")";
ctx.stroke();
}
},
clear: function() {
var ctx = this.canvas.getContext("2d");
ctx.fillStyle = "#000000";
ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
}
};
/**
* Returns a random integer between min (inclusive) and max (inclusive)
*/
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function stopEverything() {
cancelAnimationFrame(gameRun);
}
startGame();
&#13;
* {
margin: 0;
padding: 0;
}
body {
width: 100%;
height: 100%;
}
&#13;