xxxxxxxxxx
191
const WIDTH = 10;
const HEIGHT = 10;
let GRID_SIZE;
let entities = [
{
type: "player",
x: 0,
y: 0,
dir: { x: 0, y: 0 },
velocity: 0,
canMove: true,
},
{
type: "player",
x: 0,
y: 1,
dir: { x: 0, y: 0 },
velocity: 0,
canMove: true,
},
{
type: "player",
x: 1,
y: 0,
dir: { x: 0, y: 0 },
velocity: 0,
canMove: true,
},
{
type: "player",
x: 2,
y: 0,
dir: { x: 0, y: 0 },
velocity: 0,
canMove: true,
},
{
type: "player",
x: 2,
y: 1,
dir: { x: 0, y: 0 },
velocity: 0,
canMove: true,
},
// { type: "box", x: 1, y: 0, dir: { x: 0, y: 0 }, velocity: 0, canMove: true },
// { type: "box", x: 2, y: 0, dir: { x: 0, y: 0 }, velocity: 0, canMove: true },
{ type: "box", x: 3, y: 0, dir: { x: 0, y: 0 }, velocity: 0, canMove: true },
// { type: "box", x: 1, y: 1, dir: { x: 0, y: 0 }, velocity: 0, canMove: true },
{ type: "box", x: 1, y: 2, dir: { x: 0, y: 0 }, velocity: 0, canMove: true },
{ type: "box", x: 1, y: 3, dir: { x: 0, y: 0 }, velocity: 0, canMove: true },
{ type: "wall", x: 3, y: 3, dir: { x: 0, y: 0 }, velocity: 0, canMove: false },
];
function setup() {
createCanvas(400, 400);
GRID_SIZE = floor(min(width / WIDTH, height / HEIGHT));
}
function draw() {
background(220);
// if (keyIsPressed && keyIsDown(SHIFT)) input(key);
for (let i = 0; i < entities.length; i++) {
const entity = entities[i];
const { x, y } = entity;
const pos = getDrawPos(x, y);
switch (entity.type) {
case "player":
fill("white");
rect(pos.x, pos.y, GRID_SIZE, GRID_SIZE);
break;
case "box":
fill("orange");
rect(pos.x, pos.y, GRID_SIZE, GRID_SIZE);
break;
case "wall":
fill("black");
rect(pos.x, pos.y, GRID_SIZE, GRID_SIZE);
break;
}
textSize(GRID_SIZE);
fill('black');
text(i, pos.x + GRID_SIZE / 2 - textWidth(i) / 2, pos.y + GRID_SIZE / 2 + textSize() / 2.5);
}
}
function getDrawPos(x, y) {
return {
x: x * GRID_SIZE,
y: y * GRID_SIZE,
};
}
function keyPressed(evt) {
// console.log(evt);
input(evt.key);
}
function input(key) {
// console.log(key);
switch (key) {
case "ArrowRight":
step({ type: "playerMove", delta: { x: 1, y: 0 } });
break;
case "ArrowLeft":
step({ type: "playerMove", delta: { x: -1, y: 0 } });
break;
case "ArrowUp":
step({ type: "playerMove", delta: { x: 0, y: -1 } });
break;
case "ArrowDown":
step({ type: "playerMove", delta: { x: 0, y: 1 } });
break;
}
}
function step(action) {
const new_entities = structuredClone(entities);
// console.log(new_entities);
switch (action.type) {
case "playerMove":
const { delta } = action;
const players = new_entities.filter((entity) => entity.type === "player");
players.forEach((player) => {
player.dir = delta;
player.velocity = keyIsDown(SHIFT) ? 3 : 1;
});
break;
}
let i = 0;
for (; i < 1000; i++) {
//printEntities(new_entities);
if (!resolveEntities(new_entities)) return;
if (isResolved(new_entities)) {
// console.log("resolved!");
break;
}
}
// console.log("resolved", isResolved(new_entities), "steps", i, new_entities);
entities = new_entities;
}
function resolveEntities(entities) {
for (const entity of entities) {
const { dir, velocity } = entity;
if (velocity > 0) {
entity.x += entity.dir.x;
entity.y += entity.dir.y;
entity.velocity--;
entity.x = mod(entity.x, WIDTH);
entity.y = mod(entity.y, HEIGHT);
for (const entity2 of entities) {
if (entity === entity2) continue;
if (entity.x === entity2.x && entity.y === entity2.y) {
if (!entity2.canMove) return false;
entity2.velocity = 1;
entity2.dir.x = entity.dir.x;
entity2.dir.y = entity.dir.y;
}
}
}
}
return true;
}
function isResolved(entities) {
return entities.every((entity) => entity.velocity === 0);
}
function printEntities(entities) {
for (const entity of entities) {
console.log(JSON.stringify(entity));
}
console.log();
}
function mod(v, n) {
return ((v % n) + n) % n;
}