1

各正方形にランダムな画像が割り当てられたグリッドを描画しようとしています。描画シーケンスに問題があり、Javascript 変数の閉鎖の問題が発生する可能性があります。どんな助けでも大歓迎です。

var tileSize = 30;
var drawCanvasImage = function(ctx,tile,x,y) {
return function() {
    ctx.drawImage(tile,x,y);
    console.log("x = " + x + "/ y = " + y);
}
}

function textures(ctx) {
var grass = new Image();
var sea = new Image();
var woods = new Image();
for (var i=0; i<=10; i++) {
    for (var j=0; j<=20; j++) {
        rand = Math.floor(Math.random()*3 + 1);
        x = i * tileSize;
        y = j * tileSize;
        if (rand == 1) {
            grass.onload = drawCanvasImage(ctx,grass,x,y);
        } else if (rand == 2) {
            sea.onload = drawCanvasImage(ctx,sea,x,y);
        } else {
            woods.onload = drawCanvasImage(ctx,woods,x,y);
        }
    }
}
grass.src = "textures/grass.png";
sea.src = "textures/sea.png";
woods.src = "textures/woods.png";
}

//function called by the onload event in the html body tag
function draw() {
var ctx = document.getElementById("grid").getContext('2d');
grid(ctx);  //a function to draw the background grid - works fine
textures(ctx);
}

現在の結果は 3 つの描画されたタイルで、すべて x = 300 の位置 (10 の i ループ * 30 の tileSize に相当) とランダムな y 位置にあります。

先導に従い、変数 drawCanvasImage を作成して (おそらく?) 閉鎖の問題を説明した後、少なくともこれら 3 つのタイルを描画することができました。

----編集---- 作業コード - リビジョン 2:

function randomArray() {
for (var i=0; i<=(xValue/tileSize); i++) {
    terrainArray[i] = [];
    for (var j=0; j<=(yValue/tileSize); j++) {
        rand = Math.floor(Math.random()*4 + 1);
        if (rand == 1) {
            terrainArray[i][j] = 3;
        } else if (rand == 2) {
            terrainArray[i][j] = 2;
        } else if (rand == 3) {
            terrainArray[i][j] = 1;
        } else {
            terrainArray[i][j] = 0;
        }
    }
}
}

var drawTerrain = function(ctx,tile,landUseValue) {
return function() {
    for (var i=0; i<=(xValue/tileSize); i++) {
        for (var j=0; j<=(yValue/tileSize); j++) {
            if (terrainArray[i][j] == landUseValue) {
                ctx.drawImage(tile,i*tileSize,j*tileSize);
            }
        }
    }
}
}

function textures(ctx) {
var grass = new Image();
var sea = new Image();
var woods = new Image();
var desert = new Image();
grass.onload = drawTerrain(ctx,grass,3);
sea.onload = drawTerrain(ctx,sea,0);
woods.onload = drawTerrain(ctx,woods,2);
desert.onload = drawTerrain(ctx,desert,1);
grass.src = "textures/grass.png";
sea.src = "textures/sea.png";
woods.src = "textures/woods.png";
desert.src = "textures/desert.png";
}
4

2 に答える 2

1

onloadすべての反復で3つの画像のを書き直しています。したがって、最後に追加されたonloadfまたはすべてのイメージのみが実行されます。

提案:thredがロードされた後にのみ描画メソッドを実行します(そして、それらは、drawCanvasImageなしですべての反復を呼び出すだけです.onload=

さらに良い方法:ランダムを配列に保存し、各画像がロード時に配列を独立してウォークスルーし、該当する場合はそれ自体のコピーのみを追加します。

rev2の改善

function randomArray() {
for (var i=0; i<=(xValue/tileSize); i++) {
    terrainArray[i] = [];
    for (var j=0; j<=(yValue/tileSize); j++) {
        rand = Math.floor(Math.random()*4 + 1);
        terrainArray[i][j] = 4-rand; 
        //OR: replace above two lines with terrainArray[i][j]=Math.floor(Math.random()*4 + 1);. There's no need to have them in exactly reverse order.
    }
}
}

var drawTerrain = function(ctx,tile,landUseValue) {
return function() {
    for (var i=0; i<=(xValue/tileSize); i++) {
        for (var j=0; j<=(yValue/tileSize); j++) {
            if (terrainArray[i][j] == landUseValue) {
                ctx.drawImage(tile,i*tileSize,j*tileSize);
            }
        }
    }
}
}

function textures(ctx) {
var grass = new Image();
var sea = new Image();
var woods = new Image();
var desert = new Image();
grass.onload = drawTerrain(ctx,grass,3);
sea.onload = drawTerrain(ctx,sea,0);
woods.onload = drawTerrain(ctx,woods,2);
desert.onload = drawTerrain(ctx,desert,1);
grass.src = "textures/grass.png";
sea.src = "textures/sea.png";
woods.src = "textures/woods.png";
desert.src = "textures/desert.png";
}

さらに柔軟にするために配列を使用して画像を保存してから、を使用できますlength。このように、別の画像を追加する場合は、配列を変更するだけです。

var srcArray=["textures/grass.png","textures/sea.png","textures/woods.png","textures/desert.png"];
var imgArray=[];
var terrainArray=[];
function textures(ctx){
randomArray();
    for(var i=0;i<srcArray.length;i++){
        imgArray[i]=new Image();
        imgArray[i].src=srcArray[i];
        imgArray[i].onload=drawTerrain(ctx,i);
    }
}
function randomArray() {
for (var i=0; i<=(xValue/tileSize); i++) {
    terrainArray[i] = [];
    for (var j=0; j<=(yValue/tileSize); j++) {
        terrainArray[i][j]=Math.floor(Math.random()*srcArray.length);

    }
}
}

var drawTerrain = function(ctx,index) {
return function() {
    for (var i=0; i<=(xValue/tileSize); i++) {
        for (var j=0; j<=(yValue/tileSize); j++) {
            if (terrainArray[i][j] == index) {
                ctx.drawImage(imgArray[index],i*tileSize,j*tileSize);
            }
        }
    }
}
}

だから今、あなたがしなければならないのはあなたがterrain(ctx)すべての画像をロードしたいときに呼び出すことだけです。また、画像のリストに画像を追加する場合は、それを一番上の配列に追加するだけです深く掘り下げてランダムな値などを変更する必要はありません。

于 2012-04-22T18:06:46.580 に答える
1

これは、ループを実行するたびに [image].onload に新しい関数を割り当てて、前の関数を上書きするためです。このようにして、3 つの画像のみが作成されます。これはうまくいくはずです:

if (rand == 1) {
    grass.addEventlistener('load', drawCanvasImage(ctx,grass,x,y), false);
} else if (rand == 2) {
    sea.addEventlistener('load', drawCanvasImage(ctx,sea,x,y), false);
} else {
    woods.addEventlistener('load', drawCanvasImage(ctx,woods,x,y), false);
}

ここでは、ループごとに新しいリスナーを追加するだけです。

于 2012-04-22T18:01:02.937 に答える