xxxxxxxxxx
274
let DEBUG_MODE = false;
let vehicles = [];
let foods = [];
let nest;
function setup() {
createCanvas(800, 800);
for (let i = 0; i < 70; i++) {
vehicles.push(
new Vehicle(
random(width / 2 - 50, width / 2 + 50),
random(height),
random(7, 8)
)
);
}
bigFood(100, 100, 30);
nest = new Nest(700, 700);
}
function draw() {
background(0);
if (foods.length == 0) {
let a = random(0, 2 * PI);
let r = 350;
bigFood(width / 2 + sin(a) * r, height / 2 + cos(a) * r, 30);
}
if (nest.r == nest.energy) {
let a = random(0, 2 * PI);
let r = 150;
nest = new Nest(width / 2 + sin(a) * r, height / 2 + cos(a) * r);
}
for (let i = 0; i < vehicles.length; i++) {
let v = vehicles[i];
let target;
//let target = createVector(mouseX, mouseY);
if (!v.isCarry) {
let t = nearest(v.pos.x, v.pos.y, foods);
//console.log(t);
target = createVector(t.x, t.y);
v.seek(target);
} else {
target = createVector(nest.x, nest.y);
v.seek(target);
}
v.detect(vehicles);
v.update();
v.reappear();
v.display();
}
for (let i = 0; i < foods.length; i++) {
foods[i].update();
}
nest.update();
}
function mousePressed() {
DEBUG_MODE = !DEBUG_MODE;
}
///// CLASS /////
class Vehicle {
constructor(x = 0, y = 0, size = 1) {
this.pos = createVector(x, y);
this.vel = p5.Vector.random2D().mult(3);
this.acc = createVector(0, 0);
this.size = size;
this.mass = 1;
//
this.angle = 0;
//
this.maxSpeed = 5;
this.maxSteerForce = 1;
// for detection
this.detectVector = createVector();
this.directionVector = createVector();
this.predictDistance = 10;
this.detectRadius = 20;
this.wanderAngle = random(TWO_PI);
this.isCarry = false;
}
detect(others) {
for (let other of others) {
if (this != other) {
this.detectVector = p5.Vector.mult(
this.vel.copy().normalize(),
this.predictDistance
);
let centerPos = p5.Vector.add(this.pos, this.detectVector);
let distance = centerPos.dist(other.pos);
if (distance < this.detectRadius) {
this.directionVector = p5.Vector.sub(other.pos, centerPos);
this.directionVector.setMag(this.detectRadius);
this.directionVector.mult(-1); // flip the vector to avoid
let directionPos = p5.Vector.add(centerPos, this.directionVector);
this.seek(directionPos);
}
}
}
}
seek(targetPos) {
let desiredVec = p5.Vector.sub(targetPos, this.pos);
let distance = desiredVec.mag();
for (let i = 0; i < foods.length; i++) {
if (distance < 1 && foods[i].display && this.isCarry == false) {
this.isCarry = true;
foods[i].display = false;
}
}
desiredVec.normalize();
desiredVec.mult(this.maxSpeed);
let steerForce = p5.Vector.sub(desiredVec, this.vel);
steerForce.limit(this.maxSteerForce);
this.applyForce(steerForce);
}
reappear() {
if (this.pos.x < 0) {
this.pos.x = width;
} else if (this.pos.x > width) {
this.pos.x = 0;
}
if (this.pos.y < 0) {
this.pos.y = height;
} else if (this.pos.y > height) {
this.pos.y = 0;
}
}
applyForce(f) {
if (this.mass > 0) {
let force = p5.Vector.div(f, this.mass);
this.acc.add(force);
}
}
update() {
this.vel.add(this.acc);
this.pos.add(this.vel);
this.acc.mult(0);
//
this.angle = this.vel.heading();
}
display() {
push();
translate(this.pos.x, this.pos.y);
push(); // push for rotation
rotate(this.angle);
// draw the vehicle
stroke(255);
fill(255, 150);
triangle(0, 0, -this.size, -this.size * 0.4, -this.size, this.size * 0.4);
pop(); // pop for rotation
if (this.isCarry) {
push();
noStroke();
fill(242, 97, 63, 200);
circle(0, 0, 10);
pop();
}
if (DEBUG_MODE) {
// draw detecting graphics
noFill();
stroke(255, 0, 0);
line(0, 0, this.detectVector.x, this.detectVector.y);
translate(this.detectVector.x, this.detectVector.y);
ellipse(0, 0, this.detectRadius * 2, this.detectRadius * 2);
stroke(0, 255, 0);
line(0, 0, this.directionVector.x, this.directionVector.y);
}
pop();
}
}
class Food {
constructor(x, y) {
this.x = x;
this.y = y;
this.isAvi = true;
this.display = true;
}
update() {
if (this.display) {
push();
noStroke();
fill(242, 97, 63, 200);
circle(this.x, this.y, 10);
pop();
}
}
}
function bigFood(x, y, r) {
for (let i = 0; i < floor(r) * 5; i++) {
let tx = random(-r, r);
let ty = random(-r, r);
if (dist(tx, ty, 0, 0) < r) {
foods.push(new Food(x + tx, y + ty));
}
}
}
function nearest(x, y, list) {
let flag,
disTemp = 2 * height;
//console.log(list[0]);
for (let i = 0; i < list.length; i++) {
let dis = dist(x, y, list[i].x, list[i].y);
if (dis < disTemp) {
disTemp = dis;
flag = i;
}
}
return list[flag];
}
class Nest {
constructor(x, y) {
this.x = x;
this.y = y;
this.r = 80;
this.energy = 0;
}
update() {
for (let i = 0; i < vehicles.length; i++) {
let dis = dist(vehicles[i].pos.x, vehicles[i].pos.y, this.x, this.y);
if (dis < this.r - 30 && vehicles[i].isCarry) {
for (let j = 0; j < foods.length; j++) {
if (foods[j].display == false) {
foods.splice(j, 1);
break;
}
}
//console.log(foods.length);
vehicles[i].isCarry = false;
this.energy += 1;
}
}
push();
stroke(255);
strokeWeight(3);
noFill();
circle(this.x, this.y, this.r);
fill(242, 97, 63, 200);
this.energy = constrain(this.energy, 0, this.r);
noStroke();
circle(this.x, this.y, this.energy);
pop();
}
}