HTML5 Canvas游戏,多层问题

时间:2015-05-23 03:59:14

标签: javascript html5 canvas

我正在创建我的第一个HTML5游戏之一。这是一种类似战争部/传说战争的游戏。这是一款基于等距瓦片的MMORTS游戏。现在,在我构建游戏的过程中,我正在努力保持资源管理和速度;但是,我遇到了一个问题。

我有一个名为renderMap的方法,遵循这些步骤

  1. renderMap加载当前地图块。地图块目前被定义为6x6网格块。
  2. renderMap循环遍历每个单独的图块,从ASCENDING X,Y到DESCENDING X,Y,并将该图块绘制到等距网格上。在将瓷砖绘制到屏幕的同时,它还会检查该瓷砖是否在建筑物上,并将该建筑物绘制在瓷砖顶部。
  3. 现在,因为renderMap必须为作为块的一部分的每个单独的tile调用drawImage约36次,所以如果每次调用该函数,它真的开始变成资源耗尽帧。所以,我对内存中的画布进行了renderMap绘制,每画面都会绘制到主画布上。因此,drawImage的36次调用每帧只减少1次。

    我唯一需要拨打renderMap的是,无论如何瓷砖或建筑物都会更新。例如,如果加载了一个新块,我们需要加载新的等距映射。

    但是,如果我希望这些建筑物或瓷砖有动画怎么办?

    例如,我在游戏中添加了一个名为oil well的建筑物。如果油井位于6x6块中装载在玩家客户端并显示的任何牌上,它将迫使游戏必须多次调用renderMap,以便渲染单个建筑物新图像(因为动画)。所以我最终只渲染了35块额外的瓷砖,以便更新那栋1楼。

    我该怎么办?最好包含动画吗?

    这是游戏的样子,所以这对于为问题添加上下文可能会有所帮助:

    (抱歉图片混乱......我正在做一些测试)

    image of game

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;
&#13;
&#13;