如何一次性更新 canvas?和沙堆的效率

How do I update the canvas all at once? And efficiency in sandpiles

我目前正在使用 javascript 和 "sandpiles" 的 p5.js 库编写代码。沙堆是离散二维space中的数学结构,其中"sand",一个整数放在一个点上,并将"topple"到相邻的单元格上。我对编码比较陌生,所以我不知道最有效的方法。

目前我正在使用一个二维数组,我通过创建一个全局沙堆数组创建了一个二维数组,并在我的设置函数中使该数组中的每个元素成为它自己的数组,允许我有一个 x 和 y 索引覆盖 canvas。

当我去显示每个像素的值("amount of sand")时,我的问题就来了——每个像素都被单独查看,并根据它的值被某种颜色的 "point" 替换

function update() {

for (var x = 0; x < width; x++) {
    for (var y = 0; y < height; y++) {
        if (sandpiles[x][y] == int(0)) {
            stroke(255, 255, 0);
        } else if(sandpiles[x][y] == 1) {
            stroke(0, 185, 63);
        } else if(sandpiles[x][y] == 2) {
            stroke(0, 104, 255);
        } else if(sandpiles[x][y] == 3) {
            stroke(122, 0, 229);
        } else {
            stroke(255, 0, 0);
        }
        point(x, y);
    }
}

沙堆作为一种结构具有非常好的对称性,我想知道是否可以在绘制像素时停止屏幕,以便可以立即看到每个 "state" 调用而不是单个像素。另外,我知道 javascript 本身可能有一种方法可以更好地工作,所以如果有人可以指导我使用 js 以更优雅的方式处理每个像素的功能,我会非常乐意欣赏它。另外,由于我在 canvas 的每次绘制中检查每个像素两次(一次翻倒,一次更新),有没有办法让搜索更有效率,或者我会必须包括特定的搜索算法?谢谢。

编辑: 下面是整个代码 - 我删除了一些可选参数,这样更容易阅读,我希望我做对了。

total_sand = 10000;
sandpiles = [];
var next_sandpiles;

function setup() {
    createCanvas(301, 301);
    for (var x = 0; x < width; x++) {
        sandpiles[x] = [];
        for (var y = 0; y < height; y++) {
            sandpiles[x][y] = 0;
        }
    }
    next_sandpiles = sandpiles;

    //STARTING CONDITIONS
    if (width % 2 == 0) {
        sandpiles[width/2][height/2] = total_sand;
    } else {
        sandpiles[(width-1)/2][(height-1)/2] = total_sand;
    }


}

function topple() {

    for (var x = 0; x < width; x++) {
        for (var y = 0; y < height; y++) {
            if (sandpiles[x][y] > 3) {

                next_sandpiles[x][y] = next_sandpiles[x][y] - 4;
                if (x > 0) {
                    next_sandpiles[x-1][y]++;
                }
                if (x < width - 1) {
                    next_sandpiles[x+1][y]++;
                }
                if (y > 0) {
                    next_sandpiles[x][y-1]++;
                }
                if (y < height - 1) {
                    next_sandpiles[x][y+1]++;
                }
            }
        }
    }

    sandpiles = next_sandpiles;
}

function update() {

    for (var x = 0; x < width; x++) {
        for (var y = 0; y < height; y++) {
            if (sandpiles[x][y] == int(0)) {
                stroke(255, 255, 0); // colour 0
            } else if(sandpiles[x][y] == 1) {
                stroke(0, 185, 63); // colour 1
            } else if(sandpiles[x][y] == 2) {
                stroke(0, 104, 255); // colour 2
            } else if(sandpiles[x][y] == 3) {
                stroke(122, 0, 229); // colour 3
            } else {
                stroke(255, 0, 0); // colour 4
            }
            point(x, y);
        }
    }

}

function draw() {

    // while (toppling) {
    //  topple();
    // }

    topple();

    update();

    // noLoop();    

}

您应该将 loadPixels()updatePixels()pixels 数组一起使用:

function update() {

loadPixels();
var r;
var g;
var b;

for (var x = 0; x < width; x++) {
    for (var y = 0; y < height; y++) {
        if (sandpiles[x][y] == int(0)) {
            r = 255;
            g = 255;
            b = 0;
        } else if(sandpiles[x][y] == 1) {
            r = 0;
            g = 185;
            b = 63;
        } // add as many colors as you please
        var index = (x + y * width)*4;
        pixels[index] = r;
        pixels[index+1] = g;
        pixels[index+2] = b;
        pixels[index+3] = 255; // alpha
    }
}

updatePixels();
}