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

当前的结果是三个绘制的瓦片,都在 x = 300 的位置(相当于 10 的 i 循环 * 30 的 tileSize)和一个随机的 y 位置。

在通过创建变量 drawCanvasImage 来解决(也许?)关闭问题之后,我至少得到了这三个图块来绘制。

----编辑---- 工作代码 - 修订版 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

这是因为每次执行循环时,都会为 [image].onload 分配一个新函数,从而覆盖之前的函数。这就是你最终只有三个图像的方式。这应该有效:

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 回答
1

您正在onload每次迭代中重写三个图像的 s 。因此,它只会执行最后添加的onloadf 或每个图像。

建议:仅在加载 thred 后运行您的绘图方法(并且他们只是在drawCanvasImage没有 的情况下调用每次迭代.onload=

更好的是:将随机数存储在一个数组中,让每个图像在加载时独立地遍历数组,并在适用的地方仅添加其自身的副本。

修订版 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);
        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 回答