//*********************************// //********Save Your Brains*********// //USC Mobile Media Project*********// //***************Fall 2003*********// //*********************************// // declaring a global variable to hold an array of Zombie objects Zombie[] zombies; //creating a global variable for player of type Human Human player; //instantiate a GPS class P5gps gps; //number of zombies int zombieCount = 100; //define the size of the stage int stage_x = 640; int stage_y = 480; //player will start from the middle float start_x = stage_x/2; float start_y = stage_y/2; //vars for mobile lab field (btw, when I was playing last night, this was jacked...) float x_min = -118.27933 -(.00447/4); float x_max = -118.27933 + (.00447/4); float y_min = 34.02918 - (.00647/4); float y_max = 34.02918 + (.00647/4); //vars for usc field //float x_min= -118.28689; //float x_max = -118.28242; //float y_min = 34.01852; //float y_max = 34.02499; //text stuff boolean printText = false; BFont creepy; void setup() { //stage size size(stage_x, stage_y); //load a font creepy = loadFont("Meta-Bold.vlw.gz"); //make a new P5gps object gps = new P5gps(4800, "$GPRMC"); // creating an (empty) array with capacity zombieCount zombies = new Zombie[zombieCount]; //create the player player = new Human(); player.x = start_x; player.y = start_y; player.w = 3; player.h = 3; //makes an empty array of previous x,y positions of size 5 for (int lmn = 0; lmn < 5; lmn++) { player.last_y[lmn] = 0; player.last_x[lmn] = 0; //print(player.last_x); } // populating the array with Zombies for (int i = 0; i < zombieCount; i++) { zombies[i] = new Zombie(); //TAF added... //makes sure that zombies aren't created on top of the player boolean validSpot = false; while (validSpot == false) { zombies[i].x = random(0, width); zombies[i].y = random(0, height); //float diffPosition = abs(zombies[i].x - player.x); if (abs(zombies[i].x - player.x) > 80 || abs(zombies[i].y - player.y) > 80) { validSpot = true; } } //...to here //makes zombies all 2X2 pixels zombies[i].w = 2; zombies[i].h = 2; } } void loop() { //refresh background(150); updateInterface(); //zombies move about for (int i = 0; i < zombieCount; i++) // iterating 33 times { zombies[i].hangOut(); } //human moves too //comment out the gpsPosition function line to control player with keys w, s, d, a //player.gpsPosition(); player.drawHuman(); } // TAF - game over function void game_over() { boolean gameOvered = true; background(150); while (gameOvered) { if (mousePressed) { gameOvered = false; } } } void serialEvent() { //get a new collection of gps data gps.processNMEA((char)serial); } //TAF, updates score, etc. void updateInterface () { fill(255,50,50,255); textFont(creepy, 44); text("Time: ", 15, 50); int score = millis()/1000; text(score, 100,50); } //lets player move around if not getting GPS data void keyPressed() { for (int lmn = 4; lmn > 2; lmn--) { player.last_y[lmn] = player.last_y[lmn - 1] ; player.last_x[lmn] = player.last_x[lmn - 1] ; //print(player.last_x); } player.last_x[0] = player.x; player.last_y[0] = player.y; if (key == 'w') { player.y-=2; } if (key == 's') { player.y+=2; } if (key == 'd') { player.x+=2; } if (key == 'a') { player.x-=2; } } //***Zombie Class***************************************************// //***hunt(), wander(), hangOut(), setTarget(), drawZombie()*********// class Zombie { //declare vars float x, y, w, h, tx, ty, delta_x, delta_y, xSpeed, ySpeed; float randomWalkDistance, randomWalkDirection; //TAF: walkDirection: 1-4, walkDistance is how far to walk float speedScalar = 0.3; //TAF Speed vector is multiplied by, increase to make zombies hunt faster //goes after the player's position as defined by setTarget() void hunt() { delta_x = abs(x-tx); delta_y = abs(y-ty); if(delta_x>delta_y) { xSpeed = speedScalar; //TAF ySpeed = speedScalar*(y/x); //TAF } else { ySpeed = speedScalar; xSpeed = speedScalar*(x/y); } setTarget(player.x, player.y); if (tx>x) { x = x + xSpeed; } else { x = x - xSpeed; } if (ty>y) { y = y + ySpeed; } else { y = y - ySpeed; } drawZombie(); } //TAF - zombie wanders around, moving in a random direction for a random distance void wander(){ if (randomWalkDistance < 1)//find new distance if zombie reach the end of the walk { int walkDirection = (int)(random(4)); randomWalkDistance = (float)(random(30) + 1); randomWalkDirection = (float)walkDirection; } if (randomWalkDirection == 0) { x--; randomWalkDistance = randomWalkDistance - 1.0; } if (randomWalkDirection == 1) { x++; randomWalkDistance = randomWalkDistance - 1.0; } if (randomWalkDirection == 2) { y--; randomWalkDistance = randomWalkDistance - 1.0; } if (randomWalkDirection == 3) { y++; randomWalkDistance = randomWalkDistance - 1.0; } } //zombie wanders around, and waits until within a range to hunt player void hangOut() { //set the x,y target as the human setTarget(player.x, player.y); //calculate the delta x, y delta_x = tx-x; delta_y = ty-y; //determine distance from player based on hypoteneuse (c) float a_squared = sq(delta_x); float b_squared = sq(delta_y); float c = sqrt(a_squared+b_squared); //check distance (if we are close, then hunt, if we are far, then don't if (c>80) { drawZombie(); wander(); } else { hunt(); if (c < 5){ fill(255, 20, 20); rect(0, 0, width, height); //game_over(); } } } //sets the target for the zombie to chase (current player position) void setTarget(float xin, float yin) { tx = xin; ty = yin; } //draws out zombie dot void drawZombie() { ellipseMode(CENTER_RADIUS); fill(150, 0, 0, 50); ellipse(x, y, w, h); } } //end of Zombie class //***Human Class*****************// //***gpsPosition(), drawHuman()**// class Human { //define vars float x, y, w, h, xSpeed, ySpeed, curr_x, curr_y; boolean alive; //TAF float[] last_x = new float[5]; float[] last_y = new float[5]; //gets the GPS data and translates it to a pixel value as defined by the stage parameters void gpsPosition() { last_x[0] = x; last_y[0] = y; curr_y = gps.latitude(); curr_x = gps.longitude(); x = ((curr_x - x_min)/(x_max - x_min)) * stage_x; y = ((curr_y - y_min)/(y_max - y_min)) * stage_y; //print("x: "+x); //print("y: "+y); } //draws the human dot void drawHuman() { ellipseMode(CENTER_RADIUS); fill(0, 255, 255, 255); ellipse(x, y, w, h); /* noStroke(); for (int opq = 0; opq < 5; opq++) { ellipseMode(CENTER_RADIUS); fill(0, 255, 255, 255); ellipse(last_x[opq], last_y[opq], w, h); } */ stroke(0,0,0); } } //end of Human class //***GPS code for Processing*****************// //***Glen Murphy, glen@glenmurphy.com********// class P5gps { private boolean locked = false; private boolean available = false; private String latitude; // ddmm.mmmm private String longitude; // ddmm.mmmm private int north; private int east; private String knots; private String heading; private String altitude; // metres private String nmea; private String nmeaType; P5gps(int rate, String nmeaTypeIn) { beginSerial(rate); nmeaType = nmeaTypeIn; } void processNMEA(char nmeaIn) { nmea += nmeaIn; if(nmeaIn == '\n') { String dataBlock[] = splitStrings(nmea, ','); if(dataBlock[0].equals(nmeaType)) { if(nmeaType.equals("$GPRMC")) { latitude = dataBlock[3]; north = (dataBlock[4].equals("N")) ? 1 : -1; longitude = dataBlock[5]; east = (dataBlock[4].equals("E")) ? 1 : -1; knots = dataBlock[7]; heading = dataBlock[8]; locked = dataBlock[2].equals("A") ? true : false; } else if (nmeaType.equals("$GPGGA")) { latitude = dataBlock[2]; north = (dataBlock[3].equals("N")) ? 1 : -1; longitude = dataBlock[4]; east = (dataBlock[5].equals("E")) ? 1 : -1; locked = (Integer.valueOf(dataBlock[6]).intValue() > 0) ? true : false; altitude = dataBlock[9]; } available = true; } nmea = ""; } } float minutesToDegrees(float dm) { return (int)(dm / 100) + (dm - ( (int)(dm/100) ) * 100) / 60; } float latitude() { if(!available) return 0; // convert from ddmm.mmmm to dd.dddddd return minutesToDegrees(Float.valueOf(latitude).floatValue()) * north; } float longitude() { if(!available) return 0; // convert from ddmm.mmmm to dd.dddddd return minutesToDegrees(Float.valueOf(longitude).floatValue()) * east; } float velocity() { if(!available) return 0; // return velocity in km/h return Float.valueOf(knots).floatValue() * 1.85; } float heading() { if(!available) return 0; return Float.valueOf(heading).floatValue(); } boolean locked() { return locked; } }