Lil Nippers

Unfortunately, this doesn’t look nearly as good in tiny youtube format, as it’s actually 1000+ pixels wide. The Macs in the clusters are huge and I wanted to make a thing that takes up most, if not all of the space. The nippers are pretty simple in nature: you feed them by typing on your keyboard, and after they eat a certain amount they will explode and become two tiny nippers. If there’s no food left for them to eat, their will to leave dissipates and they slowly move to a stop. Poor little nippers!

Originally, I wanted to assign more significance to the act of typing–there’s a residual element of that left over as the most frequent letters found in the English language (e, t, and a) give the nippers more energy than the least common (z, q, x). This was easily cribbed from Wikipedia, lots of people have done research into this and little kids use it to break each other’s substitution ciphers. As it stands, it’s more fun to smash keys and watch the nippers run around.

Were I to have more time to work on this, I would’ve loved to add a way for the nippers to slowly die. They each have their own different speeds, and when you run the program you’ll sometimes notice one brutally beating the competition, picking up food left and right and leaving slow, hungry nippers in its dust. I’d like to have them slow to a stop and begin to shrink if they haven’t eaten in a certain amount of time, reminding us that the circle of life involves stone-cold competition.


int zoom = 400;
PImage lLeg;
PImage rLeg;
PImage body;

//---GLOBAL COLORS---
color green = color(163, 169, 72);
color yellow = color(237, 185, 46);
color orange = color(248, 89, 49);
color red = color(206, 24, 54);
color blue = color(0, 153, 137);

//---FOOD STUFF---
ArrayList foods;

//---BUG STUFF---
ArrayList bugs;

//for adding bugs
ArrayList bugCoords;
int queue;

//for bugs eating foods
int distDex;

void setup() {
size(1800+zoom, 300);
noStroke();
smooth();

foods = new ArrayList();

bugs = new ArrayList();
bugs.add(new Bug(random(width-400), random(height*.75, height)));

bugCoords = new ArrayList();

rLeg = loadImage("rightleg.png");
lLeg = loadImage("leftleg.png");
body = loadImage("body.png");

}

void draw() {
background(230);
fill(255);
Bug zoomy = bugs.get(0);
pushMatrix();
translate(width-height-50+cos(zoomy.xpos/2), -height/4);
pushMatrix();
translate(height/3+25,height-23);
image(lLeg, -18, 3*sin(zoomy.xpos),height/6,height/6);
image(rLeg, 18, 3*cos(zoomy.xpos), height/6, height/6);
popMatrix();
image(body, 0, 0, height, height);
popMatrix();
rect(0, 0, width-399, height);
fill(230);
rect(0, height*.75, width-400, height);

for (Food f : foods) {
f.display();
}

for (Bug b : bugs) {

//get the closest food
float leastDist = -1;
float tempDist;
if (foods.size() > 0) {
for (int i = 0; i < foods.size(); i++) { Food g = foods.get(i); if (leastDist < 0) { leastDist = dist(b.xpos, b.ypos, g.x, g.y); distDex = i; } tempDist = dist(b.xpos, b.ypos, g.x, g.y); if (tempDist < leastDist) { distDex = i; leastDist = tempDist; } } } if (foods.size() > 0) {
Food goal = foods.get(distDex);
b.id = distDex;
b.seek(goal.x, goal.y);
}

if (foods.size() < 1) { b.vx = lerp(b.vx, 0, .001); b.vy = lerp(b.vy, 0, .001); } if ((dist(b.xpos, b.ypos, b.goalx, b.goaly) < 3) && (foods.size() > 0)) {
Food g = foods.get(b.id);
b.eat(g.priority);
foods.remove(b.id);

b.vx = lerp(b.vx, 0, .001);
b.vy = lerp(b.vy, 0, .001);
}

b.size = lerp(b.size, b.desiredSize, .1);

if (b.isMature() == true) {
b.desiredSize = 0.05;
bugCoords.add(b.xpos);
bugCoords.add(b.ypos);
queue += 1;
}

b.update();
b.display();
}

// safely add bugs
if (queue > 0) {
for (int i = 0; i < queue; i++) { float x = bugCoords.get(i); float y = bugCoords.get(i+1); bugs.add(new Bug(x+5, y)); } queue = 0; bugCoords.clear(); } } //---------------------------------------------------- //-- CHECK THE KEYBOARD FOR DELICIOUS FOOD! -- //---------------------------------------------------- void keyReleased() { //upper case if (int(key) >= 65 && int(key) < = 90) { float xpos = random(10, width-400-50); float ypos = random(height*.75+15, height - 5); int pri = checkUpper(key); if (pri != 0) { foods.add(new Food(xpos, ypos, 8, checkUpper(key))); } } //lower case else if (int(key) >= 97 && int(key) < = 122) { float xpos = random(10, width-400-50); float ypos = random(height*.75+15, height - 5); int pri = checkLower(key); if (pri != 0) { foods.add(new Food(xpos, ypos, 8, checkLower(key))); } } } //---------------------------------------------------- //-- GRAB COLOR/PRIORITY INFO FROM KEYBOARD -- //---------------------------------------------------- int checkLower(char letter) { int pri = 0; if ("eta".indexOf(str(letter)) > -1) {
pri = 5;
}
else if ("oinshr".indexOf(str(letter)) > -1) {
pri = 4;
}
else if ("dlcumwfg".indexOf(str(letter)) > -1) {
pri = 3;
}
else if ("ypbvk".indexOf(str(letter)) > -1) {
pri = 2;
}
else if ("xqz".indexOf(str(letter)) > -1) {
pri = 1;
}
return pri;
}

int checkUpper(char letter) {
int pri = 0;
if ("ETA".indexOf(str(letter)) > -1) {
pri = 5;
}
else if ("OSINSHR".indexOf(str(letter)) > -1) {
pri = 4;
}
else if ("DLCUMWFG".indexOf(str(letter)) > -1) {
pri = 3;
}
else if ("YPBVK".indexOf(str(letter)) > -1) {
pri = 2;
}
else if ("XQZ".indexOf(str(letter)) > -1) {
pri = 1;
}
return pri;
}

class Bug {
float xpos, ypos;
float vx, vy;
float dist;
float size = 0.05;
float desiredSize = size;
float ms = 100;
float goalx, goaly;
int id;
float speed;
float lastAte;

Bug(float xin, float yin) {
xpos = xin;
ypos = yin;
size = 0.05;
vx = 0;
vy = 0;
speed = random(.5,1.2);
}

void display() {
noStroke();
fill(52, 27, 27);
pushMatrix();
float depth = 1-((height-ypos)/height);
translate(xpos, ypos+cos(xpos/2)-depth*size*ms/2);
scale(depth*size, depth*size);
fill(72, 47, 47);
ellipse(-(ms/20), (ms/2)+sin(xpos), ms/10, ms/10);
fill(52, 27, 27);
ellipse(2*cos(millis()/200), 0, ms, ms);
ellipse((ms/20), (ms/2)+cos(xpos), ms/10, ms/10);
popMatrix();
}

void eat(float foodSize) {
desiredSize += foodSize / 100;
lastAte = millis();
}

void seek(float goalxin, float goalyin) {
goalx = goalxin;
goaly = goalyin;
float absx = goalx - xpos;
float absy = goaly - ypos;
float dist = sqrt((absx * absx) + (absy * absy));
vx = absx / dist * speed;
vy = absy / dist * speed;
}

void update() {
xpos += vx;
ypos += vy;

if (xpos + vx > width-400-(ms*size/2)) {
vx *= -1;
xpos = min(xpos, width-400-(ms*size/2));
}
else if (xpos + vx < 0) { vx *= -1; xpos = max(xpos, 0); } if (ypos + vy > height) {
vy *= -1;
ypos = min(ypos, height);
}
else if (ypos + vy < height*.75) { vy *= -1; ypos = max(ypos, height*.75); } } boolean isMature() { if (size > 1) {
return true;
}
return false;
}
}

class Food {
float x, y, dia;
int priority;
color flavor;

Food (float xin, float yin, float din, int pri) {
x = xin;
y = yin;
dia = din;
priority = pri;

//------SET COLOR-------
if (pri == 5) {
flavor = red;
}
else if (pri == 4) {
flavor = orange;
}
else if (pri == 3) {
flavor = yellow;
}
else if (pri == 2) {
flavor = green;
}
else if (pri == 1) {
flavor = blue;
}
}

void display() {
fill(flavor);
pushMatrix();
translate(x,y);
scale(1-((height-y)*2/height),1-((height-y)*2/height));
ellipse(0,0,dia,dia);
popMatrix();
}

boolean isGone() {
if (dia < 1) { return true; } return false; } }

Author: madeleine

maddy (madeleine?) varner is a freshman art student at carnegie mellon university. she gets along with computers well enough. she has a youtube (www.youtube.com/user/madeleinelv) and an openprocessing (http://www.openprocessing.org/user/31193) her twitter is @mlvarner