我正在创建我的第一个HTML5游戏之一。这是一种类似战争部/传说战争的游戏。这是一款基于等距瓦片的MMORTS游戏。现在,在我构建游戏的过程中,我正在努力保持资源管理和速度;但是,我遇到了一个问题。
我有一个名为renderMap
的方法,遵循这些步骤
renderMap
加载当前地图块。地图块目前被定义为6x6网格块。renderMap
循环遍历每个单独的图块,从ASCENDING X,Y到DESCENDING X,Y,并将该图块绘制到等距网格上。在将瓷砖绘制到屏幕的同时,它还会检查该瓷砖是否在建筑物上,并将该建筑物绘制在瓷砖顶部。现在,因为renderMap
必须为作为块的一部分的每个单独的tile调用drawImage
约36次,所以如果每次调用该函数,它真的开始变成资源耗尽帧。所以,我对内存中的画布进行了renderMap
绘制,每画面都会绘制到主画布上。因此,drawImage
的36次调用每帧只减少1次。
我唯一需要拨打renderMap
的是,无论如何瓷砖或建筑物都会更新。例如,如果加载了一个新块,我们需要加载新的等距映射。
但是,如果我希望这些建筑物或瓷砖有动画怎么办?
例如,我在游戏中添加了一个名为oil well
的建筑物。如果油井位于6x6块中装载在玩家客户端并显示的任何牌上,它将迫使游戏必须多次调用renderMap
,以便渲染单个建筑物新图像(因为动画)。所以我最终只渲染了35块额外的瓷砖,以便更新那栋1楼。
我该怎么办?最好不包含动画吗?
这是游戏的样子,所以这对于为问题添加上下文可能会有所帮助:
(抱歉图片混乱......我正在做一些测试)
答案 0 :(得分:1)
创建一个spritesheet,其中包含动画油井所需的所有图像"瓦。
然后你可以从精灵表中拉出精灵,并将渲染后的地图覆盖在单个油井瓷砖上。
然后您将渲染一次大地图。您只需多次渲染该图块(比重新渲染整个地图仅为一个图块设置动画更有效)。您可以使用第二个叠加的画布以获得最佳性能。你甚至可以做一个覆盖的画布,它只是一个精灵的大小,并使用CSS定位将其移动到目标图块上。
示例代码和演示:
var canvasT=document.getElementById("canvasTop");
var ctx=canvasT.getContext("2d");
var canvasB=document.getElementById("canvasBottom");
var ctxB=canvasB.getContext("2d");
var cw,ch;
var nextTime=0;
var duration=1000/60*3;
//
var spritesheetWidth=256;
var spritesheetHeight=256;
var spriteCols=4;
var spriteRows=4;
var spriteCount=spriteRows*spriteCols;
var spritePosition=0;
var spriteWidth=spritesheetWidth/spriteCols;
var spriteHeight=spritesheetHeight/spriteRows;
var fireX=265;
var fireY=100;
//
var imgCount=2;
var fire=new Image();
fire.onload=start;
fire.src='https://dl.dropboxusercontent.com/u/139992952/stackoverflow/explodeSprite.png'
var map=new Image();
map.onload=start;
map.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/isometric1.png";
function start(){
if(--imgCount>0){return;}
cw=canvasB.width=canvasT.width=map.width;
ch=canvasB.height=canvasT.height=map.height;
canvasB.width=map.width;
canvasB.height=map.height;
ctxB.drawImage(map,0,0);
animate();
}
function animate(time) {
if(time<nextTime){requestAnimationFrame(animate);return;}
nextTime=time+duration;
var row=parseInt(spritePosition/spriteCols);
var col=spritePosition-row*spriteCols;
var spX=col*spriteWidth;
var spY=row*spriteHeight;
// Drawing code goes here
ctx.clearRect(0,0,cw,ch);
ctx.drawImage(fire,
spX,spY,spriteWidth,spriteHeight,
fireX,fireY,spriteWidth,spriteHeight);
spritePosition++;
if(spritePosition>spriteCount-1){
spritePosition=0;
}
requestAnimationFrame(animate);
}
&#13;
body{ background-color: ivory; }
#wrapper{
position:relative;
width:1095px;
height:655px;
}
#canvasTop,#canvasBottom{
position:absolute; top:0px; left:0px;
border:1px solid green;
width:100%;
height:100%;
}
#canvasTop{
border:1px solid red;
}
&#13;
<div id="wrapper">
<canvas id="canvasBottom"></canvas>
<canvas id="canvasTop"></canvas>
</div>
&#13;