Chapter 90

侵略シミュレーション

miku
miku
2021.11.19に更新
このチャプターの目次

実行結果

解説

マップ画像を用意して配列に読み込む。

一時用配列[i] = マップ配列[iの上下左右にあるインデックスのどれか];

マップ配列のすべてのピクセルを走査し、自身のピクセルの上下左右にあるピクセルのどれかを自身としてセットする。

この際、下記の注意点がある。

  • 上下左右ランダムに選んだピクセルが壁や空白ならコピーしない
  • 上書き先は別に用意した配列にする。

コード例

const cellSize = 10;
const cellWall = "#000000ff";
const cellNone = "#00000000";
const dirs = [
  { x: 1, y: 0 },
  { x: 0, y: 1 },
  { x: -1, y: 0 },
  { x: 0, y: -1 },
];
let board;
let mapImage;
let cellWidth;
let cellHeight;

function preload() {
  mapImage = loadImage("0.png");
}

function setup() {
  createCanvas(windowWidth, windowHeight);

  mapImage.loadPixels();
  cellWidth = mapImage.width;
  cellHeight = mapImage.height;
  board = [];
  for (let i = 0; i < cellWidth * cellHeight; i++) {
    const tx = i % cellWidth;
    const ty = Math.floor(i / cellWidth);
    const pixel = mapImage.get(tx, ty);
    board[i] = color(pixel[0], pixel[1], pixel[2], pixel[3]).toString("#rrggbbaa");
  }
}

function draw() {
  const temp = board.slice();
  for (let i = 0; i < cellWidth * cellHeight; i++) {
    const x = i % cellWidth;
    const y = floor(i / cellWidth);
    if (isWall(x, y) || isNone(x, y)) {
      continue;
    }
    const dir = dirs[floor(random(dirs.length))];
    const tx = x + dir.x;
    const ty = y + dir.y;
    if (isWall(tx, ty)) {
      continue;
    }
    const fi = y * cellWidth + x;
    const ti = ty * cellWidth + tx;
    temp[fi] = board[ti];
  }
  board = temp.slice();

  clear();
  for (let i = 0; i < cellWidth * cellHeight; i++) {
    const x = i % cellWidth;
    const y = floor(i / cellWidth);
    fill(board[i]);
    rect(x * cellSize, y * cellSize, cellSize, cellSize);
  }
}

function isWall(x, y) {
  const i = y * cellWidth + x;
  return board[i] === cellWall;
}

function isNone(x, y) {
  const i = y * cellWidth + x;
  return board[i] === cellNone;
}