This example was adapted from an interactive figure in the the tile map chapter of compform.net. This version supports multiple simultanious users with p5.party!
Try this example in two browser windows at once!
const grid_cols = 12;
const grid_rows = 8;
const row_height = 32;
const col_width = 32;
let road_set;
let overlay_checkbox, road_checkbox;
let shared;
function preload() {
partyConnect("wss://demoserver.p5party.org", "tile_mapper");
shared = partyLoadShared("globals");
road_set = loadImage("./road.png");
}
function setup() {
createCanvas(grid_cols * col_width, grid_rows * row_height);
// create the ui
road_checkbox = createCheckbox("Show Road", true);
overlay_checkbox = createCheckbox("Show Active Cells", false);
// generate a 2D array to hold the state of each grid cell
if (!shared.grid) {
shared.grid = create2DArray(grid_cols, grid_rows, false);
// populate an initial drawing
shared.grid[6][4] = true;
shared.grid[7][4] = true;
shared.grid[8][4] = true;
shared.grid[7][3] = true;
shared.grid[7][5] = true;
}
noSmooth();
}
function mouseReleased() {
if (mouseX < 0 || mouseX >= width || mouseY < 0 || mouseY >= height) return;
console.log("mouseReleased");
// find the grid location of the click
const grid_x = floor(mouseX / col_width);
const grid_y = floor(mouseY / col_width);
// toggle the cell state
shared.grid[grid_x][grid_y] = !shared.grid[grid_x][grid_y];
}
function touchEnded() {
console.log("touch end");
mouseReleased();
// mouseClicked();
}
function draw() {
background("#333333");
drawMap();
drawGrid();
}
function drawMap() {
// loop over each cell
for (let col = 0; col < grid_cols; col++) {
for (let row = 0; row < grid_rows; row++) {
// check the state of the cell
const cellIsSet = sampleGrid(col, row);
if (cellIsSet) {
// draw the road
if (road_checkbox.checked()) {
const score = getScore(col, row);
drawRoadTile(score, col, row);
}
// draw the overlay
if (overlay_checkbox.checked()) {
blendMode(LIGHTEST);
fill("red");
noStroke();
const x = col * col_width;
const y = row * row_height;
rect(x, y, col_width, row_height);
blendMode(NORMAL);
}
}
}
}
}
// draw grid lines
function drawGrid() {
stroke(255, 255, 255, 20);
for (let x = 0; x < width; x += col_width) {
line(x, 0, x, height);
}
for (let y = 0; y < height; y += row_height) {
line(0, y, width, y);
}
}
// draws a single tile from the atlas at the given grid col + row
function drawRoadTile(score, col, row) {
// find location to draw
const x = col * col_width;
const y = row * row_height;
// the tiles are packed into a single 4 x 4 atlas
// we need calculate what part of the image to draw
const sx = (score % 4) * 16;
const sy = floor(score / 4) * 16;
// draw it
image(road_set, x, y, col_width, row_height, sx, sy, 16, 16);
}
// apply the rules to find the tile id that should be dawn
function getScore(col, row) {
let score = 0;
if (sampleGrid(col, row - 1)) score += 1;
if (sampleGrid(col + 1, row)) score += 2;
if (sampleGrid(col, row + 1)) score += 4;
if (sampleGrid(col - 1, row)) score += 8;
return score;
}
// check the grid value at the col, row
// if the location is out of bounds just return false
function sampleGrid(col, row) {
if (col < 0 || col >= grid_cols) return false;
if (row < 0 || row >= grid_rows) return false;
return shared.grid[col][row];
}
// init an array cols x rows large
function create2DArray(cols, rows, value) {
const a = [];
for (let col = 0; col < cols; col++) {
a[col] = [];
for (let row = 0; row < rows; row++) {
a[col][row] = value;
}
}
return a;
}
<!DOCTYPE html>
<html>
<head> </head>
<body>
<main></main>
<div id="readme"></div>
<h2>index.js</h2>
<div id="source-javascript"></div>
<h2>index.html</h2>
<div id="source-html"></div>
<script src="https://cdn.jsdelivr.net/npm/p5@1.4.1/lib/p5.js"></script>
<script src="/dist/p5.party.js"></script>
<script src="index.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.3/highlight.min.js"></script>
<link rel="stylesheet" href="/examples.css" />
<script src="/examples.js" type="module"></script>
</body>
</html>