2012-01-03 3 views
3

나는 등각 타일 게임 엔진을 작성하려고하고이 코드의 속도로 문제가 : 나는 낮은 번호 Location.width 및 Location.height을 설정하면캔버스에서 타일 그리기의 속도를 높이려면 어떻게해야합니까?

$(function() { 

var canvas = document.getElementById('GameCanvas'); 
var context = document.getElementById('GameCanvas').getContext('2d'); 

var imgObj = new Image(); 
imgObj.src = 'img/sand_surface.png'; 

var Game = { 

    tileScaleX: 64, 
    tileScaleY: 32, 
    FPSLimit: 50, // max allowed framerate 
    realFPS: 0, // real framerate 

    init: function() { 


     this.cycle(); // main animation loop 
    }, 

    cycle: function() { 

     this.debug(); // print framerate 

     startTime = new Date; // start fps time 

     this.clear(); // celar canvas  
     this.draw(); // draw frame 

     endTime = new Date; // end fps time 

     setTimeout(function() { 
      endTimeWithSleep = new Date; // end fps time with sleep 
      this.realFPS = 1000/(endTimeWithSleep - startTime); 
      this.cycle(); // repeat animation loop 
     }.bind(this), (1000/this.FPSLimit) - (endTime - startTime)); 
    }, 

    debug: function() { 

     $('.DebugScreen').html('<b>FPS:</b> ' + Math.round(this.realFPS*1)/1); 
    }, 

    clear: function() { 

     canvas.width = canvas.width; // clear canvas 
    }, 

    draw: function() { 

     Location.drawSurface(); // draw tiles 
    }, 

} 

var Location = { 

    width: 60, 
    height: 120, 

    drawSurface: function() { 

     for (y = 0; y < this.height; y++) { 

      for (x = 0; x < this.width; x++) { 

       if ((y % 2) == 0) { 
        rowLeftPadding = 0; 
       } else { 
        rowLeftPadding = Game.tileScaleX/2; 
       } 

       context.drawImage(imgObj, (x * Game.tileScaleX + rowLeftPadding), y * (Game.tileScaleY/2), Game.tileScaleX, Game.tileScaleY); 
      } 
     } 
    }, 
} 

Game.init(); // start game 
}); 

는, 다음 빠르게 (초당 50 프레임)을 실행하지만, 이 예 (Location.width = 60, Location.height = 120)의 프레임 속도는 10fps이고 50fps가 필요합니다.이 스크립트의 속도를 높이는 방법에 대해 의구심이 있습니까?

+1

호기심에서, 여기서 곱셈과 나눗셈이 성취하는 것 :'Math.round (this.realFPS * 1)/1'? –

답변

5

1) 볼 수없는 경우에도 모든 타일을 그려 놓은 것처럼 보입니다. "클리핑 (clipping)"을 사용하십시오. context.drawImage()을 호출하기 전에 타일이 보이는지 계산해야합니다.

2) 풍경이 정적 인 경우 가능한 한 많이 계산하십시오. 그러나 거대한 이미지를 만드는 것도 좋은 아이디어는 아닙니다. 큰 덩어리 (예 : 512x512)를 미리 계산하는 것이 좋습니다.

3) 어떤 브라우저에서는 'setTimeout()'대신 requestAnimationFrame (나는 또한 this article이 상당히 흥미 롭다)을 사용하면 더 나은 프레임 속도를 얻을 수 있다고합니다.

4) 크기 조정/비율 조정은 성능에 영향을 줄 수 있습니다 (특히 이전 브라우저 또는 하드웨어의 경우). 타일이 이미 32x64 인 경우 3 개의 매개 변수로 drawImage()를 사용하여 크기 조정을 피할 수 있습니다 (확대/축소 효과를 얻기 위해 크기를 조절해야하는 경우에는 적용 할 수 없음).

+0

+1, 특히 볼 수없는 타일을 그리지 않고 가능하면 크기를 조정하지 않는 부분의 경우 –

+1

참고로 볼 수없는 타일은 그리지 않습니다. 클리핑은 여전히 ​​좋은 제안이며,이를 지적하고 싶습니다. – Loktar

0

내 편에서 코드를 엉망으로 만든 후 게시 한 코드가 45-50 사이에 있습니다. 한 가지 제안은 jQuery를 사용하지 않고 fps를 표시하는 요소의 html을 수정하지 않는 것입니다. 또한 데모를 최대 100 프레임으로 수정하고 약 70fps로 만들었습니다.

크기 조정 된 이미지를 캐싱하고 대신 성능을 향상시킬 수도 있습니다. 아래의 데모에서는 임시 캔버스에 크기가 조정 된 이미지를 캐시하고 대신 사용합니다.

Live Demo (I 이미지에 대한 onload을 구현 같은 느낌 didnt는, 그래서 그 경우 흰색 화면이 그냥 다시 실행 충돌) @jjmontes 우수한 답변을뿐만 아니라

0

, 당신은 또한 여러 캔버스 요소를 사용한다 귀하의 게임은 변경된 캔버스 부분 만 업데이트합니다. 지금은 매번 모든 것을 지우고 다시 그립니다.

관련 문제