Thursday, February 28, 2008

Mobile Medi(a) Midterm

For our midterm, Yasmin and I began prototyping a way for
inmates to quickly and easily audioblog, using Asterisk.
Shawn Van Every provided sagacious advice and his
own special brand of humor along the way.



Blogging From Behind Bars
http://itp.nyu.edu/~mt245/freedom/freedom.php




One of the first things I've discovered in my research is that one of the biggest fears that prisoners face is the fear of being forgotten. By setting up an easy and completely free interface for prisoners to publish audio on the web, we are creating a way for them to maintain their presence in the outside world, to communicate with more friends and family than they otherwise would, to document the hardships of prison life, and to preserve these posts for posterity.

A good friend of ours, Shaina Feinberg, has been spearheading this project for RapHappy, and she's discovered some interesting stuff. One of the things she came across is the following site, which contains blogs purportedly by people in correctional facilities. There is some real powerful stuff in here, even though the comments are all spam:

http://prisonblogs.net/drupal/


But not all prisoners have access to computers, much less the know-how and inclination to publish a blog. One thing all prisoners do have, however, is the infamous PHONE CALL.


PHONES AND PRISONS

----or so I'd thought, but Shaina found out something important: Higher-security prisons don't actually allow for access to telephones. To do this project at all, we will have to focus on medium- and lower-security prisons. Here's a map of the different prison facilities, color-coded by security level, here in New York State:


http://www.docs.state.ny.us/facilitymapcolor.pdf


Shaina discovered another important thing, which is that in recent years prisoners have been smuggling LOTS of cellphones into jail. At one point, apparently, some 75% of prisoners had access to cellphones. Which means that, if we are going to do this project, we have to make it very clear that all phone calls we receive are coming from authorized prison payphones, not from any illicit cellphones. Prisoners need to feel safe using our service.


HOW THE PRISON PHONE SYSTEM WORKS

As it happens, prisons are like universities (and vice-versa :))---each is run totally differently. In one prison, inmates may only be allowed to RECIEVE calls at preappointed times; at another, inmates may be charged such exorbitant fees that making phone calls is an impossibility.

The New York State DEPT of Corrections list rules for phone usage on their website:

An inmate is only permitted to call persons on their approved telephone list and may only have up to 15 telephone numbers on their approved list at any time. Phone numbers may only be added or deleted at the request of the inmate. This is generally done on a quarterly basis when the inmate meets with his or her assigned Correction Counselor. If, however, you do not wish to receive telephone calls from an inmate, you need to notify the facility, in writing, and your name will be entered on the inmate's Negative Correspondence and Telephone List. The inmate will be immediately notified in writing that you have been removed from his/her "Telephone List" and that disciplinary action may be taken if the telephone is used in any manner to contact you. In addition, your telephone number will be removed from the telephone system.



I asked Shaina to inquire about the possibility of using call-forwarding to get around this limitation, and the response was that call forwarding is PROHIBITED. How, I'm not sure.

I had also been wondering about the possibility of using an 800-number, so prisoners wouldn't have to pay the extreme prices that prisons of charge them. But the NYS Corrections website was clear about this:

Inmate telephone calls and telephone conversations are restricted to the telephone number dialed or otherwise placed by or for the inmate. Telephone call forwarding, third party phone calls, and calls to 1-800 numbers are prohibited. Inmates are also prohibited from placing calls to wireless communication devices (i.e., cellular or PCS phone, pagers, etc.). Inmates will be subject to disciplinary action should they violate these rules.



Finally, and due to the bad influence of Shawn Van Every's mobile classes, I considered setting up a conference call application for inmates. This would allow them to talk to all of their friends at once, maximizing the interactions they get with their allotted phone time.

This, I was told, would be illegal.


INTERFACE/EASE OF USE

Aside from avoiding 800 numbers and conference calls, there was another important caveat to consider. Namely: the application will have to be very easy to use. If long telephone menu systems frustrate you, imagine how an inmate feels, when their precious telephone minutes are ticking away.

This poses an interesting challenge:

Because our application is an audio blog, users will each be given their own unique page with a private url (http://raphappy.com/username/). Hence, some sort of login process is necessary. In our prototype, we ask users to spell their user name out loud, and then enter a 4-digit pin. This is relatively quick and easy, but there's bound to be a better solution out there.


TECHNOLOGY

Our audio blogging application utilizes ITP's Asterisk server along with a voice-parsing service called LumenVox. AGI scripts allow us to query RapHappy's database for users' information, log new information, and to move audio off the school's Asterisk server and onto a web server, where people can hear it.


PRELIMINARY CONCLUSIONS

While making the actual application didn't pose too much of a challenge, overcoming the bureaucratic obstacles to our project will take some time. At his point it looks like I will need to take the following steps:

1) Purchase DID numbers that are in the same local area as prisons, setting up a cheaper (free, ideally) way for prisoners to call loved ones, as well as audio blog.

2) Find a way around the "Call List" regulations. Shaina has been looking into this, and says that we can actually probably pull this off, if we go through a proper prison advocacy organization.

3) Start small. We are beginning with just 5 bloggers from a women's prison in upstate New York. If they and their loved ones appear to enjoy the service, then they will be great advertisement for getting our service approved in other prisons.

Hopefully within the next month or so we can figure out whether audio blogging is the sort of service that inmates would be willing to use. We also look forward to getting feedback on our phone system's ease of use. I'm sure some people will complain about the login process---hopefully we can conjure up a simpler and easier way to do this.

Friday, February 1, 2008

Thursday, January 31, 2008

Mobile Media Week 1

So here's a really cool SMS service that I found, called U R N A-hole:
http://itp.nyu.edu/~mtf245/ubicomp/

Coincidentally, I found it in my own folder on ITP's server. I made it using a mail parsing script almost identical to the one Shawn gave us. So let this be an example of the limitless SMS miracles you can achieve with a popper and a kron job. I wish I remembered to use this more often, because my life is rife with a-holes.

From the site:
"Just snap a photo of any old asshole with your cellphone and text it to urnahole@gmail.com with a message explaining why they are such an asshole. It'll show up here, completely anonymous, except for the fact that they probably saw you pointing your cellphone at them and taking a picture without asking, asshole."

Wednesday, January 23, 2008

Thursday, December 13, 2007

Redial Final:::Jabberjockeys

INTRODUCTION


Jabberjockeys consist of a pair of underwear (one male, one female) which discreetly inform a partner when the other gets aroused. By sensing subtle changes in temperature, moisture and pressure the undergarments detect arousal. The underwear automatically notifies the partner by activating vibrating motors sewn into the fabric of their underwear, thus enabling them to discreetly share their heightened emotions.

Sexual arousal is a personal state; but one that is most satisfyingly experienced with a partner. If a person becomes aroused in a public setting, it is difficult to notify their partner of their arousal without creating a disturbance. This project aims to solve this dilemma by providing a discreet and effective way for couples to share their spontaneous and private compulsions.

Jabberjockeys employs a whole hodgepodge of languages in getting two pairs of inanimate underwear to communicate in any sort of articulate manner. These languages are, to wit: Asterisk, Arduino, Java, Python, and good old-fashioned HTML.


(arranging circuits for the panties and boxer briefs)



ASTERISK



I will begin with the Asterisk dialplan, which is of most interest to people in Shawn Van Every's Redial class.

Essentially, this code does two major things:

1) It reads users' keypresses and sends this information to the woman's phone. Since her panties have four motors in them, a user will press the motor number (1-4) followed by the intensity of vibration (0-4). If a user wants to turn all of the motors on or off at once, they can press 5 followed by the intensity level (0-4).

2) It runs an EAGI script that will analyze the user's voice and cause the panties to vibrate accordingly. Quiet encouragement will cause the panties to purr subtly. More vociferous input will cause the panties to hum enthusiastically. Silence will make them stop altogether.

The Asterisk dialplan is a follows:



exten => s,1,Wait(2);
exten => s,2,Answer();
exten => s,3,Playback(beep);
exten => s,4,WaitExten(300);
exten => 10,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=A"); This CURLs a Python script on the phone.
exten => 10,2,Goto(mtf245,s,3);
exten => 11,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=B");
exten => 11,2,Goto(mtf245,s,3);
exten => 12,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=C");
exten => 12,2,Goto(mtf245,s,3);
exten => 13,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=D");
exten => 13,2,Goto(mtf245,s,3);
exten => 14,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=E");
exten => 14,2,Goto(mtf245,s,3);
exten => 20,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=F");
exten => 20,2,Goto(mtf245,s,3);
exten => 21,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=G");
exten => 21,2,Goto(mtf245,s,3);
exten => 22,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=H");
exten => 22,2,Goto(mtf245,s,3);
exten => 23,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=I");
exten => 23,2,Goto(mtf245,s,3);
exten => 24,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=J");
exten => 24,2,Goto(mtf245,s,3);
exten => 30,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=K");
exten => 30,2,Goto(mtf245,s,3);
exten => 31,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=L");
exten => 31,2,Goto(mtf245,s,3);
exten => 32,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=M");
exten => 32,2,Goto(mtf245,s,3);
exten => 33,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=N");
exten => 33,2,Goto(mtf245,s,3);
exten => 34,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=O");
exten => 34,2,Goto(mtf245,s,3);
exten => 40,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=P");
exten => 40,2,Goto(mtf245,s,3);
exten => 41,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=Q");
exten => 41,2,Goto(mtf245,s,3);
exten => 42,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=R");
exten => 42,2,Goto(mtf245,s,3);
exten => 43,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=S");
exten => 43,2,Goto(mtf245,s,3);
exten => 44,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=T");
exten => 44,2,Goto(mtf245,s,3);
exten => 50,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=U");
exten => 50,2,Goto(mtf245,s,3);
exten => 51,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=V");
exten => 51,2,Goto(mtf245,s,3);
exten => 52,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=W");
exten => 52,2,Goto(mtf245,s,3);
exten => 53,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=X");
exten => 53,2,Goto(mtf245,s,3);
exten => 54,1,System(curl "https://fargo.mymobilesite.net/lob/lob.py?name=Y");
exten => 54,2,Goto(mtf245,s,3);
exten => 6,1,EAGI(/home/mtf245/asterisk_agi/runMe.sh); Pointing to shell script with EAGI
exten => 6,2,Goto(mtf245,s,3);
exten => i,n,Goto(mtf245,s,3); Loops back for next input
exten => t,n,Goto(mtf245,s,3);




(extensive research went into choosing vibrator locations)



JAVA EAGI


The Java EAGI script called from the dialplan is essentially the same code as that in Shawn's tutorial, with a couple subtle changes. The script essentially listens to the audio stream coming from the users phone and analyzes its volume. A louder average will make the panties vibrate harder, while a softer volume makes the vibrate gentler. My additions are as follows:

1) For smoother numbers, and because the Python script on the woman's phone can only handle one request every few seconds, I am re-averaging the numbers we get. I also upped the frequency it reads from the audio stream to intervals of 100 milliseconds, for greater accuracy.

2) Every 6 seconds or so, Java makes an HTTP request to the phone, sending it data that corresponds to the intensity of the user's voice. While we simply used a CURL to do this in Asterisk, we are using a regular HTTP request with GET data, here.

The additional code is as follows:



class ReadingThread implements Runnable
{
public void run()
{
try
{
int cnt = 0;
int loopcnt = 0;
long totalavg = 0;
int totaltotal;
while (audioLoop)
{
byte[] inputBytes = new byte[8000];
int readBytes = 0;

readBytes = ais.read(inputBytes);

int avg = 0;
long total = 0;
for (int i = 0; i < readBytes; i++)
{
total += unsignedByteToInt(inputBytes[i]);
}
avg = (int)(total/readBytes);

// now re-average
loopcnt++;
totalavg+=avg;

if (loopcnt > 98) {
totaltotal = (int)(totalavg/100);
char param = 'U';
if (totaltotal < 8) {
param ='U';
}
else if (totaltotal < 15) {
param ='V';
}
else if (totaltotal < 22) {
param ='W';
}
else if (totaltotal < 30) {
param ='X';
}
else {
param ='Y';
}

try {
// script we are hitting is https://fargo.mymobilesite.net/lob/lob.py?name=XXX
// Construct data
client.send("******** TOTAL AVG: "+totaltotal);
java.net.URL url = new java.net.URL("https://fargo.mymobilesite.net/lob/lob.py?name="+param);
HttpURLConnection m_con = (HttpURLConnection)url.openConnection();
System.out.println(m_con.getResponseMessage());
m_con.disconnect();

} catch (Exception e) {
client.send("ERROR MAKING HTTP REQUEST");
}

// reset loop
loopcnt = 0;
totalavg = 0;
totaltotal = 0;

}

/* for testing
String stemp = Integer.toString(avg);
fsos.write(stemp + " ");
if (cnt%10 == 0)
{
fsos.write("\n");
fsos.flush();
}
*/

Thread.sleep(100);
}
}
catch (IOException ioe)
{
System.out.println("Bad bad");
ioe.printStackTrace();
}
catch (InterruptedException ie)
{

}
}

int unsignedByteToInt(byte b) {
return Math.abs((int)b);
}
}




(relentless user-testing puts our panties to the test)



PYTHON


In the above dialplan and Java EAGI, we are sending data to a Python script on the woman's phone. The woman's phone is a Nokia N-95, which happens to be running its own Apache web server. Nokia has dubbed this Mobile Web Server, and it makes all sorts of projects like this really easy to do.

The Python script I wrote sits in a public directory on this server, and can be hit from any browser. So you could actually just manipulate the panties from your web browser, if you wanted. The URL is:
https://fargo.mymobilesite.net/lob/lob.py?name=XXX
where XXX is the motor/level desired for vibration.

The Python script connects to a BlueSmirf bluetooth device that has been embroidered into panties. After making a connection, it can be re-run as many times as you want with new GET data. When the script gets data, it relays this data on to the panties, where an Arduino Lilypad microcontroller has been pre-programmed to interpret this data and vibrate the motors accordingly.

The Python script is as follows:



MAIN_TMPL = "plain.psp"
FORM_TMPL = "form"

# define request handler
def handler(req):
hrh = HRHandler()
result = hrh.handler(req)
del hrh
return result

class HRHandler(object):
def __init__(self):
pass

def handler(self, requ):
self.req = self.parse_args(requ)
args = self.req.get_vars
try:
name = str(args['name'])
except KeyError:
name = None
title = ''
if name != None:
title = 'You just entered, ' + name
global sock
sock.send(name)
else:
title = 'Enter a number'
global sock
sock=socket.socket(socket.AF_BT,socket.SOCK_STREAM)
SparkAddress = "00-a0-96-1b-27-46"
target=(SparkAddress,1)
sock.connect(target)
content = ''
contentFromFile = open((apache.server_root() + '/htdocs/lob/' + TMPL_DIR + '/' + FORM_TMPL+'.html'), 'r')
temp = contentFromFile.readlines()
contentFromFile.close()
for line in temp:
content += line + '\n'

requ.content_type = 'text/html; charset=UTF-8'
requ.html_head = ''
requ.html_body_attr = ''

fname = TMPL_DIR + '\\' + MAIN_TMPL
template = psp.PSP(requ, filename = fname)
template.run({'content':content, 'html_head':requ.html_head, 'html_body_attr':requ.html_body_attr, 'title':title})

del template
return apache.OK

def parse_args(self, req):
req.get_vars = {}
try:
if req.args:
temp = req.args.split('&')
for arg in temp:
arg = arg.split('=')
req.get_vars[arg[0]] = arg[1]
except IndexError:
pass
return req

def sendbt(val):
global sock
sock.send(val)


The "form" file included at the beginning of the script is actually an HTML template with a form for inputing and submitting data from a browser.



(the Lilypad Arduino is connected to vibrators)



ARDUINO


The Arduino code is the heart and soul of Jabberjockeys. It assigns digital pins to their respective motors, then waits for input from the BlueSmirf. Then it turns on and off certain motors with a long, inelegant set of conditional statements. You can ignore the variables for galvanic skin response, since we haven't yet added this feature:


int galvanicPin = 0; // select the input pin for the galvanic
int galvanicVal = 0; // variable to store the value coming from the sensor
int galvanicThresh = 700;
int motorPin[] = {6,9,10,11};
int motorValue = 1024;
int potPin = 5; //for testing
int potValue = 1024;
char inByte = ' ';
//int connectionStatus = 0;
int motor1Status = 0;
int motor2Status = 0;
int motor3Status = 0;
int motor4Status = 0;

void setup() {
Serial.begin(57600);
pinMode(6, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
}

void loop() {
readRespondSensor();
// setMotorValue();
buttonCheck();
// printValues();
delay(100);
}

void readRespondSensor(){
galvanicVal = analogRead(galvanicPin); // read the value from the sensor
if (galvanicVal > galvanicThresh){
// Serial.println("THIS IS WHERE WE CALL THE SCRIPT FOR THE OTHER UNDERWEAR");
}
}

void buttonCheck() {
if (Serial.available()) {
inByte = Serial.read();
if (inByte == 'A') {
digitalWrite(motorPin[0],LOW); // turn off motor
motor1Status = 0;
}
else if (inByte == 'B') {
analogWrite(motorPin[0],64); // determine voice levels and vary strenth of motor
motor1Status = 1;
}
else if (inByte == 'C') {
analogWrite(motorPin[0],128); // determine voice levels and vary strenth of motor
motor1Status = 2;
}
else if (inByte == 'D') {
analogWrite(motorPin[0],192); // determine voice levels and vary strenth of motor
motor1Status = 3;
}
else if (inByte == 'E') {
analogWrite(motorPin[0],255); // determine voice levels and vary strenth of motor
motor1Status = 4;
}
else if (inByte == 'F') {
digitalWrite(motorPin[1],LOW); // turn off motor
motor2Status = 0;
}
else if (inByte == 'G') {
analogWrite(motorPin[1],64); // determine voice levels and vary strenth of motor
motor2Status = 1;
}
else if (inByte == 'H') {
analogWrite(motorPin[1],128); // determine voice levels and vary strenth of motor
motor2Status = 2;
}
else if (inByte == 'I') {
analogWrite(motorPin[1],192); // determine voice levels and vary strenth of motor
motor2Status = 3;
}
else if (inByte == 'J') {
analogWrite(motorPin[1],255); // determine voice levels and vary strenth of motor
motor2Status = 4;
}
else if (inByte == 'K') {
digitalWrite(motorPin[2],LOW); // turn off motor
motor3Status = 0;
}
else if (inByte == 'L') {
analogWrite(motorPin[2],64); // determine voice levels and vary strenth of motor
motor3Status = 1;
}
else if (inByte == 'M') {
analogWrite(motorPin[2],128); // determine voice levels and vary strenth of motor
motor3Status = 2;
}
else if (inByte == 'N') {
analogWrite(motorPin[2],192); // determine voice levels and vary strenth of motor
motor3Status = 3;
}
else if (inByte == 'O') {
analogWrite(motorPin[2],255); // determine voice levels and vary strenth of motor
motor3Status = 4;
}
else if (inByte == 'P') {
digitalWrite(motorPin[3],LOW); // turn off motor
motor4Status = 0;
}
else if (inByte == 'Q') {
analogWrite(motorPin[3],64); // determine voice levels and vary strenth of motor
motor4Status = 1;
}
else if (inByte == 'R') {
analogWrite(motorPin[3],128); // determine voice levels and vary strenth of motor
motor4Status = 2;
}
else if (inByte == 'S') {
analogWrite(motorPin[3],192); // determine voice levels and vary strenth of motor
motor4Status = 3;
}
else if (inByte == 'T') {
analogWrite(motorPin[3],255); // determine voice levels and vary strenth of motor
motor4Status = 4;
}
else if (inByte == 'U') {
analogWrite(motorPin[0],LOW); // determine voice levels and vary strenth of motor
analogWrite(motorPin[1],LOW); // determine voice levels and vary strenth of motor
analogWrite(motorPin[2],LOW); // determine voice levels and vary strenth of motor
analogWrite(motorPin[3],LOW); // determine voice levels and vary strenth of motor
}
else if (inByte == 'V') {
analogWrite(motorPin[0],64); // determine voice levels and vary strenth of motor
analogWrite(motorPin[1],64); // determine voice levels and vary strenth of motor
analogWrite(motorPin[2],64); // determine voice levels and vary strenth of motor
analogWrite(motorPin[3],64); // determine voice levels and vary strenth of motor
}
else if (inByte == 'W') {
analogWrite(motorPin[0],128); // determine voice levels and vary strenth of motor
analogWrite(motorPin[1],128); // determine voice levels and vary strenth of motor
analogWrite(motorPin[2],128); // determine voice levels and vary strenth of motor
analogWrite(motorPin[3],128); // determine voice levels and vary strenth of motor
}
else if (inByte == 'X') {
analogWrite(motorPin[0],192); // determine voice levels and vary strenth of motor
analogWrite(motorPin[1],192); // determine voice levels and vary strenth of motor
analogWrite(motorPin[2],192); // determine voice levels and vary strenth of motor
analogWrite(motorPin[3],192); // determine voice levels and vary strenth of motor
}
else if (inByte == 'Y') {
analogWrite(motorPin[0],255); // determine voice levels and vary strenth of motor
analogWrite(motorPin[1],255); // determine voice levels and vary strenth of motor
analogWrite(motorPin[2],255); // determine voice levels and vary strenth of motor
analogWrite(motorPin[3],255); // determine voice levels and vary strenth of motor
} else {
for (int i=0; i <= 3; i++){
digitalWrite(motorPin[i], LOW);
}
}
}
}


void setMotorValue () {
//potValue = analogRead(potPin);
motorValue = potValue;
}

void printValues(){
Serial.print("galvanicVal = ");
Serial.print(galvanicVal);
Serial.println();
// Serial.print("connectionStatus = ");
// Serial.print(connectionStatus);
Serial.println();
Serial.print("motor1Status = ");
Serial.print(motor1Status);
Serial.println();
Serial.print("motor2Status = ");
Serial.print(motor2Status);
Serial.println();
}

Tuesday, October 30, 2007

Midterm: Earwigs and Oriental Produce in the Year 2078



The idea from this actually comes from fairly classical sources. I was holed up in the apartment, huddled over a pot of Japanese nabemono, trying to warm myself with the steam rising off the boiling daikon and lamenting the passing of summer in general when that classic Basho verse came leaping into my head:



身にしみて大根からし秋の風



Indeed, these daikon that would soon be warming my belly were themselves a timeless symbol of the fall harvest. I was also reminded of the little monk-in-training in Basho's subsequent (and much more evocative) verse:



鞍壷に小坊主のせて大根引



To me, this little blue-headed rascal has always given me images of the selfsame boy, riding a daikon like a rocketship--or like Kubrick's Strangelove straddling his beloved bomb.




From there is was no small jump to a distopian future in which the frequently incosistent systems of English nomenclature applied to oriental produce in the world's supermarkets wreaked havok on civilian earwig populations. That, in a nutshell, is basically where the idea for this game comes from.





The application was built entirely in Flash Lite 2.0. My process involved several trips to Chinatown, where I would peruse the produce, thinking about their warp and contour, trying not to bruise them in the fondling. Then I would return home and attempt to reproduce my feelings about my encounters with the myriad tubers and vegetables Mott Street. Once I had satisfactory renderings of produce, I would load them into Flash and animate them with Actionscript.



Moving the earwig according to its velocity and angle required me to use some strange operators called "sine" and "cosine" that I had not encountered since the spring of my second year in middle school. It's strange how something you thought would never be necessary in life can come back to haunt you like a bamboo root in the year 2078.



Like real earwigs in nature, the earwig in my game has 5 lives. Also, it crawls in your ear while you sleep and uses its pincher to sever important synapses and neurons and vessels.

Tuesday, October 2, 2007

moblogging is fo suckaz





Free photo blogging from your mobile at mobblog.it