2012-04-06 1 views
1

Je suis en train d'apprendre HTML5 (et OO Javascript) et j'essaie de faire un moteur de jeu simple mais le rendu sur toile fonctionne dans des conditions très étranges. Here est un lien vers la page et voici mon index.html:

HTML5 Toile de rendu bizarrement

<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> 



lors du premier chargement, il donnera un NS_ERROR_DOM_TYPE_MISMATCH_ERR Exception dans Firefox 11.0 et un TypeError Exception dans Chrome 18.0. Pour le faire fonctionner:

Firefox 11,0

  • sélectionnez l'URL dans la barre d'adresse et appuyez sur Entrée manuelle OU
  • cliquez sur le bouton Actualiser
  • appuyez sur F5.

Chrome 18,0

  • sélectionnez l'URL dans la barre d'adresse et cliquez manuellement sur Entrée ou
  • cliquez sur le bouton Actualiser
  • Appuyez sur F5 ou
  • appuyez sur Maj/Ctrl + F5.

Ce que je soupçonne - Juste une supposition, mais il semble que l'un ou plusieurs des fichiers .js ne sont pas disponibles/prêt au moment où il est appelé lors de la première charge de page. Après l'avoir traversé plusieurs fois dans Firebug, il semble que les images des sprites ne soient jamais chargées sur la première page.

Peut-être certains des fichiers .js sont-ils toujours en cours de téléchargement lorsque l'instanciation à Game() est en cours, puis mise en cache, et sont uniquement disponibles lors du chargement de la deuxième page?

Des idées? Je vous serais reconnaissant de votre compréhension, merci!

+0

Hmm, j'ai fait de Game.js le premier des quatre inclus mais je semble avoir le même comportement (je force rafraîchi donc je ne sors pas d'une copie cachée) –

Répondre

3

J'ai copié vos fichiers localement et j'ai effectué quelques tests. Il me semble que ce ne sont pas vos fichiers JavaScript qui sont indisponibles, mais votre sprite.

Vous ne chargez pas le fichier PNG avant d'appeler le Game.start. Quand vous faites:

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

Cela commence un téléchargement asynchrone de l'image. Le reste du code est exécuté avant le chargement complet de l'image. Lorsque vous découpez l'image, vous la découpez comme si l'attribut src était nul.

C'est la raison pour laquelle vous pouvez cliquer sur Rafraîchir et tout fonctionne comme prévu ... l'image est mise en cache.

Vous pouvez préempter en quelque sorte le chargement de l'image-objet en ajoutant une balise d'image juste avant la toile:

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

Cela pourrait fonctionner car l'événement de charge du corps ne se déclenche pas tant que le contenu (y compris les images) est complètement chargé (je crois, je devrais chercher ceci). Ensuite, si vous affectez cette image à img.src, vous référencerez l'image mise en cache.

Vous pouvez également lier le reste des fonctionnalités du jeu à img.onload. Par exemple:

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(); 
}; 

Faire cela est un peu plus propre et il garantir que vous n'avez pas des conditions de course avec vos ressources.

J'ai eu un problème similaire avec un plugin jQuery que j'ai créé pour dessiner un N-puzzle à partir d'une image source. J'ai trouvé this MDN documentation extrêmement utile à l'époque, bien que j'ai fini par utiliser div divisés au lieu d'une toile.

+0

C'est super merci! Après avoir regardé le processus de chargement dans la fonction Chrome Chronologie, je commençais à suspecter la même chose. Cependant, je supposais simplement que lorsque vous déclarez un nouvel objet Image(), il attend juste que l'image soit chargée jusqu'à ce que cela se produise. Je vois maintenant que ce n'est pas le cas. Ceci est un nouveau compte donc je n'ai pas assez de réputation pour upvote votre message mais quand je le ferai, je le ferai. Merci encore, vous m'avez sauvé des heures de confusion! –

+1

@AlexAlksne, vous pouvez le marquer comme une réponse. Maintenant, vous devez prendre en compte lors du chargement de 2 + sprites, 'self.run()' ne devrait pas être appel jusqu'à ce que tous les sprites sont chargés. – Alexander

+0

@AlexAlksne pas de problème. Dans un cas comme celui-ci, il peut être difficile d'attraper les temps de chargement ... surtout quand votre sprite est seulement 4K. –