Category: Assignment-07-Life

Adam-Assignment-07-Life

Eye & Fly

Click to build blocks, click again to get rid off blocks. Use the arrow keys to navigate left, right and up.

The block building is adapted from simple platform game engine by Jacob Haip

Screen Shot 2013-12-17 at 12.21.16 pm

Sleepy Eye

Screen Shot 2013-12-17 at 12.22.03 pm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
 
///noise 
 
float x, y, oldX, oldY;
float xNoise, yNoise;
float xOffSet, yOffSet;
//
 
 
int blinkbottom = -100;
 
int eyewidth = 200;
 
int pupil = 60;
 
void setup () {
  size (800, 800);
  smooth ();
 
  ///noise 
  xNoise = random( width );
  yNoise = random( height );
  xOffSet = 0.01;  //  change this value to alter the line
  yOffSet = 0.01;  //  change this value to alter the line
}
 
void draw () {
  background (255);
  fill (100);
  noStroke ();
 
 
  float d = dist(width/2, 100, x, y);
  float m = map(d, 0, height-200, 200, 68);
 
    float p1 = map(d, 0, height-200, 59, 27);
 
fill(0); 
        ellipse(mouseX, mouseY, 300, 280); 
 
      drawNoisePoint( );
 
fill(255); 
 
 
  // eye balls 
    ellipse (mouseX, mouseY, eyewidth, m);
 
//map
  float eye1x = map (x, 0, 500, 150, 250);
  float eye1y = map (y, 0, height, 150, 250);
 
 
  eye1x = constrain (eye1x, 150, 250);
 
 
 
 
  // iris
  ellipseMode (CENTER);
  fill (94, 56);
  ellipse (mouseX+eye1x-200, mouseY+eye1y-200, 100, 100);
println(eye1x); 
 
 
  //pupils
  fill (0);
  ellipse (mouseX+eye1x -200, mouseY+eye1y-200, p1, p1);
 
beginShape();
vertex(mouseX -100,mouseY-80);
vertex(mouseX+100,mouseY-80);
vertex(mouseX+100,blinkbottom+mouseY+20);
vertex(mouseX+0,blinkbottom+mouseY);
vertex(mouseX-100,blinkbottom+mouseY+20);
endShape();
 
 
  if ((mousePressed == true) && (blinkbottom<68)) {
    blinkbottom+=15;
  }
  else if (blinkbottom>-100)
  {
    blinkbottom-=10;
  } 
 
 
 
 
}
 
 
 
 
void drawNoisePoint( )
{
    x = noise( xNoise )  * width ;
    y = noise( yNoise )  * height;
    ellipse( x, y, 5, 5 );
    xNoise = xNoise + xOffSet;
    yNoise = yNoise + yOffSet; 
}

Stillness (Assignment 7/9)

Overview

stillness cover photo

I made a projection of virtual butterflies which will come land on you (well, your projected silhouette) if you hold still, and will fly away if you move.

Inspiration

This semester, a friend of mine successfully lobbied for the creation of a “Mindfulness Room” to be created in one of the dorms on campus. The room is meant to be a place where students go to relax, meditate, and, as the name implies, be more mindful.

For my final project, I wanted to create something that was for a particular place, and so I chose the Mindfulness Room. Having tried to meditate in the past, I know it can be very challenging to clear your mind and sit entirely still for very long. So, the core of this project was to make something that would make you want to be still (and that would also fit in with the overall look and feel of the room.)

Technical Aspects

Some of the technical hurdles in this project:

  • Capturing a silhouette from a Kinect cam image. I tried to DIY this initially, which didn’t go well. Instead, I ended up finding this tutorial about integrating a Kinect and PBox2D. I fixed the tutorial code so that it would run in the most recent version of Processing and with the most recent version of the SimpleOpenNI library.
  • Integrating assorted libraries: SimpleOpenNIblobDetectionPBox2DToxicLibs, standard Java libraries. I almost certainly didn’t actually need to use all of them, but figured that out too late.
  • Dealing with janky parts of those libraries (e.g., jitteriness in the blobDetection library, fussiness of SimpleOpenNI). Using the libraries made my project possible, but I also couldn’t fix some things about them. I did, however, manage to improve blob detection from the Kinect cam image by filtering out all non-blue pixels (the Kinect highlights a User in blue).
  • Trying to simulate butterflies flying—with physics. Trying to simulate a whimsical flight path using forces in PBox2D had only ok results. I think it would be easier to create their paths in vanilla Processing or with another library, (though that might make collision detection far more challenging.)
  • Finding a computationally cheap way to do motion tracking. When I tried simple motion tracking, my program ate all my computer’s memory and still didn’t run. I ended up taking the Kinect/SimpleOpenNI provided “Center of Mass” and using that to track motion, which worked pretty well for my purposes.

Critical Reflection

As I worked on this project, I was unsure throughout that all the pieces (butterflies, kinect, etc.) would come together and/or work well. I think they came together fairly well in the end. Even though the project right now doesn’t live up to what I imagined in my head at the beginning, it still does what I essentially wanted it to do—making you want to stay still.

When people saw the project, their general response was “that’s really cool”, which was rewarding. Also, the person in charge of the Mindfulness room liked it enough that she wanted me to figure out how to make it work there long term. (Which could be really logistically difficult, in terms of setup and security because the room is always open and unsupervised, and drilling into the walls to mount things isn’t allowed.)

So, though there’s a list of things I think should be better about this project (see below), I think I managed to my concept simplistically, and well given that simplicity.

Things that could be better about this:

  • Butterflies’ visual appeal. Ideally, the wings would be hinged-together PBox2D objects. And antennae/other details would add a lot.
  • Butterflies movement. Could be more butterfly-like.
  • Attraction to person should probably be more gradual/a few butterflies at a time.
  • Code cleanliness: not good.
  • Ragged edge of person’s silhouette should be smooth.
  • Better capture of user. Sometimes the Kinect refuses to recognize a person as a User, or stops tracking it. This could have to do with how I treat the cam image, or placement, or lighting, or just be part of how I was doing Kinect/SimpleOpenNI. After talking with Golan, I think ditching OpenNI altogether and doing thresholding on the depth image would work best.

Video

Code

https://github.com/juliat/stillness2

monkeysphere

{video and sketches pending}

When this assignment was first released, all I wanted to do was simulate a Monkeysphere. The program adds a “friend” every time you press any key. The most recent friend would take up the creature’s attention, thus the creature always keeps the most recent friend in its sight. Although this program was only supposed to be strictly simulation, things got a lot more personal once I started adding names since the names are of people I knew/know in real life. I started projecting, resulting in the part where you press the mouse and discover a sort of anxiety-ridden creature trying to escape the sphere but it can’t. At any rate, once you get to Dunbar’s number, the creature has hit its limit of “friends” and needs to take a break. Once you give it some time, it’ll return to befriend a new round of friends.

I think I’ll work on this a bit more to figure out smoother animations and of course, the freezing problem: the program randomly freezes during the second round of counting up to Dunbar’s number (it seems it’s 23?).

Charachromism

“Chara” is intended to be short for “character” or “characteristics”. “Chromism” is a chemistry term that stands for change in color.

This was intended to be a simulation of an over-simplified version of my observations of human group behavior.
The color of each Dot represents its core personality. In addition, each also has its own set of characteristics that influence how the Dot approaches with and is influenced by other Dots.

The simulation is not working as I intend it to yet. There are a few characteristics that I haven’t implemented yet. This is a work in progress. I would like to put the Processing program on here, but it does not run when I upload it onto OpenProcessing and I do not know why.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
ArrayList<flock> allFlocks;
ArrayList<dot> allDots;
int nDots;
 
void setup() {
  size(400, 400);
  colorMode(HSB, 100);
  noStroke();
 
  nDots = 50;
 
  allFlocks = new ArrayList<flock>();
 
  allDots = new ArrayList<dot>();
  for (int i=0; i<ndots ; i++) {
    float x = random(width);
    float y = random(height);
    float s = random(0, 100);
    Dot d = new Dot(x, y, s, 10);
    allDots.add(d);
  }
}
 
void draw() {
  background(0, 0, 100);
 
  for (int i=0; i<allDots.size(); i++) {
    Dot ithDot = allDots.get(i);
    Flock iFlock = ithDot.flock;
    PVector ip = ithDot.position;
 
    float shadeDiff = iFlock.avgShade - ithDot.shade;
    if (shadeDiff>1.0) {
      ithDot.shade+=(shadeDiff*ithDot.agreeableness/100.0);
    }
 
    if (iFlock.stdev>(40.0*ithDot.openness)) {
      iFlock.removeDot(ithDot);
      if (iFlock.flockSize()==0) {
        allFlocks.remove(iFlock);
      }
      Flock fnew = new Flock();
      fnew.addDot(ithDot);
      ithDot.flock = fnew;
    }
    else {
      for (int j=0; j<i ; j++) {
        Dot jthDot = allDots.get(j);
        Flock jFlock = jthDot.flock;
        PVector jp = jthDot.position;
 
        float dx = ip.x-jp.x;
        float dy = ip.y-jp.y;
        float dh = sqrt(dx*dx+dy*dy);
 
        if (dh > ithDot.radius && dh<ithdot .radius*20) {
 
          float componentInX = dx/dh;
          float componentInY = dy/dh;
          float proportionToDistanceSquared = 1.0/(dh*dh);
 
          float attraction = ithDot.checkCompatibility(jthDot.flock.avgShade);
 
          if (attraction<ithDot.openness*proportionToDistanceSquared*20
          && jFlock.stdev<(30.0*ithDot.openness)) {
            iFlock.removeDot(ithDot);
            jFlock.addDot(ithDot);
 
            ithDot.flock = jFlock;
 
            if (iFlock.flockSize()==0) {
              allFlocks.remove(iFlock);
            }
          }
        }
      }
    }
  }
 
  for (Flock f: allFlocks) {
    f.run();
  }
 
  fill(0,0,0);
  text ("# of Flocks: "  + str(allFlocks.size()), 5,15);
}
 
 
void keyPressed() {
  if (key=='r' || key=='R') {
    allFlocks.clear();
    allDots.clear();
    for (int i=0; i<nDots; i++) {
      float x = random(width);
      float y = random(height);
      float s = random(0, 100);
      Dot d = new Dot(x, y, s, 10);
      allDots.add(d);
    }
  }
}
 
 
class Dot {
  PVector position;
  PVector velocity;
  PVector acceleration;
  float shade;
  float radius;
  float maxforce;
  float maxspeed;
  ArrayList<Dot> group; //prioritized members of group this Dot associates with
  //The following are the Dot's characteristics
  float agreeableness; //probability of going w/ flow of group
  float extraversion; //probability of associating with other Dots
  float openness; //probability of being interested in a different color
  float spontaneity; //probability of randomly going off somewhere
 
  Flock flock;
 
  Dot (float x, float y, float s, float rad) {
    position = new PVector(x, y);
 
    float angle = random(TWO_PI);
    velocity = new PVector(cos(angle), sin(angle));
 
    acceleration = new PVector(0, 0);
 
    shade = s;
 
    radius = rad;
 
    maxspeed = 1.0;
    maxforce = 0.01;
 
    group = new ArrayList<dot>();
    flock = new Flock();
    flock.addDot(this);
 
    agreeableness = random(0, 1.0);
    extraversion = random(0, 1.0);
    openness = random(0, 1.0);
    spontaneity = random(0, 1.0);
 
//    println(str(shade)+"   "+str(openness));
  }
 
  float checkCompatibility (float s) {
    float lower = min(s, shade);
    float higher = max(s, shade);
    float shadeDist = min(higher-lower,(100-higher)+lower);
    float distRatio = abs(shadeDist)/100;
    return distRatio;
  }
 
  void updateFlock(Flock f) {
    flock = f;
  }
 
  void run(ArrayList</dot><dot> dots) {
    flock(dots);
    update();
    handleBoundaries();
    render();
  }
 
  void handleBoundaries() {
    if (position.x > width+radius ) position.x -= width;
    if (position.x < 0-radius     ) position.x += width;
    if (position.y > height+radius) position.y -= height;
    if (position.y < 0-radius     ) position.y += height;
  }
 
  void applyForce (PVector force) {
    acceleration.add(force);
  }
 
  //From Flocking by Daniel Shiffman
  //http://processing.org/examples/flocking.html
  void flock(ArrayList<Dot> dots) {
    PVector sep = separate(allDots);
    PVector ali = align(dots);
    PVector coh = cohesion(dots);
    sep.mult(1.5);
    coh.mult(1.0);
    ali.mult(1.0);
 
    applyForce(sep);
    applyForce(coh);
    applyForce(ali);
  }
 
  // Method to update position
  void update() {
    // Update velocity
    velocity.add(acceleration);
    // Limit speed
    velocity.limit(maxspeed);
    position.add(velocity);
    // Reset accelertion to 0 each cycle
    acceleration.mult(0);
  }
 
  // A method that calculates and applies a steering force towards a target
  // STEER = DESIRED MINUS VELOCITY
  PVector seek(PVector target) {
    PVector desired = PVector.sub(target, position);  // A vector pointing from the position to the target
    // Scale to maximum speed
    desired.normalize();
    desired.mult(maxspeed);
 
    // Steering = Desired minus Velocity
    PVector steer = PVector.sub(desired, velocity);
    steer.limit(maxforce);  // Limit to maximum steering force
    return steer;
  }
 
  // Separation
  // Method checks for nearby dots and steers away
  PVector separate (ArrayList</dot><dot> dots) {
    float desiredseparation = 15.0f;
    PVector steer = new PVector(0, 0, 0);
    int count = 0;
    // For every dot in the system, check if it's too close
    for (Dot other : dots) {
      float d = PVector.dist(position, other.position);
      // If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
      if ((d > 0) && (d < desiredseparation)) {
        // Calculate vector pointing away from neighbor
        PVector diff = PVector.sub(position, other.position);
        diff.normalize();
        diff.div(d);        // Weight by distance
        steer.add(diff);
        count++;            // Keep track of how many
      }
    }
    // Average -- divide by how many
    if (count > 0) {
      steer.div((float)count);
    }
 
    // As long as the vector is greater than 0
    if (steer.mag() > 0) {
      // First two lines of code below could be condensed with new PVector setMag() method
      // Not using this method until Processing.js catches up
      // steer.setMag(maxspeed);
 
      // Implement Reynolds: Steering = Desired - Velocity
      steer.normalize();
      steer.mult(maxspeed);
      steer.sub(velocity);
      steer.limit(maxforce);
    }
    return steer;
  }
 
  // Alignment
  // For every nearby dot in the system, calculate the average velocity
  PVector align (ArrayList</dot><dot> dots) {
    float neighbordist = 50;
    PVector sum = new PVector(0, 0);
    int count = 0;
    for (Dot other : dots) {
      float d = PVector.dist(position, other.position);
      if ((d > 0) && (d < neighbordist)) {
        sum.add(other.velocity);
        count++;
      }
    }
    if (count > 0) {
      sum.div((float)count);
      // First two lines of code below could be condensed with new PVector setMag() method
      // Not using this method until Processing.js catches up
      // sum.setMag(maxspeed);
 
      // Implement Reynolds: Steering = Desired - Velocity
      sum.normalize();
      sum.mult(maxspeed);
      PVector steer = PVector.sub(sum, velocity);
      steer.limit(maxforce);
      return steer;
    }
    else {
      return new PVector(0, 0);
    }
  }
 
  // Cohesion
  // For the average position (i.e. center) of all nearby dots, calculate steering vector towards that position
  PVector cohesion (ArrayList</dot><dot> dots) {
    float neighbordist = 50;
    PVector sum = new PVector(0, 0);   // Start with empty vector to accumulate all positions
    int count = 0;
    for (Dot other : dots) {
      float d = PVector.dist(position, other.position);
      if ((d > 0) && (d < neighbordist)) {
        sum.add(other.position); // Add position
        count++;
      }
    }
    if (count > 0) {
      sum.div(count);
      return seek(sum);  // Steer towards the position
    }
    else {
      return new PVector(0, 0);
    }
  }
 
  void render() {
    fill(shade,100,100);
    ellipse(position.x, position.y, radius, radius);
  }
}
 
 
class Flock {
  ArrayList</dot><dot> dots;
  float avgShade;
  float pcx;
  float pcy;
  float stdev;
 
  Flock() {
    dots = new ArrayList</dot><dot>();
    avgShade = 0;
    pcx = 0;
    pcy = 0;
    stdev = 0;
    allFlocks.add(this);
  }
 
  void updateInfo(){
    float newx = 0;
    float newy = 0;
    int n = dots.size();
    float tempsum = 0;
    float totalShade = avgShade*n;
    for (Dot d: dots) {
      PVector pos = d.position;
      newx+=pos.x;
      newy+=pos.y;
 
      tempsum+=pow((totalShade-d.shade),2);
    }
 
    pcx = newx/dots.size();
    pcy = newy/dots.size();
 
    stdev = sqrt(tempsum/n);
  }
 
  void addDot(Dot d) {
    //Using previous numbers to calculate new avgs for runtime
    int n0 = dots.size();
    float totShade0 = avgShade*n0;
    int n = n0+1;
    float totShade = totShade0+d.shade;
    //Update the avg
    avgShade = totShade/n;
 
    d.updateFlock(this);
    dots.add(d);
  }
 
  void removeDot(Dot d) {
    //Using previous numbers to calculate new avgs for runtime
    int n0 = dots.size();
    float totShade0 = avgShade*n0;
    int n = n0-1;
    float totShade = totShade0-d.shade;
    //Update the avg
    avgShade = totShade/n;
 
    dots.remove(d);
  }
 
  int flockSize() {
    return dots.size();
  }
 
  void run() {
    for (Dot d: dots) {
      d.run(dots);
    }
  }
}
</dot></ithdot></i></ndots></dot></flock></dot></flock>

Portrait(s) in a Projected Creature

Nervous from Chloe Chia on Vimeo.

In the rush of things, I seem to have forgotten a few things. 1) The ability for art to elegantly express that which is hard to express, 2) the ability for art in catharsis, and 3) reaching out to people when in need of help.

WP_001713

I originally had numerous separate ideas for the assignments, but after numerous iterations and talk of being ‘poetic’, I realized that this creature that I made–originally intended to be a “live stress ball”–could have so much more meaning when placed into context. Especially if that context is my own studio in the Design school. Lately, I have been feeling very nervous in general about all of my classes, ever so precariously keeping the balance between them, outside activities, and mental states. The stress of it can be overwhelming, and leave one feeling very trapped as I do now.

WP_001715WP_001714

But in the process of making the video, and watching my own creature almost ‘come to terms’ with his confines, I can’t help but wonder whether or not such stress and pressure that I feel is merely an artificial boundary I place upon myself. It is up to me to figure out, given the limitations upon my skills and my time, what am I capable of doing, rather than focusing just on the limits and failures.

WP_001718

This is definitely the same sort of thinking with which I approached these assignments, keeping it as simple as possible, and working with the code that I’m most comfortable with. On the programming end, there are still many things I would like to fix later on as I get more and more fluent in Processing. One of those things includes figuring out how to get the creature attracted to the mouse, since at the moment a mouse press only activates a different gravity vector (which, I admit, I modified throughout the process of filming). I couldn’t quite figure out how to recall each node that creates the spring skeleton of the creature…

WP_001717

Unfortunately Javascript mode doesn’t seem to like my sketch and refuses to run in the OpenProcessing applet… Will have to figure out how to work that kink.

 

Buzz – Slurp

I began this project with a simple question in mind, how could I simulate a living creature? I thought about making something that would expand and deflate to simulate breathing. The simplest thing was to plug some eyes onto a shape, as Golan pointed out to me.By making it blink once in a while, the object becomes alive. My thoughts wandered and eventually landed on food. Creatures all need to eat right? So I started to formulate a critter that would devour another critter. I wanted to make something approachable, entertaining, and different from my previous projects.

After some quick sketches, I decided to create a baby chameleon-like creature, named Camel.

camel_2

camel_3

camel_4

camel1

I wanted to give my creature an environment where he could live, but it would have to be contained enough so he wouldn’t escape. The first thought that came into mind was just to make a simple boxed out area on the canvas so he wouldn’t be able to step out of the border. Simple enough right? However, I felt like that didn’t depict the life of a chameleon. A chameleon is a slow careful creature that spends most of its life up in the tree tops, catching bugs. I thought that this type easy-going lifestyle needed a fluid shape that would represent something soft, without extreme changes.

Furthermore, I wanted to describe a cycle in life. When the fly would buzz around the chameleon, within a certain range of Camel’s vision, he would reach out for the fly with his tongue. But Camel is still a baby, so sometimes the fly would get away when it twitches violently enough. The viewer can also chose to help out Camel catch the fly. The fly naturally wants to run away from anything coming towards it, so if you push scare it in the right direction, Camel will be able to eat it.

 

The Wind Walker

The Wind Walker likes to use his head to feel for subtle variations in wind currents. He moves if he feels uncomfortable or bored.

Play with the Wind Walker on OpenProcessing (requires Java)

Behavior is more important than visual realism in creating the illusion of life. We observe this in Karl Sims’ “Evolved Virtual Creatures”, a simulation in which evolved box creatures interact with their environment in surprising and often humorous ways.

With this principle in mind, I sought to invent a charming creature with lifelike mannerisms. I drew inspiration from two sources: the dutch artist Theo Jansen, and the Kikkerland line of Wind Up Toys.

A wind-powered Strandbeest (Dutch: strand = beach) roams a beach
A charming toy that teaches children about the perils of the adult world

I wrote a custom spring system based on Hooke’s Law to control his limbs, and the sketch runs using the P3D renderer. It is interactive in a limited sense – if one clicks, the Wind Walker turns to face the mouse.

img001
Preliminary sketches with greasy fingers

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; } }

Ticha-Do you hear the birdie sing

My creature ended up not being an abstract or fantastical mystical one, but a relatively normal-looking robin that responds to the user’s voice. Lately, I’ve been doing a lot of work with the AudioInput library in processing because of the level of interactivity it offers between the user and the program. As someone who grew up in a musically oriented environment, I strongly believe that music is one of the best methods of bonding individuals. Thus, I created a robin that responds to singing but runs away when the input audio level exceeds a certain threshold. At the certain point, the robin will start to dance and even sing along once it has gained enough of the user’s trust.

I admit that I am still not completely satisfied with this project – I had spent so much time on trying to make the audio work and handling awkward boolean logic that I was not able to make the simulation as sophisticated as I wanted it to be. Nevertheless, this was a very valuable learning experience for me as it forced me to reason about my code more carefully and reacquainted me with good ol’ null pointer exceptions.

Dropbox link for the code because OpenProcessing hates me: https://www.dropbox.com/s/m1pbwk68zsvgkzz/singing_bird.zip

Ralph-Assignment-07-Life

20131017_082320

This piece is a simple evolution simulator. I was inspired by my complete bafflement at the Evolution vs Creationism “debate” in the United States. I could not understand how such a simple logic behind the concept of evolution was so difficult to understand for so many people, so I created a created a very basic emulation of it. The reference in this piece is the pepper moth case, where a population of species of moth near London clearly changed color depending on the pollution level. Similarly, the finches in the simulation has a higher probability of eating a moth that has greater contrast with the background. The speed of the simulation and the shade of the tree is also adjustable by the user, so there’s no bullshit going on here.