/* built with Studio Sketchpad:
* https://sketchpad.cc
*
* observe the evolution of this sketch:
* https://studio.sketchpad.cc/sp/pad/view/ro.Oj39fnDIoU4/rev.574
*
* authors:
* Wolfe
* license (unless otherwise specified):
* creative commons attribution-share alike 3.0 license.
* https://creativecommons.org/licenses/by-sa/3.0/
*/
// My older sketch Wolves and Sheeps
// Wolves pursue sheeps, sheeps evade wolves
// Each tries not to collide others (of their kind)
// Pursuing wolves and evading sheeps have red circle around them
// Roaming ones are without these
// May 9-th 2012 - lame flocking
// my first attempt to use vectors at all
ArrayList Pack, Herd;
PVector average;
int count;
int WOLVES = 10;
int SHEEPS = 100;
int wIndentDIST = 15;
int sIndentDIST = 15;
int sFlockDIST = 100;
////// main setup ////////////////
void setup() {
size(600, 600, P2D);
Pack = new ArrayList();
Herd = new ArrayList();
for (int w=1; w<=WOLVES; w++) {
Pack.add(new Wolf());
}
for (int s=1; s<=SHEEPS; s++) {
Herd.add(new Sheep());
}
}
////// main draw ////////////
void draw() {
background(#02A713); // green lawn
/////////////////////// RESETING ////////////////////////
for (int w=0; w<Pack.size(); w++) {
Wolf wolf = (Wolf) Pack.get(w);
wolf.pursuedTarget = null;
wolf.pursuing = false;
// wolf.maxSpeed = 2;
}
for (int s=0; s<Herd.size(); s++) {
Sheep sheep = (Sheep) Herd.get(s);
sheep.evading = false;
sheep.flock = false;
// sheep.maxSpeed = 5;
}
/////////////////////////////////////////////////////////
////////// indenting ///////////
for (int w1=0; w1<Pack.size(); w1++) {
Wolf wolf1 = (Wolf) Pack.get(w1);
for (int w2=0; w2<Pack.size(); w2++) {
Wolf wolf2 = (Wolf) Pack.get(w2);
if (w1 != w2) {
float dist = wolf1.pos.dist(wolf2.pos);
if (dist < wIndentDIST) {
wolf1.evade(PVector.sub(wolf2.pos, wolf1.pos));
}
}
}
}
count = 0;
average = new PVector(0, 0);
for (int s1=0; s1<Herd.size(); s1++) {
Sheep sheep1 = (Sheep) Herd.get(s1);
for (int s2=0; s2<Herd.size(); s2++) {
Sheep sheep2 = (Sheep) Herd.get(s2);
if (s1 != s2) {
float dist = sheep1.pos.dist(sheep2.pos);
if (dist < sIndentDIST) {
sheep1.evade(PVector.sub(sheep2.pos, sheep1.pos));
}
//////////////////!!!!!!!!!!!!!!!!!!!!! flocking trying
if (dist < sFlockDIST) {
PVector averageDir = PVector.add(sheep1.pos,sheep2.pos);
averageDir.div(2);
averageDir.normalize();
sheep1.pursue(averageDir);
sheep2.pursue(averageDir);
}
//////////////////!!!!!!!!!!!!!!!!!!!!!
}
}
}
////////////////////////////////
////////////////// MAIN STEERING ENGINE //////////////////
for (int w=0; w<Pack.size(); w++) {
Wolf wolf = (Wolf) Pack.get(w);
//
for (int s=0; s<Herd.size(); s++) {
Sheep sheep = (Sheep) Herd.get(s);
if (sheep.pos.dist(wolf.pos) < sheep.fleeDist) {
sheep.evade(PVector.sub(wolf.pos, sheep.pos));
sheep.evading = true;
}
if (wolf.pos.dist(sheep.pos) < wolf.attackDist) {
wolf.pursuing = true;
if (wolf.pursuedTarget == null) wolf.pursuedTarget = sheep;
// if (wolf.pos.dist(sheep.pos) < 5) Herd.remove(s); // kill
if (wolf.pos.dist(sheep.pos) < wolf.pos.dist(wolf.pursuedTarget.pos)) {
wolf.pursuedTarget = sheep;
}
sheep.evade(PVector.sub(wolf.pos, sheep.pos));
sheep.evading = true;
// sheep.maxSpeed = 5;
} else sheep.wander();
// } else sheep.pursue(new PVector(10,10));
//
}
//
if (wolf.pursuedTarget != null) {
wolf.pursue(PVector.sub(wolf.pursuedTarget.pos, wolf.pos));
wolf.pursuing = true;
// wolf.maxSpeed = 5;
}
else wolf.wander();
}
//////////////////////////////////////////////////////////
for (int w=0; w<Pack.size(); w++) {
Wolf wolf = (Wolf) Pack.get(w);
wolf.update();
wolf.draw();
}
for (int s=0; s<Herd.size(); s++) {
Sheep sheep = (Sheep) Herd.get(s);
sheep.update();
sheep.draw();
}
}
///////////////////////////////
///////////////////////////////////////
///////////////////////////////////////
//////////////// Animal //////////////
class Animal {
public PVector pos, vel, acc;
public PVector vecAcc, vecVel;
int radius;
float maxSpeed;
float friction;
Animal() {
vel = new PVector(0, 0);
acc = new PVector(0, 0);
vecAcc = new PVector(0, 0);
vecVel = new PVector(0, 0);
radius = 5;
maxSpeed = 5;
friction = 0.05;
}
void drawVector(PVector v, PVector loc, float scal) {
pushStyle();
float len = v.mag()*scal;
stroke(0,100);
line(loc.x, loc.y, loc.x+v.x*scal, loc.y+v.y*scal);
popStyle();
}
public void pursue(PVector target) {
acc.add(target);
}
public void evade(PVector target) {
acc.sub(target);
}
public void wander() {
if (abs(vel.x) < abs(vel.y)) pursue(new PVector(random(-10, 10), 0));
else pursue(new PVector(0, random(-10, 10)));
}
public void update() {
vecAcc.set(acc);
acc.normalize();
vel.add(acc);
// vel.x += vel.x * -friction;
// vel.y += vel.y * -friction;
vecVel.set(vel);
vel.limit(maxSpeed);
pos.add(vel);
acc.set(0, 0, 0);
// acc.set(0,0,0); //brzda
////// BOUNCE //////////
//if ((pos.x+radius>width) || (pos.x-radius<0)) vel.x *= -1;
//if ((pos.y+radius>height) || (pos.y-radius<0)) vel.y *= -1;
////// BOUNCE //////////
////// SEAMLESS //////
if (pos.x>width) pos.x = 0;
if (pos.x<0) pos.x = width;
if (pos.y>height) pos.y = 0;
if (pos.y<0) pos.y = height;
////// SEAMLESS //////
}
}
///////////////////////////////////////
///////////////////////////////////////
///////////// Sheep /////////////
class Sheep extends Animal {
boolean evading, seekingFood, flock;
int fleeDist = 50;
int feedDist = 200;
Sheep() {
pos = new PVector(random(20, width-20), random(20, height-20));
evading = false;
}
Sheep(float x, float y) {
pos = new PVector(x, y);
evading = false;
}
public void draw() {
pushStyle();
stroke(0);
if (evading) {
strokeWeight(2);
stroke(255, 0, 0);
}
// elseif (seekingFood) stroke(0, 255, 0);
else {
strokeWeight(1);
stroke(0);
}
fill(255);
ellipse(pos.x, pos.y, radius*2, radius*2);
popStyle();
pushStyle();
strokeWeight(1);
drawVector(vel, pos, 4);
popStyle();
/*
pushStyle();
stroke(255, 100, 100, 200);
strokeWeight(3);
drawVector(acc, pos, 25 );
popStyle();
*/
}
}
///////////////////////////////////////
///////////////////////////////////////
///////////// Wolf ////////////////
class Wolf extends Animal {
boolean pursuing;
Sheep pursuedTarget;
int attackDist = 50;
Wolf() {
pos = new PVector(random(20, width-20), random(20, height-20));
pursuing = false;
}
Wolf(float x, float y) {
pos = new PVector(x, y);
pursuing = false;
}
public void draw() {
pushStyle();
if (pursuing) {
strokeWeight(2);
stroke(255, 0, 0);
}
else {
strokeWeight(1);
stroke(0);
}
fill(0);
ellipse(pos.x, pos.y, radius*2, radius*2);
popStyle();
pushStyle();
strokeWeight(1);
drawVector(vel, pos, 4);
popStyle();
/*
pushStyle();
stroke(255, 100, 100, 200);
strokeWeight(3);
drawVector(acc, pos, 25 );
popStyle();
*/
}
}