/*________________________________________________ * TAG 2.0 * Jonathan Hey * April 2007 * jono.hey+at+gmail.com * * CURRENT ISSUES * - use color variables * - background using back object is a mess - maybe create 4 of them? * * ADVANCED TAG * 2.0 Changes * - added tag sound * - added start screen * - player select * - locate player on startscreen * - added player trails * - added in game music - on/off (BACKSPACE) * - fixed players getting stuck at the side * - add tag animation * - add scoreboard * * To add * - wall detection in its own method * - add faces/characters * - add special grab arm * - use threading * - improve font and writing * - thicker trails * - use alpha in trails *________________________________________________*/ // for background PGraphics back; // for sound import krister.Ess.*; AudioChannel tag; AudioChannel woohoo; AudioChannel gameMusic; boolean music = true; // Gameplay parameters int numberOfPlayers = 4; int myWidth = 600; int myHeight = 400; float growSpeed = 0.15; float shrinkSpeed = 1.0; int tagbackTime = 2; // in seconds float winningSize = 90; int kidInitialSize = 20; // start positions int kid1x = myWidth-50; int kid1y = myHeight-50; int kid2x = 50; int kid2y = myHeight-50; int kid3x = 50; int kid3y = 50; int kid4x = myWidth-50; int kid4y = 50; // for no tagback tagback int framerate = 50; int tagbackLimit = tagbackTime*framerate; int justTagged=0; //the player number who just tagged int firstTag = 0; //to mark the first tag - only to solve the 0 player shrinking // for showing location int fadeTime = 1; int fadeLimit = fadeTime*framerate; // basic setup Kid[] kids = new Kid[numberOfPlayers]; int gameState = 0; int IT; // IT is the player number who is currently IT // keys (player 1 keys are always cursors) char kid2Left = 'v'; char kid2LeftCaps = 'V'; char kid2Right = 'n'; char kid2RightCaps = 'N'; char kid2Up = 'g'; char kid2UpCaps = 'G'; char kid2Down = 'b'; char kid2DownCaps = 'B'; char kid3Left = 'a'; char kid3LeftCaps = 'A'; char kid3Right = 'd'; char kid3RightCaps = 'D'; char kid3Up = 'w'; char kid3UpCaps = 'W'; char kid3Down = 's'; char kid3DownCaps = 'S'; char kid4Left = 'j'; char kid4LeftCaps = 'J'; char kid4Right = 'l'; char kid4RightCaps = 'L'; char kid4Up = 'i'; char kid4UpCaps = 'I'; char kid4Down = 'k'; char kid4DownCaps = 'K'; PFont titleFont; PFont smallFont; void setup() { titleFont = loadFont("BaskOldFace-25.vlw"); smallFont = loadFont("BaskOldFace-16.vlw"); textFont(titleFont, 25); // active and size 25 textAlign(LEFT); // for background back = createGraphics(myWidth, myHeight, P3D); back.beginDraw(); //back.background(102,102,102); back.endDraw(); // for sound Ess.start(this); tag = new AudioChannel("tag.wav"); tag.volume(2); woohoo = new AudioChannel("woohoo.wav"); gameMusic = new AudioChannel("bennyhill_music.wav"); gameMusic.volume(3); size(600, 400); draw_background(); // for pixel trails loadPixels(); smooth(); frameRate(framerate); set_random_IT(); // create Kids create_kids(); setITs(IT); gameState = 0; } void draw() { switch(gameState){ case 0: //start screen draw_startscreen(); for (int i = 0; i < kids.length; i++){ kids[i].display(); } break; case 1: //playing draw_background(); // update the pixel array after moving the kids updatePixels(); for (int i = 0; i < kids.length; i++){ kids[i].move(); kids[i].update_pixel_trail(); kids[i].display(); kids[i].increment_tag_timer(); } IT = kids[IT].check_for_tag(IT); setITs(IT); kids[IT].grow(growSpeed); kids[IT].changeColor(); if(firstTag!=0){ // to make sure player 0 doesn't shrink on the first go kids[justTagged].shrink(shrinkSpeed); } //print(IT); check_winner(); break; case 2: //win textFont(titleFont, 25); fill(255,255,255, 80); text("Kid "+(IT+1)+" rocks!\nEnter to play continue\nDelete to reset", myWidth/2, (3*myHeight)/4); draw_scoreboard(); break; } } void reset_game_and_play(){ //reset background and players draw_background(); reset_kids(); set_random_IT(); setITs(IT); if (music){ gameMusic.play(5); } //set to playing gameState=1; } void reset_game_and_startscreen(){ //reset background and players kids = new Kid[numberOfPlayers]; //println("kid length: "+ kids.length); create_kids(); set_random_IT(); setITs(IT); //set to playing gameState=0; } void create_kids(){ kids[0] = new Kid( kid1x, kid1y, kidInitialSize, 0); kids[0].setColors(102,0,102); if(numberOfPlayers>1){ kids[1] = new Kid( kid2x, kid2y, kidInitialSize, 1); kids[1].setColors(0,51,102); if(numberOfPlayers>2){ kids[2] = new Kid( kid3x, kid3y, kidInitialSize, 2); kids[2].setColors(0,0,163); if(numberOfPlayers>3){ kids[3] = new Kid( kid4x, kid4y, kidInitialSize, 3); kids[3].setColors(0,0,224); } } } } void reset_kids(){ kids[0].setSize(kidInitialSize); kids[0].setLocation(kid1x, kid1y); kids[0].setColors(102,0,102); if(numberOfPlayers>1){ kids[1].setSize(kidInitialSize); kids[1].setLocation(kid2x, kid2y); kids[1].setColors(0,51,102); if(numberOfPlayers>2){ kids[2].setSize(kidInitialSize); kids[2].setLocation(kid3x, kid3y); kids[2].setColors(0,0,163); if(numberOfPlayers>3){ kids[3].setSize(kidInitialSize); kids[3].setLocation(kid4x, kid4y); kids[3].setColors(0,0,224); } } } } void set_random_IT(){ IT=int(random(-0.4,(numberOfPlayers-0.51))); } void draw_background() { background(102); fill(255, 255, 255); textAlign(LEFT); textFont(titleFont, 25); text("Got the halo? Run!\nNo halo? Get them!", myWidth/2, myHeight/6); } void draw_startscreen() { background(102); fill(255, 255, 255); textAlign(LEFT); textFont(titleFont, 25); text("Can you keep the halo?", myWidth/4, myHeight/6); if (numberOfPlayers == 1){ text("It's just me.\nBring it on.", myWidth/4, myHeight/2); textFont(smallFont, 16); text("cursors", kid1x-kids[0].getSize()/2, kid1y+kids[0].getSize()/2+20); } else if (numberOfPlayers == 2){ text("It's a duel.\nMay the best person win.", myWidth/4, myHeight/2); textFont(smallFont, 16); text("cursors", kid1x-kids[0].getSize()/2, kid1y+kids[0].getSize()/2+20); text("v,n,g,b", kid2x-kids[1].getSize()/2, kid2y+kids[1].getSize()/2+20); } else if (numberOfPlayers == 3){ text("It's a party.\nThere's "+numberOfPlayers+" of us.", myWidth/4, myHeight/2); textFont(smallFont, 16); text("cursors", kid1x-kids[0].getSize()/2, kid1y+kids[0].getSize()/2+20); text("v,n,g,b", kid2x-kids[1].getSize()/2, kid2y+kids[1].getSize()/2+20); text("a,d,w,s", kid3x-kids[2].getSize()/2, kid3y+kids[2].getSize()/2+20); } else if (numberOfPlayers == 4){ text("It's a party.\nThere's "+numberOfPlayers+" of us.", myWidth/4, myHeight/2); textFont(smallFont, 16); text("cursors", kid1x-kids[0].getSize()/2, kid1y+kids[0].getSize()/2+20); text("v,n,g,b", kid2x-kids[1].getSize()/2, kid2y+kids[1].getSize()/2+20); text("a,d,w,s", kid3x-kids[2].getSize()/2, kid3y+kids[2].getSize()/2+20); text("j,l,i,k", kid4x-kids[3].getSize()/2, kid4y+kids[3].getSize()/2+20); } textFont(smallFont, 16); text("Enter to start\nUse 1,2,3,4 to select number of players\nBackspace toggles music on/off", myWidth/4, (3*myHeight)/4); //textSize(16); //text("Kid 1: cursors \nKid 2: x,v,d,c \nKid 3: q,e,2,w \nKid 4: j,l,i,k", myWidth/8, (3*myHeight)/4); } void draw_scoreboard(){ int scoreBoardx = myWidth/8; int scoreBoardy = myHeight/2; int columnSpacing = 60; int lineSpacing = 30; textFont(titleFont,25); fill(255,255,255); text("Kid", scoreBoardx, scoreBoardy); text("Wins", scoreBoardx+columnSpacing, scoreBoardy); for (int i=0; i=winningSize){ kids[IT].addWin(); gameMusic.stop(); woohoo.play(1); gameState = 2; } } void setITs(int iAmIT){ for (int i=0; iinitialSize){ size = size - s; //println("shrinking!"); } } void changeColor(){ ITG = ITG-int(colorIncrement); } void addWin(){ numberOfWins = numberOfWins + 1; } //-------------------------------------- //GET methods //-------------------------------------- // returnd the xPos and yPos values of the Kid float[] getPos(float[] positionVals) { positionVals[0] = xPos; positionVals[1] = yPos; return positionVals; } float getSize(){ return size; } int getPlayerNumber(){ return playerNumber; } int getTagback(){ return tagback; } int getNumberOfWins(){ return numberOfWins; } color getColor(){ return pixelTrailColor; } //-------------------------------------- //CALCULATING methods //-------------------------------------- void check_distances(){ float xDist = 0; float yDist = 0; float hypothenuse = 0; for (int i = 0; i < kids.length; i++){ //println("kid length in check distances: "+kids.length); float[] posKid2 = new float[2]; float[] kidComparePos = kids[i].getPos(posKid2); //println("Kid "+i+"= x("+kidComparePos[0]+"), y("+kidComparePos[1]+")"); xDist = xPos-kidComparePos[0]; yDist = yPos-kidComparePos[1]; hypothenuse = sqrt(pow(xDist,2)+pow(yDist,2)); touching_distance[i] = hypothenuse - size/2 - kids[i].getSize()/2; //println("touching_distance["+i+"] ="+touching_distance[i]); } } int check_for_tag(int whoIsIT){ check_distances(); for(int i=0; itagbackLimit)){ tag.play(1); justTagged = whoIsIT; //set the player who tagged as justTagged whoIsIT = i; //then set the person who is now IT //play a mini tag animation kids[whoIsIT].tag_animation(); // set the IT player to go faster kids[whoIsIT].setMoveSpeed(8); // fix the player who just tagged someone kids[justTagged].setTagback(0); kids[justTagged].reset_IT_colors(); kids[justTagged].setMoveSpeed(5); if (firstTag==0){firstTag=1;} } } return whoIsIT; } //OTHER methods //-------------------------------------- void increment_tag_timer(){ if(tagback<=tagbackLimit){ tagback = tagback+1; } //println("tagback "+playerNumber+":"+tagback); } void reset_IT_colors(){ ITR = 255; ITG = 255; ITB = 0; } void update_pixel_trail(){ // updates the colors of the pixels in a cross around the center //center pixels[int(yPos)*width+int(xPos)] = color(R+50,G+50,B+50, 40); pixels[int(yPos)*width+int(xPos+1)] = color(R,G,B, 5);// center right pixels[int(yPos)*width+int(xPos-1)] = color(R,G,B, 5);// center left // complete other parts of 9 square pixels[int(yPos-1)*width+int(xPos-1)] = color(R,G,B, 2);// top left pixels[int(yPos-1)*width+int(xPos)] = color(R,G,B, 5);// top center pixels[int(yPos-1)*width+int(xPos+1)] = color(R,G,B,2);// top right pixels[int(yPos+1)*width+int(xPos-1)] = color(R,G,B, 2);// bottom left pixels[int(yPos+1)*width+int(xPos)] = color(R,G,B, 5);// bottom center pixels[int(yPos+1)*width+int(xPos+1)] = color(R,G,B, 2);// bottom right // far edges of cross pixels[int(yPos)*width+int(xPos+2)] = color(R,G,B, 98);// center extreme right pixels[int(yPos)*width+int(xPos-2)] = color(R,G,B, 98);// center extreme left pixels[int(yPos+2)*width+int(xPos)] = color(R,G,B, 98);// bottom extreme center pixels[int(yPos-2)*width+int(xPos)] = color(R,G,B, 98);// top extreme center } void draw_trail(){ back.beginDraw(); //back.noStroke(); back.fill(0xFFFF0000); back.ellipse( xPos, yPos, size, size ); back.endDraw(); image(back, xPos, yPos); } void tag_animation(){ fill(255, 255, 255,20); strokeWeight(2); stroke(ITR, ITG, ITB); ellipse(xPos, yPos, size+10, size+10); } void move() { // checks on bumping into the side when moving if (((xPos+v[0]+(size/2))<=myWidth) && (0<=(xPos-(size/2)+v[0]))){ xPos = xPos + v[0]; } if(((yPos+v[1]+(size/2))<=myHeight) && (0<=(yPos-(size/2)+v[1]))){ yPos = yPos + v[1]; } // allow movement back in if they grow over the side if (((xPos + (size/2))>=myWidth)&&(v[0]<0)){ xPos = xPos + v[0]; } if (((xPos -(size/2))<=0)&&(v[0]>0)){ xPos = xPos + v[0]; } if (((yPos + (size/2))>=myHeight)&&(v[1]<0)){ yPos = yPos + v[1]; } if (((yPos -(size/2))<=0)&&(v[1]>0)){ yPos = yPos + v[1]; } } void display() { if (IT == true){ //fill(ITR, ITG, ITB); //stroke(ITR-10, ITG, ITB); fill(R,G,B); strokeWeight(8); stroke(haloColor); } else if (IT == false){ strokeWeight(2); fill(R, G, B); stroke(R-20, G-20, B-20); } ellipse(xPos, yPos, size, size); textAlign(CENTER); textFont(smallFont, 16); fill(255,255,255,90); text(playerNumber+1, xPos, yPos-(size/2)-10); textAlign(LEFT); draw_face(); //draw_trail(); // for showing the location of the players if (locationTimer<=fadeLimit){ show_location(); locationTimer = locationTimer+1; update_show_location_color(); } else if (locationTimer>fadeLimit){ reset_show_location_color(); } } // add a face to the players void draw_face(){ int eyeSize; float radius = size/2; if (int(size/10)<1){ eyeSize = 1; } else{ eyeSize = int(size/10); } // smile stroke(255,255,255); strokeWeight(eyeSize/2); noFill(); arc(xPos, yPos, size/2, size/2, PI/8, 7*PI/8); // eyes noStroke(); fill(255,255,255); ellipse((xPos+(radius/3)), (yPos-(radius/3)), eyeSize, eyeSize); noStroke(); fill(255,255,255); ellipse((xPos-(radius/3)), (yPos-(radius/3)), eyeSize, eyeSize); } // for showing the location of the players void show_location() { noFill(); strokeWeight(2); stroke(showLocationColor); ellipse(xPos, yPos, size+10, size+10); } void update_show_location_color(){ showLocationColorR = showLocationColorR-5; showLocationColorG = showLocationColorG-5; showLocationColorB = showLocationColorB-5; setShowLocationColor(showLocationColorR, showLocationColorG, showLocationColorB); } } // Keys //---------------------------------------------- void keyPressed(){ //To restart after winning if (gameState == 2){ if (((keyCode == ENTER)||(keyCode == RETURN)) && (gameState==2)){ reset_game_and_play(); } if (keyCode == DELETE){ setup(); } if (keyCode == BACKSPACE){ if (music){ music = false; } else { music = true; } } } // Keys for in game: gameState 1 if (gameState == 1){ //Player 1 if (keyCode == UP) { kids[0].setVelocity(0,-1); } if (keyCode == DOWN) { kids[0].setVelocity(0,1); } if (keyCode == RIGHT) { kids[0].setVelocity(1,0); } if (keyCode == LEFT) { kids[0].setVelocity(-1,0); } if (numberOfPlayers>=2){ //Player 2 if ((key == kid2Up) || (key == kid2UpCaps)) { kids[1].setVelocity(0,-1); } if ((key == kid2Down) || (key == kid2DownCaps)) { kids[1].setVelocity(0,1); } if ((key == kid2Right) || (key == kid2RightCaps)) { kids[1].setVelocity(1,0); } if ((key == kid2Left) || (key == kid2LeftCaps)) { kids[1].setVelocity(-1,0); } if (numberOfPlayers >=3){ //Player 3 if ((key == kid3Up) || (key == kid3UpCaps)) { kids[2].setVelocity(0,-1); } if ((key == kid3Down) || (key == kid3DownCaps)) { kids[2].setVelocity(0,1); } if ((key == kid3Right) || (key == kid3RightCaps)) { kids[2].setVelocity(1,0); } if ((key == kid3Left) || (key == kid3LeftCaps)) { kids[2].setVelocity(-1,0); } //Player 4 if (numberOfPlayers >= 4){ if ((key == kid4Up) || (key == kid4UpCaps)) { kids[3].setVelocity(0,-1); } if ((key == kid4Down) || (key == kid4DownCaps)) { kids[3].setVelocity(0,1); } if ((key == kid4Right) || (key == kid4RightCaps)) { kids[3].setVelocity(1,0);; } if ((key == kid4Left) || (key == kid4LeftCaps)) { kids[3].setVelocity(-1,0); } } // end 4 player } //end 3 player } // end 2 player } // keys for start screen: gameState 0 if (gameState == 0){ //To start initially if ((keyCode == ENTER)||(keyCode == RETURN)){ gameState=1; if (music){ gameMusic.play(5); } } if (keyCode == BACKSPACE){ if (music){ music = false; } else { music = true; } } //select players on start screen if ((key == '1') || (key == '!')){ numberOfPlayers = 1; growSpeed = 0.2; winningSize = 100; reset_game_and_startscreen(); } if ((key == '2') || (key == '@')){ numberOfPlayers = 2; growSpeed = 0.2; winningSize = 100; reset_game_and_startscreen(); } if ((key == '3') || (key == '#')){ numberOfPlayers = 3; growSpeed = 0.2; winningSize = 80; reset_game_and_startscreen(); } if ((key == '4') || (key == '$')){ numberOfPlayers = 4; growSpeed = 0.15; winningSize = 90; reset_game_and_startscreen(); } // show player locations on key presses if ((keyCode == LEFT)||(keyCode == RIGHT)||(keyCode == UP)||(keyCode == DOWN)){ kids[0].reset_show_location_color(); kids[0].setLocationTimer(0); } if ((key == kid2Left)||(key == kid2LeftCaps)||(key == kid2Right)||(key == kid2RightCaps)||(key == kid2Up)||(key == kid2UpCaps)||(key == kid2Down)||(key == kid2DownCaps)){ kids[1].reset_show_location_color(); kids[1].setLocationTimer(0); } if ((key == kid3Left)||(key == kid3LeftCaps)||(key == kid3Right)||(key == kid3RightCaps)||(key == kid3Up)||(key == kid3UpCaps)||(key == kid3Down)||(key == kid3DownCaps)){ kids[2].reset_show_location_color(); kids[2].setLocationTimer(0); } if ((key == kid4Left)||(key == kid4LeftCaps)||(key == kid4Right)||(key == kid4RightCaps)||(key == kid4Up)||(key == kid4UpCaps)||(key == kid4Down)||(key == kid4DownCaps)){ kids[3].reset_show_location_color(); kids[3].setLocationTimer(0); } } }