2012-03-07 9 views
4

だから、HTML5を使ってミニクラフトのウェブサイトのテーマを作りたいと思います。私はHTML5/Javascriptで少し不安定です(しばらく使用していない)ので、助けが必要です。私は、画面に収まる16x16pxタイルの数を計算しようとしています。次に、画面の背景に対してランダムに「マップを生成する」。次に、同じ2つのforループを使用してマップを生成し、タイル(生成プロセス中にピクチャパスが割り当てられている)で画面を満たします。問題は、キャンバスが完全に白いことです。誰もが問題を選ぶことができる、と私に可能な限りのヒントを教えてください?前もって感謝します!ここに私のHTML5コードは次のとおりです。HTML5キャンバスでforループを使用して画像を描画しますか?

<!DOCTYPE html> 
<html> 
    <head> 
     <title>Minecraft Background Check</title> 
    </head> 
    <body> 
     <canvas id="bg" style="position:fixed; top:0; left:0; border:1px solid #c3c3c3; width: 100%; height: 100%;"></canvas> 
     <script type="text/javascript"> 
      "use strict"; 
      var c = document.getElementById("bg"); 
      var ctx = c.getContext("2d"); 
      ctx.canvas.width = window.innerWidth; 
      ctx.canvas.height = window.innerHeight; 

      var width = Math.ceil(window.innerWidth/16); 
      var height = Math.ceil(window.innerHeight/16); 

      for (var x=0;x<width;x++) 
      { 
       for(var y=0;y<height;y++) 
       { 
        var rand = Math.floor(Math.random()*11); 
        var texLoc = getImageNameFromRand(rand,y,height); 

        var img=new Image(); 
        img.onload = function(){ 
         return function() { 
          ctx.drawImage(img,x*16,y*16); 
         }; 
        }; 
        img.src=texLoc; 
       } 
      } 

      function getImageNameFromRand(rand,yVal,maxY) 
      { 
       var dirt = 'dirt.png'; 
       var stone = 'stone.png'; 
       var cobble = 'cobble.png'; 
       var mosscobble = 'mosscobble.png'; 
       var bedrock = 'bedrock.png'; 

       if(yVal===0) 
       { 
        return dirt; 
       } else if(yVal<3) 
       { 
        if(rand < 7) { 
         return dirt; } 
        else { 
         return stone; } 
       } else if(yVal<5) 
       { 
        if(rand < 4) { 
         return dirt; } 
        else { 
         return stone; } 
       } else if(yVal<maxY-2) 
       { 
        if(rand === 0) { 
         return dirt; } 
        else if(rand < 4) { 
         return cobble; } 
        else if(rand < 5) { 
         return mosscobble; } 
        else { 
         return stone; } 
       } else if(yVal<maxY-1) 
       { 
        if(rand < 4) { 
         return bedrock; } 
        else { 
         return stone; } 
       } else if(yVal<maxY) 
       { 
        if(rand < 7) { 
         return bedrock; } 
        else { 
         return stone; } 
       } else { 
        return bedrock; } 
       return bedrock; 
      } 
     </script> 
    </body> 
</html> 

答えて

2

ここには説明がたくさんあります。私は以下のコードをテストして動作させましたが、単純に1つのイメージを繰り返し使用しました。うまくいけば、これはあなたのコードとマージされたときに動作します。 forループの代わりに、コードを下に配置します(var heightの後で関数getImageNameFromRandの前に)。

まず、コードはグローバル名前空間内のすべての変数を定義しています。そのため、img変数はsrcとonload関数などと一緒に元のループを使用するたびに置き換えられます。さらに、forループをインクリメントするxとyは、onload関数でクロージャによって参照されますが、(onload関数ではなく)外側ループの間だけインクリメントされるため、両方ともonload呼び出し中に終了値に設定されます元のループが実行されたときの終了値)。

また、(function(){YOUR CODE HERE})()のような無名関数にすべてのスクリプトを入れてみてください。こうすることで、ローカル変数でグローバル名前空間に追加することはなく、onloadはクロージャのために必要なものを持ちます。私はすべてを無名関数に入れてテストし、それは私のために働いた。

うまくいけば、これをすべて正しくコピーして貼り付けました。オフの場合はコメントしてください。がんばろう!!!

//Copy this code in place of your original "for" loop: 

var imgs = []; 
var imgIndex = 0; 

for (var x = 0; x < width; x++){ 
    for(var y = 0; y < height; y++){ 
     var rand = Math.floor(Math.random() * 11); 
     var texLoc = getImageNameFromRand(rand, y, height); 

     imgs[imgIndex] = new Image(); 

     imgs[imgIndex].onload = (function() { 
      var thisX = x * 16; 
      var thisY = y * 16; 

      return function() { 
       ctx.drawImage(this, thisX, thisY); 
      }; 
     }()); 

     imgs[imgIndex].src = texLoc; 
     imgIndex += 1; 
    } 
} 
1

あなたは次のようにします。あなたはimg以上の閉鎖を作成しようとしている

img.onload = function(){ 
    return function() { 
     ctx.drawImage(img,x*16,y*16); 
    }; 
}; 

のでonloadハンドラの内部には、それはあなたのイメージを参照しますループの反復で作成されます。

しかし、あなたはそれをやっていません。代わりに、onloadハンドラは、無名関数を定義して何もしないだけです。あなたはすぐに匿名関数を呼び出し、imgに渡しているように、あなたはそれを変更した場合は、(forループコンテキストから)imgの上に閉じ、それはあなたがやりたいだろう

img.onload = function(img){ 
    return function() { 
     ctx.drawImage(img,x*16,y*16); 
    }; 
}(img); 

外部の匿名関数がすぐに呼び出されない場合は、画像のオンロードハンドラになります。そして何も起こりません。空白のキャンバスにつながります。

+1

ありがとうございますが、まだ空白のキャンバスを取得しています。他に何か間違っていますか?再度、感謝します。 – Flafla2

+0

キャンバスを見て、それが期待していたスペースを占めていることを確認しましたか?たとえば、 'width:100%'と 'height:100%'を省略し、代わりに 'right:0;ウィンドウ全体を伸ばします(これは 'position:fixed'で動作するはずです)。それ以外の場合は、100%の幅と高さを達成するために行う必要があります。 – Jeremy

0

問題は、あなたのforループで、の上に画像を重ねて描画しています。お互いにです。最初の実行(x = 0、y = 0)の後にforloopsから完全に脱出すると、ランダムなイメージのタイルが0,0の位置に表示されます。それがダブルforループ全体を通過すると、最後のイメージがキャンバスの下隅に描画され、あなたが見ている '白い白いキャンバス'が作成されます。ランダムタイルのキャンバスをあらかじめ塗りつぶしておく必要があります。これはまた、forループがonload()関数内にある必要があることを意味します。バックグラウンドは数百回/数千回ではなく一度だけ描画されるからです。

html5キャンバスパターン/タイルを探して、そこから作業します。

img.onload = function(){ 

    // - nested for loops 
    // -> generate a tile pattern to fit the entire canvas 

    // - ctx.drawImage() 

}; 

幸運:

また、あなたのonload関数を使用すると、このようなものとして、それを持つことができ、内部の機能を必要としません!

関連する問題