Skip to content

Instantly share code, notes, and snippets.

@roxwize
Created October 27, 2022 01:41
Show Gist options
  • Select an option

  • Save roxwize/a5c4f673ac9c9962af47bb490df8451c to your computer and use it in GitHub Desktop.

Select an option

Save roxwize/a5c4f673ac9c9962af47bb490df8451c to your computer and use it in GitHub Desktop.
JavaScript prototype for pre
class Cell {
constructor(type, colour = '#000000', ctx, arr) {
this.type = type;
this.colour = colour;
this.ctx = ctx; // The canvas itself
this.arr = arr;
this.cellSize = {
w: Math.round(this.ctx.width / this.arr.w),
h: Math.round(this.ctx.height / this.arr.h),
};
}
draw(x, y) {
this.ctx.getContext('2d').fillStyle = this.colour;
this.ctx
.getContext('2d')
.fillRect(
x * this.cellSize.w,
y * this.cellSize.h,
this.cellSize.w,
this.cellSize.h
);
}
randDir() {
return Math.random() < 0.5 ? -1 : 1;
}
is(x, y, typ) {
if (typeof typ == 'string') {
return this.arr.get(x, y).type == typ;
} else if (typeof typ == 'object') {
return typ.indexOf(this.arr.get(x, y).type) >= 0;
}
}
replace(ox, oy, nx, ny) {
this.arr.set(ox, oy, new Empty(this.arr));
this.arr.set(nx, ny, this);
}
}
class Empty extends Cell {
constructor(arr) {
super('Empty', '#000000', canvas, arr);
}
think() {
return;
}
}
class Sand extends Cell {
constructor(arr) {
super('Sand', '#e0db3a', canvas, arr);
}
think(x, y) {
const dir = this.randDir();
if (this.is(x, y + 1, ['Empty', 'Water'])) {
// If space below is empty or water, fall
this.replace(x, y, x, y + 1);
} else if (this.is(x + dir, y + 1, ['Empty', 'Water'])) {
// Fall in random diagonal direction
this.replace(x, y, x + dir, y + 1);
}
}
}
class Water extends Cell {
constructor(arr) {
super('Water', '#5fa9c9', canvas, arr);
}
think(x, y, horiz) {
const dir = this.randDir();
if (this.is(x, y + 1, 'Empty')) {
this.replace(x, y, x, y + 1);
} else if (this.is(x + dir, y, 'Empty')) {
// This prevents teleportations
horiz.push({
x: x,
y: y,
nx: x + dir,
element: this,
});
}
}
}
class Barrier extends Cell {
constructor(arr) {
super('Barrier', '#727272', canvas, arr);
}
}
class CellBuffer {
constructor(width, height) {
this.w = width;
this.h = height;
this.v = [];
for (let i = 0; i < this.w * this.h; i++) {
this.v[i] = new Empty(this);
}
}
get(x, y) {
if (x < 0 || x >= this.w || y < 0 || y >= this.h)
return new Barrier(x + y * this.w, this.v);
return this.v[x + y * this.w];
}
set(x, y, val) {
this.v[x + y * this.w] = val;
}
}
const canvas = document.getElementById('cool');
const ctx = canvas.getContext('2d');
const buf = new CellBuffer(50, 50);
let horiz = []; // Horizontal movement queue
function parseQueue() {
// Finish up horizontal movements that have been queued
for (let m of horiz) {
if (
m.element.is(m.x, m.y, m.element.type) &&
m.element.is(m.nx, m.y, 'Empty')
) {
m.element.replace(m.x, m.y, m.nx, m.y);
}
}
}
function thinkIter() {
for (let y = buf.h - 1; y >= 0; y--) {
horiz = []; // this is for the water
for (let x = 0; x < buf.w; x++) {
const cell = buf.get(x, y);
if (cell.think) {
if (cell.type !== 'Water') cell.think(x, y);
else cell.think(x, y, horiz);
}
parseQueue();
}
}
}
function drawIter() {
for (let y = 0; y < buf.h; y++) {
for (let x = 0; x < buf.w; x++) {
const cell = buf.get(x, y);
cell.draw(x, y);
}
}
}
function addWater() {
buf.set(40, 0, new Water(buf));
}
function init() {
buf.set(25, 2, new Sand(buf));
}
function tick() {
thinkIter();
drawIter();
}
setInterval(init, 300);
setInterval(tick, 10);
setInterval(addWater, 100);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment