a sandy demo for the emma project
 
 
 

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);
}
}
}
}