224 lines
5.7 KiB
224 lines
5.7 KiB
const p5 = require("p5");
|
|
new p5();
|
|
//import * as Tone from "tone";
|
|
|
|
// unhinged parcel workaround
|
|
//const sandURL = require("./sounds/sand.mp3");
|
|
|
|
const sounds = new Map();
|
|
|
|
let brushRadius = 3;
|
|
|
|
let count = 0;
|
|
let parts = new Map();
|
|
|
|
|
|
function p(x,y){
|
|
return `${x},${y}`
|
|
}
|
|
|
|
// have to specifically put these in window since im usign a bundler
|
|
window.setup = () => {
|
|
const rndr = createCanvas(120*2,60*2);
|
|
background(50);
|
|
|
|
//sounds["sand"] = new Tone.Player(sandURL).toDestination();
|
|
//rndr.elt.addEventListener('click', async () => {
|
|
// await Tone.start();
|
|
// console.log('audio is ready');
|
|
//});
|
|
}
|
|
|
|
window.draw = () => {
|
|
background(50);
|
|
//user input
|
|
if(mouseIsPressed && count <= 10000){
|
|
let mx = Math.floor(mouseX);
|
|
let my = Math.floor(mouseY);
|
|
|
|
if(!parts.get(p( mx,my ))){
|
|
if(mouseButton == LEFT){
|
|
parts.set(p( mx,my ), new Sand(mx,my));
|
|
}
|
|
else if(mouseButton == RIGHT){
|
|
parts.set(p( mx,my ), new Fire(mx,my));
|
|
}
|
|
else if(mouseButton == CENTER){
|
|
parts.set(p( mx,my ), new Water(mx,my));
|
|
}
|
|
}
|
|
/*/
|
|
for(let x=-brushRadius; x<brushRadius; x++){
|
|
for(let y=-brushRadius; y<brushRadius; y++){
|
|
}
|
|
}
|
|
//*/
|
|
}
|
|
|
|
|
|
//update
|
|
for(const [k, curr] of parts){
|
|
curr.tick();
|
|
}
|
|
|
|
//draw
|
|
for(const [k, curr] of parts){
|
|
stroke(curr.constructor.color);
|
|
point(curr.x,curr.y);
|
|
noFill();
|
|
}
|
|
}
|
|
|
|
class Particle {
|
|
constructor(x,y){
|
|
this.x = x;
|
|
this.y = y;
|
|
count++;
|
|
parts.set(p( x,y ), this);
|
|
}
|
|
|
|
die(){
|
|
count--;
|
|
parts.delete(p( this.x, this.y ));
|
|
}
|
|
|
|
move(x,y){
|
|
const ox = this.x;
|
|
const oy = this.y;
|
|
this.x = x;
|
|
this.y = y;
|
|
parts.set(p( this.x,this.y ) , this);
|
|
parts.delete(p( ox,oy ));
|
|
}
|
|
}
|
|
|
|
class Sand extends Particle {
|
|
static color = color(237,193,128);
|
|
static timeBetweenMoves = 80;
|
|
static chanceToBurn = 1/30;
|
|
//static noise;
|
|
//static filter;
|
|
//static soundCount;
|
|
//static {
|
|
// this.noise = new Tone.Noise("pink").start();
|
|
// this.noise.volume.value = -Infinity;
|
|
// this.filter = new Tone.Filter(880*2,"bandpass",-96);
|
|
// this.noise.connect(this.filter).toDestination();
|
|
//}
|
|
//static ClassTick(){
|
|
// this.soundCount = constrain(this.soundCount-1,0, Infinity);
|
|
//}
|
|
|
|
constructor(x,y) {
|
|
super(x,y)
|
|
this.playSound = true;
|
|
this.lastmove = millis();
|
|
}
|
|
|
|
tick(){
|
|
//move the sand down
|
|
if(this.y + 1 <= height &&
|
|
millis() - this.lastmove >= Sand.timeBetweenMoves){
|
|
const dn = parts.get(p( this.x,this.y+1 ));
|
|
if(dn == undefined){
|
|
this.move(this.x, this.y+1);
|
|
}
|
|
else if(dn.constructor.name == "Water"){
|
|
dn.move(-1, -1);
|
|
this.move(this.x, this.y+1);
|
|
dn.move(this.x, this.y-1);
|
|
}
|
|
|
|
this.lastmove = millis();
|
|
}
|
|
//else if(this.playSound){
|
|
// this.playSound = false;
|
|
// Tone.loaded().then(() =>{
|
|
// sounds.sand.start();
|
|
// })
|
|
//}
|
|
//if it hits something play the sample
|
|
}
|
|
}
|
|
|
|
class Fire extends Particle {
|
|
static color = color(252,86,45);
|
|
static timeBetweenMoves = 150;
|
|
|
|
constructor(x,y){
|
|
super(x,y)
|
|
this.startY = y;
|
|
this.lastmove = millis();
|
|
this.born = millis();
|
|
}
|
|
|
|
tick(){
|
|
if(Math.random() < 0.02){
|
|
this.die();
|
|
}
|
|
const nextY = this.y - 1 - round(Math.random()*0.8);
|
|
if(nextY > 0 && millis() - this.lastmove > Fire.timeBetweenMoves){
|
|
let upperNeighbor = parts.get(p(this.x, this.y-1))
|
|
if(upperNeighbor){
|
|
upperNeighbor.die();
|
|
}
|
|
this.move(this.x + round(map(Math.random(),0,1,-1,1)), nextY);
|
|
this.lastmove = millis();
|
|
}
|
|
for(let x=-1;x<=1;x++){
|
|
for(let y=-1;y<=1;y++){
|
|
if(x==0 && y==0) continue;
|
|
|
|
const n = parts.get(p(this.x+x,this.y+y));
|
|
if(n && Math.random() < n.constructor.chanceToBurn){
|
|
n.die();
|
|
parts.set(p(this.x+x,this.y+y), new Fire(this.x+x,this.y+y))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
class Water extends Particle {
|
|
static color = color(30,60,240);
|
|
static timeBetweenMoves = 60;
|
|
static chanceToBurn = 0;
|
|
constructor(x,y){
|
|
super(x,y)
|
|
this.lastmove = millis();
|
|
}
|
|
|
|
tick(){
|
|
if(millis() - this.lastmove >= Water.timeBetweenMoves){
|
|
if(this.y + 1 <= height){
|
|
let dn = parts.get(p(this.x,this.y+1));
|
|
|
|
if(dn == undefined){
|
|
this.lastmove = millis();
|
|
this.move(this.x, this.y+1)
|
|
return;
|
|
}
|
|
else if(dn.constructor.name == "Fire"){
|
|
dn.die();
|
|
this.lastmove = millis();
|
|
this.move(this.x, this.y+1)
|
|
return;
|
|
}
|
|
}
|
|
|
|
//we didnt move down so move out
|
|
let num = (Math.random() > 0.5) ? -1 : 1;
|
|
let n1 = parts.get(p(this.x-num,this.y));
|
|
let n2 = parts.get(p(this.x+num,this.y));
|
|
if(n1 == undefined){
|
|
this.lastmove = millis();
|
|
this.move(this.x-num, this.y);
|
|
}
|
|
else if(n2 == undefined){
|
|
this.lastmove = millis();
|
|
this.move(this.x+num, this.y);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|