Created
March 4, 2026 12:58
-
-
Save attentionmech/24d8dfba6b0c0d4eca5805d7c64ab62c to your computer and use it in GitHub Desktop.
forest scene in p5js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| let boids = []; | |
| let trees = []; | |
| let shrubs = []; | |
| let water = []; | |
| let horizon; | |
| function setup(){ | |
| createCanvas(900,600); | |
| horizon = height*0.62; | |
| for(let i=0;i<35;i++) boids.push(new Boid()); | |
| for(let i=0;i<25;i++) trees.push({x:random(width),h:random(70,120)}); | |
| for(let i=0;i<45;i++) shrubs.push({x:random(width),s:random(8,14)}); | |
| for(let i=0;i<500;i++) water.push(new WaterParticle()); | |
| } | |
| function draw(){ | |
| background(18); | |
| drawSky(); | |
| drawBoids(); | |
| drawGround(); | |
| drawWater(); | |
| drawTrees(); | |
| drawShrubs(); | |
| } | |
| /* SKY */ | |
| function drawSky(){ | |
| noStroke(); | |
| for(let y=0;y<horizon;y++){ | |
| let c = map(y,0,horizon,40,10); | |
| fill(c,c+20,c+40); | |
| rect(0,y,width,1); | |
| } | |
| } | |
| /* BOIDS */ | |
| class Boid{ | |
| constructor(){ | |
| this.pos=createVector(random(width),random(horizon)); | |
| this.vel=p5.Vector.random2D(); | |
| this.acc=createVector(); | |
| this.maxSpeed=2.5; | |
| this.maxForce=0.05; | |
| } | |
| flock(boids){ | |
| let sep=this.separate(boids).mult(1.5); | |
| let ali=this.align(boids); | |
| let coh=this.cohesion(boids); | |
| this.acc.add(sep); | |
| this.acc.add(ali); | |
| this.acc.add(coh); | |
| } | |
| update(){ | |
| this.vel.add(this.acc); | |
| this.vel.limit(this.maxSpeed); | |
| this.pos.add(this.vel); | |
| this.acc.mult(0); | |
| if(this.pos.x<0)this.pos.x=width; | |
| if(this.pos.x>width)this.pos.x=0; | |
| if(this.pos.y<0)this.pos.y=0; | |
| if(this.pos.y>horizon)this.pos.y=horizon; | |
| } | |
| display(){ | |
| push(); | |
| translate(this.pos.x,this.pos.y); | |
| rotate(this.vel.heading()); | |
| stroke(255); | |
| line(-6,0,6,0); | |
| line(0,0,-4,-3); | |
| line(0,0,-4,3); | |
| pop(); | |
| } | |
| separate(boids){ | |
| let desired=20; | |
| let steer=createVector(); | |
| let count=0; | |
| for(let other of boids){ | |
| let d=p5.Vector.dist(this.pos,other.pos); | |
| if(d>0 && d<desired){ | |
| let diff=p5.Vector.sub(this.pos,other.pos); | |
| diff.normalize(); | |
| diff.div(d); | |
| steer.add(diff); | |
| count++; | |
| } | |
| } | |
| if(count>0) steer.div(count); | |
| if(steer.mag()>0){ | |
| steer.setMag(this.maxSpeed); | |
| steer.sub(this.vel); | |
| steer.limit(this.maxForce); | |
| } | |
| return steer; | |
| } | |
| align(boids){ | |
| let neigh=40; | |
| let sum=createVector(); | |
| let count=0; | |
| for(let other of boids){ | |
| let d=p5.Vector.dist(this.pos,other.pos); | |
| if(d>0 && d<neigh){ | |
| sum.add(other.vel); | |
| count++; | |
| } | |
| } | |
| if(count>0){ | |
| sum.div(count); | |
| sum.setMag(this.maxSpeed); | |
| let steer=p5.Vector.sub(sum,this.vel); | |
| steer.limit(this.maxForce); | |
| return steer; | |
| } | |
| return createVector(); | |
| } | |
| cohesion(boids){ | |
| let neigh=40; | |
| let sum=createVector(); | |
| let count=0; | |
| for(let other of boids){ | |
| let d=p5.Vector.dist(this.pos,other.pos); | |
| if(d>0 && d<neigh){ | |
| sum.add(other.pos); | |
| count++; | |
| } | |
| } | |
| if(count>0){ | |
| sum.div(count); | |
| return this.seek(sum); | |
| } | |
| return createVector(); | |
| } | |
| seek(target){ | |
| let desired=p5.Vector.sub(target,this.pos); | |
| desired.setMag(this.maxSpeed); | |
| let steer=p5.Vector.sub(desired,this.vel); | |
| steer.limit(this.maxForce); | |
| return steer; | |
| } | |
| } | |
| function drawBoids(){ | |
| for(let b of boids){ | |
| b.flock(boids); | |
| b.update(); | |
| b.display(); | |
| } | |
| } | |
| /* LAND */ | |
| function drawGround(){ | |
| fill(25,70,35); | |
| rect(0,horizon,width,height-horizon); | |
| } | |
| /* TREES */ | |
| function drawTrees(){ | |
| for(let t of trees){ | |
| push(); | |
| translate(t.x,horizon); | |
| stroke(220); | |
| fractalTree(t.h); | |
| pop(); | |
| } | |
| } | |
| function fractalTree(len){ | |
| strokeWeight(map(len,10,120,1,4)); | |
| line(0,0,0,-len); | |
| translate(0,-len); | |
| if(len>12){ | |
| push(); | |
| rotate(PI/6); | |
| fractalTree(len*0.7); | |
| pop(); | |
| push(); | |
| rotate(-PI/6); | |
| fractalTree(len*0.7); | |
| pop(); | |
| } | |
| } | |
| /* SHRUBS USING L-SYSTEM */ | |
| function drawShrubs(){ | |
| for(let s of shrubs){ | |
| push(); | |
| translate(s.x,horizon+5); | |
| scale(0.4); | |
| stroke(180); | |
| lsystemBush(s.s); | |
| pop(); | |
| } | |
| } | |
| function lsystemBush(size){ | |
| let sentence="F"; | |
| for(let i=0;i<3;i++){ | |
| let next=""; | |
| for(let c of sentence){ | |
| if(c=="F") next+="F[+F]F[-F]F"; | |
| else next+=c; | |
| } | |
| sentence=next; | |
| } | |
| let len=size; | |
| let angle=PI/5; | |
| for(let c of sentence){ | |
| if(c=="F"){ | |
| line(0,0,0,-len); | |
| translate(0,-len); | |
| } | |
| else if(c=="+") rotate(angle); | |
| else if(c=="-") rotate(-angle); | |
| else if(c=="[") push(); | |
| else if(c=="]") pop(); | |
| } | |
| } | |
| /* WATER STREAM */ | |
| class WaterParticle{ | |
| constructor(){ | |
| this.pos=createVector(random(width),random(horizon+40,height)); | |
| this.vel=createVector(); | |
| } | |
| update(){ | |
| let n=noise(this.pos.x*0.003,this.pos.y*0.003,frameCount*0.01); | |
| let angle=n*TWO_PI*2; | |
| this.vel.x=cos(angle)*1.2; | |
| this.vel.y=sin(angle)*0.4; | |
| this.pos.add(this.vel); | |
| if(this.pos.x<0) this.pos.x=width; | |
| if(this.pos.x>width) this.pos.x=0; | |
| if(this.pos.y<horizon+30) this.pos.y=random(horizon+40,height); | |
| } | |
| display(){ | |
| stroke(120,170,255,120); | |
| point(this.pos.x,this.pos.y); | |
| } | |
| } | |
| function drawWater(){ | |
| for(let p of water){ | |
| p.update(); | |
| p.display(); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment