2012-04-06 7 views
1

저는 HTML5 (및 OO Javascript)를 배우는 과정에 있으며 간단한 게임 엔진을 만들려고 노력하고 있지만 캔버스에 렌더링하는 것은 매우 이상한 조건에서 작동합니다. Here 페이지에 대한 링크이며, 여기 내 index.html을이다 : 처음로드 할 때

HTML5 Canvas rendering oddly

<html> 
<head> 
    <script type="text/javascript"> 
     function load() 
     { 
      var game = new Game(); 
      game.start(); 
     } 
    </script> 
    <title>Game</title> 
    <style> 
     canvas 
     { 
      outline:0; 
      border:1px solid #000; 
      margin-left: auto; 
      margin-right: auto; 
     } 
    </style> 
</head> 
<body onload="load()"> 
    <canvas id='c'></canvas> 

    <script src="classes/Tuple.js"></script> 
    <script src="classes/Rect.js"></script> 
    <script src="classes/Sprite.js"></script> 
    <script src="classes/Game.js"></script> 
</body> 
</html> 



, 그것은 파이어 폭스 11.0에 NS_ERROR_DOM_TYPE_MISMATCH_ERR 예외와 형식 오류를 줄 것이다 Chrome 18.0의 예외 그것이 작동되도록하려면

파이어 폭스 11.0

  • 을 수동으로 주소 표시 줄에 URL을 선택하여 입력 또는
  • 가 새로 고침 버튼 또는
  • F5 키를 클릭했다. 크롬 18.0

    는 주소 표시 줄에 URL을 선택하고 수동으로 입력하거나

  • 가 새로 고침 버튼 또는
  • F5 키를 눌러 또는
  • 시프트 (Shift) 키를 누르면/Ctrl + F5를 클릭했다.

내가을 의심 무엇 - 그냥 추측하지만이의 .js 파일 중 하나 이상처럼 보인다는 첫 번째 페이지로드하는 동안 호출 될 때까지 준비/사용할 수 없습니다. Firebug에서 몇 번 밟아서 첫 페이지 요청시 스프라이트 이미지가로드되지 않는 것 같습니다.

Game()이 생성되고 캐시 된 다음 두 번째 페이지로드에서만 모든 .js 파일의 인스턴스가 다운로드 될 수 있습니다.

아이디어가 있으십니까? 고마워, 고마워!

+0

흠, 4 가지 중 첫 번째를 Game.js로 만들었지 만 동일한 동작을하고있는 것처럼 보입니다. (강제로 새로 고쳐서 캐시 된 복사본을 만들지 않습니다) –

답변

3

파일을 로컬로 복사하고 테스트를 수행했습니다. 사용할 수없는 자바 스크립트 파일이 아닌 것처럼 보입니다.하지만 스프라이트.

Game.start에 전화 할 때까지 PNG를로드하지 않습니다. 작업 할 때 :

roadSpritesheetImage.src = "assets/sprites/player/playerSpriteSheet.png"; 

이렇게하면 이미지를 비동기 적으로 다운로드하기 시작합니다. 나머지 코드는 이미지가 완전히로드되기 전에 실행되므로 이미지를 슬라이스 할 때 src 속성이 null 인 것처럼 슬라이스합니다.

이것이 새로 고침을 맞춰 모든 것이 정상적으로 작동하는 이유입니다 ... 이미지가 캐싱되었습니다.

당신은 종류의 단지 캔버스하기 전에 이미지 태그를 추가하여 스프라이트의로드를 선점 할 수 있습니다 몸로드 이벤트 (이미지 포함) 내용까지 해고되지 않기 때문에

<img src="assets/sprites/player/playerSpriteSheet.png" style="display:none;" /> 

이 작동 것입니다 완전히로드 (나는 이것을보아야 할 것이라고 생각한다). 그런 다음이 이미지를 img.src에 할당하면 캐시 된 이미지를 참조하게됩니다.

또는 게임 기능의 나머지 부분을 img.onload에 바인딩 할 수 있습니다. 예를 들면 다음과 같습니다.

self.loadSprites = function() 
{ 
    var roadSpritesheetImage = new Image();  
    roadSpritesheetImage.onload = function() { 
     self.entities.push(new Sprite("testTile", 
      roadSpritesheetImage, 
      new Tuple(16, 16), 
      new Rect(0, 0, 32, 16))); 
     self.run(); 
    }; 

    roadSpritesheetImage.src = "assets/sprites/player/playerSpriteSheet.png"; 
}; 

self.run = function() { 
    var drawSuccessful = false; 
    drawSuccessful = self.entities[0].draw(self.context); 
    self.entities[0].nextFrame(); 

    //if we managed to draw the Sprite successfully without any raised exceptions 
    if(drawSuccessful) { 
     setTimeout(self.run, 300); 
    } else { alert("stopping execution of the game."); } 
}; 

self.start = function() 
{ 
    self.loadSprites(); 
}; 

이 작업을 수행하는 것이 약간 깔끔하고 리소스와 경쟁 조건이 없음을 보장합니다.

소스 이미지에서 N-puzzle을 그리기 위해 만든 jQuery 플러그인과 비슷한 문제가 있습니다. this MDN documentation은 캔버스 대신 분할 된 div를 사용했지만 매우 유용했습니다.

+0

정말 고마워요! Chrome Timeline 기능에서 로딩 과정을 살펴본 후 동일한 문제가 의심스러워졌습니다. 그러나 나는 단지 새로운 Image() 객체를 선언 할 때, 계속 진행할 때까지 이미지가로드 될 때까지 기다릴 것이라고 생각했습니다. 나는 그것이 사실이 아니라는 것을 알았습니다. 이것은 새로운 계정이므로 귀하의 게시물을 upvote 할만큼 충분한 평판을 얻지 못했지만 그렇게 할 때 나는 그렇게 할 것입니다. 다시 한 번 고마워, 너는 나를 혼란스럽게 만들었다. –

+1

@AlexAlksne, 답으로 표시 할 수 있습니다. 이제 2 + sprites를로드 할 때 고려해야 할 사항입니다.'self.run()'은 모든 것이로드 될 때까지 호출해서는 안됩니다. – Alexander

+0

@AlexAlksne 문제가 없습니다. 이와 같은 경우 로딩 시간을 잡는 것이 어려울 수 있습니다 ... 특히 스프라이트가 4K 인 경우. –