如何一次性更新 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();
}
我目前正在使用 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();
}