xxxxxxxxxx
181
// images
const image_hw = 50
let profile_image
let robot_image
let circles = [];
let ncircles = 40;
const height = 800;
const width = 800;
const offscreenbuffer = 25; // how far offscreen until go to other side
const speed = 0.01;
// moving
let max_velocity = 0.01
// pushing
const push_scaling = 0.1;
let max_push_amplitude = 0.0005;
const max_distance_away = 200
function setup() {
createCanvas(width, height);
background(60,100,40)
profile_image = loadImage("https://alifeee.co.uk/profile-picture.png")
robot_image = loadImage("https://alifeee.co.uk/robot.png")
for (let i=0; i < ncircles; i++) {
let colour = [
Math.random() * 255,
Math.random() * 255,
Math.random() * 255,
];
let x = Math.random() * width;
let y = Math.random() * height;
let vx = (Math.random() - 0.5) * speed
let vy = (Math.random() - 0.5) * speed
c = {}
c.id = i
c.colour = colour
c.x = x
c.y = y
c.vx = vx
c.vy = vy
circles.push(c)
}
}
function draw() {
clear()
background(60,100,40)
// physics process
circles.forEach(c => {
// add velocity to location
c.x = c.x + (c.vx * deltaTime)
c.y = c.y + (c.vy * deltaTime)
// boundary conditions
let osb = offscreenbuffer
// top edge
if (c.y < -osb) {
c.y = c.y + (height + 2 * osb)
}
// bottom edge
if (c.y > height + osb) {
c.y = c.y - (height + 2 * osb)
}
// left edge
if (c.x < -osb) {
c.x = c.x + (width + 2 * osb)
}
// right edge
if (c.x > width + osb) {
c.x = c.x - (width + 2 * osb)
}
})
// push circles away from friends
circles.forEach(c => {
circles.forEach(c2 => {
if (c.id == c2.id) {
return;
}
let distance_squared = (c2.x - c.x)**2 + (c2.y - c.y)**2
let distance = distance_squared**0.5
if (distance > max_distance_away) {
return;
}
// push_vector
let pv = {}
pv.x = c2.x - c.x
pv.y = c2.y - c.y
// push_unit_vector
let puv = {}
puv.x = pv.x / distance
puv.y = pv.y / distance
let mpa = max_push_amplitude
let mv = max_velocity
let ps = push_scaling
if (c.id == 0) {
mpa = mpa * 5000
mv = mv * 10
ps = ps * 100
}
let push_amplitude = Math.min(
mpa,
(1 / distance_squared) * ps
)
// alter velocities
let s
if (c2.id == 0) {
// run towards
s = 1
} else {
s = -1
}
c.vx = c.vx + s * (push_amplitude * puv.x)
c.vy = c.vy + s * (push_amplitude * puv.y)
if (c.vx < 0) {
c.vx = Math.max(c.vx, -mv)
} else {
c.vx = Math.min(c.vx, mv)
}
if (c.vy < 0) {
c.vy = Math.max(c.vy, -mv)
} else {
c.vy = Math.min(c.vy, mv)
}
if (c.id > 0) {
return;
}
fill(255,0,0);
strokeWeight(Math.min(5, 10000 / distance_squared))
stroke(0,255,0,200)
line(c.x, c.y, c2.x, c2.y)
strokeWeight(1)
stroke(255,0,0)
// visibility_modifier
let vm = 25
line(
c.x, c.y,
c.x-puv.x*vm, c.y-puv.y*vm
)
})
})
// draw
push()
circles.forEach(c => {
push()
fill(c.colour)
noStroke()
translate(c.x, c.y)
clip(circleMask)
let this_img = robot_image
if (c.id == 0) {
this_img = profile_image
}
image(this_img, -image_hw/2, -image_hw/2, image_hw, image_hw)
pop()
})
pop()
}
function circleMask() {
circle(0,0,image_hw)
}