xxxxxxxxxx
const CIRCLE = Math.PI * 2
const HALF_CIRCLE = Math.PI
let frameNum = 0
const world = {
speed: 5,
convoDist: 25,
angleChange: 0.1,
people: [
{
x: 10,
y: 20,
a: Math.PI * 0.3,
s: 3,
size: 6,
},
{
x: 10,
y: 20,
a: Math.PI * 0.3,
s: 3,
size: 8,
},
{
x: 10,
y: 20,
a: Math.PI * 0.3,
s: 3,
size: 4,
},
{
x: 10,
y: 20,
a: Math.PI * 0.3,
s: 3,
size: 4,
},
{
x: 50,
y: 80,
a: Math.PI * 0.7,
s: 1,
size: 7,
},
{
x: 10,
y: 20,
a: Math.PI * 0.3,
s: 3,
size: 6,
},
{
x: 10,
y: 20,
a: Math.PI * 0.3,
s: 3,
size: 8,
},
{
x: 10,
y: 20,
a: Math.PI * 0.3,
s: 3,
size: 4,
},
{
x: 10,
y: 20,
a: Math.PI * 0.3,
s: 3,
size: 4,
},
{
x: 50,
y: 80,
a: Math.PI * 0.7,
s: 1,
size: 7,
},
{
x: 100,
y: 50,
a: Math.PI * 0.1,
s: 4,
size: 5,
},
{
x: 10,
y: 20,
a: Math.PI * 0.3,
s: 3,
size: 14,
},
{
x: 50,
y: 80,
a: Math.PI * 0.7,
s: 1,
size: 7,
},
{
x: 100,
y: 50,
a: Math.PI * 0.1,
s: 4,
size: 5,
},
],
chatting: new Map(),
isChatting(person) {
return Boolean(this.chatting.get(person))
},
}
function setup() {
createCanvas(window.innerWidth, window.innerHeight);
world.width = window.innerWidth
world.height = window.innerHeight
for(const p of world.people) {
p.x = Math.random() * world.width
p.y = Math.random() * world.width
p.color = Math.random() * 255
}
noStroke()
}
function draw() {
background(50,50,50)
frameNum += 1
for(const person of world.people) {
if(world.isChatting(person)) {
fill(0, 100, 255)
if(frameNum > person.endAt) {
resolve(person)
} else if(frameNum > person.resolveAt) {
end(person)
} else {
// pass
}
} else {
fill(255, 0, 0)
walk(person)
}
const {x,y,size} = person
ellipse(x-size/2,y-size/2,size*2,size*2)
}
const addConvo = frameNum % 10
if(addConvo) {
const nonChatting = world.people.filter(p => !world.isChatting(p))
const neighbours = findNeighbours(nonChatting)
for(const [person, others] of neighbours.entries()) {
const other = pickRandom(Array.from(others))
chat(person, other)
person.resolveAt = frameNum + 50
person.endAt = frameNum + 100
}
}
}
function chat(p1, p2) {
world.chatting.set(p1, p2)
world.chatting.set(p2, p1)
}
function setMapSet(m,k,v) {
if(!m.get(k)) {
m.set(k,new Set)
}
m.get(k).add(v)
}
function findNeighbours(ppl) {
const neighbours = new Map
for(const p1 of ppl) {
for(const p2 of ppl) {
if(p1 === p2) continue
if(dist(p1.x,p1.y,p2.x,p2.y) < world.convoDist) {
setMapSet(neighbours, p1, p2)
setMapSet(neighbours, p2, p1)
}
}
}
return neighbours
}
function bound(v, min, max) {
return Math.min(Math.max(v, min), max)
}
function walk(person) {
person.x = bound(person.x + Math.cos(person.a) * person.s * world.speed, 0, world.width)
person.y = bound(person.y + Math.sin(person.a) * person.s * world.speed, 0, world.height)
person.a = (person.a + ((Math.random() -0.5) * world.speed * world.angleChange)) % CIRCLE
if(closeTo(person.x, 0) || closeTo(person.x, world.width) || closeTo(person.y, 0)
|| closeTo(person.y, world.height)) {
person.a = bounceH(person.a)
}
}
function bounceH(angle) {
return (angle + HALF_CIRCLE) % CIRCLE
}
function closeTo(a,b) {
return Math.abs(a - b) < 1e-3
}
function resolve(person) {
}
function end(person) {
const other = world.chatting.get(person)
world.chatting.delete(person)
world.chatting.delete(other)
bounceH(other)
}
function pickRandom(xs) {
return xs[Math.floor(xs.length * Math.random())]
}