Elementary/Objects.pde
class Space {
Node[] nodes;
float friction;
ArrayList<GroupBehavior> behaviors;
char boundsMode; // (w)all, (t)orus
Space(int count) {
nodes = new Node[count];
friction = 1.0/5;
behaviors = new ArrayList<GroupBehavior>();
boundsMode = 'w';
}
void setup(char actMode, char drawMode, char moveMode) {
for (int i = 0; i < nodes.length; i++) {
Node n = new Node();
n.actMode = actMode;
n.drawMode = drawMode;
n.moveMode = moveMode;
n.p.set(randomVectorNear(width/2, height/2));
nodes[i] = n;
}
for (GroupBehavior b : behaviors) {
b.setup(nodes, boundsMode);
}
}
void draw() {
for (GroupBehavior b : behaviors) {
b.update(nodes, friction);
}
for (Node n : nodes) {
n.act();
n.move(friction);
affect(n);
pushStyle();
for (GroupBehavior b : behaviors) {
b.style(n);
}
n.draw();
popStyle();
}
}
void affect(Node n) {
float left = 0, right = width, top = 0, bottom = height;
if (boundsMode == 'w') {
float vLoss = 1.0/10, aLoss = 1.0/10;
if (n.left() < left && n.v.x < 0) {
n.bounce('x', left, vLoss, aLoss);
} else if (n.right() > right && n.v.x > 0) {
n.bounce('x', right, vLoss, aLoss);
}
if (n.top() < top && n.v.y < 0) {
n.bounce('y', top, vLoss, aLoss);
} else if (n.bottom() > bottom && n.v.y > 0) {
n.bounce('y', bottom, vLoss, aLoss);
}
} else if (boundsMode == 't') {
if (n.right() < left) {
n.teleport('x', right);
} else if (n.left() > right) {
n.teleport('x', left);
}
if (n.bottom() < top) {
n.teleport('y', bottom);
} else if (n.top() > bottom) {
n.teleport('y', top);
}
}
}
}
int nodeIds = 0;
class Node {
int id;
PVector p, pPrev, pNext;
PVector v;
PVector a;
float vFloor, vCeil;
float aCeil;
int energyFrames;
int energyFramesPerAction;
int framesPerAction;
private int framesUntilAction;
float w, h;
char actMode; // (b)rownian, (n)one
char drawMode; // (b)all, (l)ine
char moveMode; // (e)nergy, (l)imits
Node() {
id = nodeIds++;
p = new PVector();
v = new PVector();
a = new PVector();
vFloor = 0.5;
vCeil = 2;
aCeil = 1;
energyFrames = 0;
energyFramesPerAction = secondsOfFrames(0.5);
framesPerAction = secondsOfFrames(1);
framesUntilAction = 0;
w = 10;
h = 10;
actMode = 'b';
drawMode = 'b';
moveMode = 'e';
}
float bottom() {
return p.y + ((drawMode == 'b') ? h/2 : 0);
}
float left() {
return p.x - ((drawMode == 'b') ? w/2 : 0);
}
float right() {
return p.x + ((drawMode == 'b') ? w/2 : 0);
}
float top() {
return p.y - ((drawMode == 'b') ? h/2 : 0);
}
float mass() { // AKA influence.
float density = 1;
return w * h * density;
}
void draw() {
if (drawMode == 'b') { // ball
ellipse(p.x, p.y, w, h);
} else if (drawMode == 'l') { // line
line(p.x, p.y, pPrev.x, pPrev.y);
}
if (pNext != null) {
// Sometimes need to draw before updating position.
p = pNext;
pNext = null;
}
}
void act() {
if (actMode == 'b') {
if (framesUntilAction == 0) {
framesUntilAction = framesPerAction;
PVector r = PVector.random2D().mult(aCeil);
a.set(r);
energyFrames = energyFramesPerAction;
} else {
framesUntilAction--;
if (energyFrames > 0) {
PVector r = PVector.random2D().mult(aCeil/3);
a.add(r).limit(1);
energyFrames--;
}
}
} else if (actMode == 'n') {
if (energyFrames > 0) {
energyFrames--;
}
}
}
void move(float friction) {
pPrev = p.copy();
PVector anyA = a.copy();
float scaledFriction = friction;
if (moveMode == 'e' && energyFrames <= 0) {
anyA = null;
scaledFriction *= aCeil;
} else if (moveMode == 'l') {
float aCeil = vCeil * friction * 2;
float vMag = v.mag();
if (vMag > vCeil) {
anyA.mult(0);
} else {
anyA.mult(aCeil);
if (vMag < vFloor) {
v.set(anyA).setMag(vFloor);
}
}
}
Physics.move(p, v, anyA, scaledFriction);
}
// -
void bounce(char axis, float pEdge, float vLoss, float aLoss) {
float vBounced = -(1 - vLoss);
float aBounced = -(1 - aLoss);
if (axis == 'x') {
p.x = pEdge - ((drawMode == 'b') ?
((pEdge == 0) ? -1 : 1) * w/2 : 0);
v.x *= vBounced;
a.x *= aBounced;
} else if (axis == 'y') {
p.y = pEdge - ((drawMode == 'b') ?
((pEdge == 0) ? -1 : 1) * h/2 : 0);
v.y *= vBounced;
a.y *= aBounced;
}
}
void teleport(char axis, float pEdge) {
pNext = p.copy();
if (axis == 'x') {
pNext.x = pEdge - ((drawMode == 'b') ?
((pEdge == 0) ? 1 : -1) * w/2 : 0);
} else if (axis == 'y') {
pNext.y = pEdge - ((drawMode == 'b') ?
((pEdge == 0) ? 1 : -1) * h/2 : 0);
}
}
}