Skip to content

Instantly share code, notes, and snippets.

@JoshuaSullivan
Last active July 14, 2017 14:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JoshuaSullivan/8ba8abed460f7e18df744f46ad457b85 to your computer and use it in GitHub Desktop.
Save JoshuaSullivan/8ba8abed460f7e18df744f46ad457b85 to your computer and use it in GitHub Desktop.
Some forms of motion amuse the system more than others…
final int PILLAR_ORDER = 12;
final int DIAGONALS = PILLAR_ORDER * 2 - 1;
final float PILLAR_WIDTH = 20.0;
final float PILLAR_HEIGHT = 10.0;
final float PILLAR_SPACING = 2.0;
final float GRAVITY = -1.0;
final float ELASTICITY = -0.5;
final float MAX_HEIGHT = 500.0;
final int TOTAL_RINGS = int(ceil(float(PILLAR_ORDER) / 2));
final int DELAY = 200;
class Pillar {
float velocity, height, hue;
Pillar() {
velocity = 0.0;
height = 0.0;
hue = random(360.0);
}
void pop(float popVelocity) {
velocity += popVelocity;
}
void update() {
if (velocity == 0.0 && height == 0.0) {
// At rest.
return;
}
velocity += GRAVITY;
height += velocity;
if (height <= 0) {
// Bounce!
height = 0.0;
velocity *= ELASTICITY;
if (velocity < abs(GRAVITY)) {
velocity = 0.0;
}
} else if (height >= MAX_HEIGHT) {
// Bounce off ceiling.
height = MAX_HEIGHT;
velocity *= ELASTICITY;
}
}
void draw() {
if (height == 0.0 && velocity == 0.0) {
return;
}
float pw = PILLAR_WIDTH / 2.0;
float ph = PILLAR_HEIGHT / 2.0;
float h = round(height);
noStroke();
color c;
if (h > 0.0) {
c = color(hue, 20, 100, 100);
fill(c);
quad(0, 0, -pw, -ph, -pw, -(h + ph), 0, -h);
c = color(hue, 40, 100, 100);
fill(c);
quad(0, 0, pw, -ph, pw, -(h + ph), 0, -h);
}
float hRatio = h / MAX_HEIGHT;
c = color(hue, 4 + 10 * hRatio, 100, 100);
fill(c);
quad(0, -h, -pw, -(h + ph), 0, -(h + pw), pw, -(h + ph));
}
}
float[] offsets;
int pillarCount;
Pillar[] pillars;
Pillar[][] pillarGrid;
int lastPop = 0;
int popIndex = 0;
void setup() {
size(300, 640);
colorMode(HSB, 360, 100, 100, 100);
pillarCount = PILLAR_ORDER * PILLAR_ORDER;
pillars = new Pillar[pillarCount];
pillarGrid = new Pillar[pillarCount][pillarCount];
for (int i = 0; i < pillarCount; i++) {
pillars[i] = new Pillar();
}
int index = 0;
float rowCount = 0.0;
offsets = new float[pillarCount * 2];
float pw = PILLAR_WIDTH / 2.0 + PILLAR_SPACING;
float ph = -(PILLAR_HEIGHT / 2.0 + PILLAR_SPACING);
for (int i = 0; i < PILLAR_ORDER; i++) {
float xOffset = float(i) * -pw;
for (int j = 0; j <= i; j++) {
// Calculate the offset for this pillar.
float x = j * (PILLAR_WIDTH + 2.0 * PILLAR_SPACING) + xOffset;
float y = rowCount * ph;
offsets[index * 2] = x;
offsets[index * 2 + 1] = y;
index++;
}
rowCount += 1.0;
}
for (int i = PILLAR_ORDER - 2; i >= 0; i--) {
float xOffset = float(i) * -pw;
for (int j = 0; j <= i; j++) {
float x = j * (PILLAR_WIDTH + 2.0 * PILLAR_SPACING) + xOffset;
float y = rowCount * ph;
offsets[index * 2] = x;
offsets[index * 2 + 1] = y;
index++;
}
rowCount+= 1.0;
}
int[] rowCounts = new int[PILLAR_ORDER];
int gridLoops = 2 * PILLAR_ORDER - 1;
int pillarIndex = 0;
for (int i = 0; i < gridLoops; i++) {
// Place into the pillar grid;
int gridRow = min(i, PILLAR_ORDER - 1);
while (gridRow >= 0 && rowCounts[gridRow] < PILLAR_ORDER) {
int count = rowCounts[gridRow];
pillarGrid[gridRow][count] = pillars[pillarIndex];
rowCounts[gridRow]++;
pillarIndex++;
gridRow--;
}
}
float deltaHue = 360.0 / float(TOTAL_RINGS);
for (int i = 0; i < TOTAL_RINGS; i++) {
Pillar[] ring = getRing(i);
int ringCount = countForRing(i);
float hue = float(i) * deltaHue;
for (int j = 0; j < ringCount; j++) {
ring[j].hue = hue;
}
}
lastPop = millis();
}
void draw() {
background(0, 0, 100, 100);
int now = millis();
int timeSincePop = now - lastPop;
if (timeSincePop >= DELAY) {
int index = popIndex;
int count = countForRing(index);
Pillar[] group = getRing(index);
for (int i = 0; i < count; i++) {
group[i].pop(20.0);
}
popIndex++;
lastPop = now;
if (popIndex == TOTAL_RINGS) {
popIndex = 0;
lastPop += 5 * DELAY;
}
}
pushMatrix();
translate(150, 630);
for (int i = pillarCount - 1; i >= 0; i--) {
pushMatrix();
float x = offsets[i * 2];
float y = offsets[i * 2 + 1];
translate(x, y);
pillars[i].update();
pillars[i].draw();
popMatrix();
}
popMatrix();
}
int countForRing(int index) {
index = max(0, min(index, TOTAL_RINGS - 1));
int i = PILLAR_ORDER - 2 * index;
int j = i - 2;
if (j < 0) { return 1; }
println("i:", i, " / j:", j);
int total = i * i - j * j;
return total;
}
Pillar[] getRing(int index) {
int itemsToReturn = countForRing(index);
int count = 0;
Pillar[] pillarsToReturn = new Pillar[itemsToReturn];
int min = index;
int max = PILLAR_ORDER - index - 1;
println("Ring ", index, "should have", itemsToReturn, "items to return with bounds [", min, ",", max, "]");
for (int i = 0; i < PILLAR_ORDER; i++) {
for (int j = 0; j < PILLAR_ORDER; j++) {
if (i >= min && i <= max && j >= min && j <= max && (i == min || i == max || j == min || j == max)) {
pillarsToReturn[count] = pillarGrid[i][j];
count++;
}
}
}
return pillarsToReturn;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment