import moviemaker.*; //import processing.opengl.*; import procontroll.*; import net.java.games.input.*; import traer.physics.*; import krister.Ess.*; /** Click in the applet and press any key to start a game
Use the arrow keys for movement, 'a' for the sucking force, 's' for the blowing force
'g' to turn on the glow, but expect a performace hit */ // ----------- GAME SETTINGS ----------------- // int playerSize = 35; // radius in pixels float playerSpeed = 12; // move amount in pixels per frame TODO: make this time based color playerColor = color(255); color playerGlow = color(254, 215, 96); float nestSize = 110; // radius in pixels color nestColor = color(255); color nestGlow = color(254, 215, 96); int kickInterval = 5; // spawn a kick pulser every #th kick int kickRadius = 31; // in pixels float kickMass = 1f; color kickColor = color(255, 237, 102); color kickGlow = color(255, 162, 0); int snareInterval = 5; // spawn a snare pulser every #th snare int snareRadius = 23; // in pixels float snareMass = 1.5f; color snareColor = color(255, 150, 79); color snareGlow = color(255, 0, 0); int hatInterval = 5; // spawn a hat pulser every #th hat int hatRadius = 17; // in pixels float hatMass = 2f; color hatColor = color(198, 254, 183); color hatGlow = color(0, 234, 255); int pickUpRadius = 20; color pickUpColor = color(121, 255, 151); color pickUpGlow = color(0, 255, 30); int bumpMax = 10; // the maximum number of times a bumper will give points before despawning color skullColor = color(254, 229, 13); color skullGlow = color(0, 255, 156); color sbColor = color(253, 0, 126); color sbGlow = color(255, 0, 255); float pulseAmt = 1.3f; // percentage of how much larger they will get int maxPulsers = 20; // maximum number of pulsers allowed on screen float glowIntensity = 200; float suckStrength = 3f; // larger number means stronger sucking float blowStrength = 75f; // larger number means stronger blowing int maxEnemies = 3; // ------------------- END GAME SETTINGS ----------------------- // PFont arial; PImage[] words = new PImage[16]; PS2Controller gamepad; ParticleSystem phys = new ParticleSystem(0, .2f); Events evnt = new Events(); Player pl; Pulser puls; Vector pulsers = new Vector(20, 10); Nest nest; PickUp pick; Deathskull skull; Vector skulls = new Vector(maxEnemies, 0); Sucker sucker; Vector suckers = new Vector(maxEnemies, 0); Blower blower; Vector blowers = new Vector(maxEnemies, 0); Bumper bump; Vector bumpers = new Vector(3, 0); AudioInput in; BeatDetect beat; Countdown count; MovieMaker mm; int kickWait = 0; int snareWait = 0; int hatWait = 0; int totalCaught = 0; ScoreDisplayer score; int playTimer = 0; boolean capture = false; boolean makeMovie = false; boolean record = false; boolean debug = false; boolean screenStats = true; boolean playing = false; boolean pause = false; boolean drawGlow = true; boolean drawGhost = false; boolean useGamepad = false; boolean time = false; int timer = 0; void setup() { // setup the environment size(1024, 768, P3D); background(0); noCursor(); //smooth(); ellipseMode(CENTER_RADIUS); frameRate(30); arial = loadFont("ArialMT-24.vlw"); textFont(arial); words[0] = loadImage("0.png"); words[1] = loadImage("1.png"); words[2] = loadImage("2.png"); words[3] = loadImage("3.png"); words[4] = loadImage("4.png"); words[5] = loadImage("5.png"); words[6] = loadImage("6.png"); words[7] = loadImage("7.png"); words[8] = loadImage("8.png"); words[9] = loadImage("9.png"); words[10] = loadImage("minus.png"); words[11] = loadImage("glee.png"); words[12] = loadImage("go.png"); words[13] = loadImage("pulsers_saved.png"); words[14] = loadImage("score.png"); words[15] = loadImage("timeout.png"); if ( useGamepad ) { // setup the gamepad gamepad = new PS2Controller(this); gamepad.leftStick.setMultiplier(playerSpeed); gamepad.leftStick.setTolerance(0.3f); gamepad.rightStick.setTolerance(0.15f); gamepad.invertRightY = true; } // create the player pl = new Player(); // create the nest nest = new Nest(); // create the countdown count = new Countdown(3); // create the score displayer score = new ScoreDisplayer(); // setup the sound Ess.start(this); in = new AudioInput(1024, 44100); beat = new BeatDetect(in.size, in.sampleRate); beat.detectMode("FREQ_ENERGY"); beat.detectDetail(64); in.start(); if ( makeMovie ) mm = new MovieMaker(this, width, height, "kish.mov", MovieMaker.VIDEO, MovieMaker.LOW, 30); } void draw() { if ( pause ) { delay(5000); pause = false; } if ( !playing && ( keyPressed || ( useGamepad && gamepad.Start.pressed() ) ) ) { phys.clear(); pulsers.clear(); suckers.clear(); blowers.clear(); skulls.clear(); bumpers.clear(); pick = null; nest = new Nest(); pl = new Player(); totalCaught = 0; score.reset(); playTimer = millis(); playing = true; count.start(); } if ( count.running ) { background(10, 0, 23); count.update(); } else { if ( drawGhost ) { fill(10, 0, 23, 90); rect(0, 0, width, height); } else background(10, 0, 23); game(); if ( playing && playTime() > 180000 ) { fill(10, 0, 23, 128); rect(0, 0, width, height); image(words[15], 10, 100); image(words[13], 10, 250, words[13].width/2, words[13].height/2); printNumber(totalCaught, 500, 260, 0.5, 0); image(words[14], 10, 330, words[14].width/2, words[14].height/2); printNumber(score.total(), 500, 320, 0.5, 0); playing = false; pl.reset(); pause = true; } } if ( capture && frameCount%300 == 0 ) saveFrame("kish-####.png"); if ( makeMovie && record ) { loadPixels(); mm.addFrame(pixels, width, height); } } void game() { phys.tick(); evnt.update(); // play timer in background if ( playing ) { int timeLeft = 180000 - playTime(); int minutes = timeLeft / 60000; int seconds = (timeLeft - minutes*60000) / 1000; printNumber(minutes, -300, 200, 3, 70); if ( seconds > 9 ) printNumber(seconds, 250, 200, 3, 70); else { printNumber(0, 45, 200, 3, 70); printNumber(seconds, 250, 200, 3, 70); } } // Update the player if ( playing ) { if ( useGamepad ) { pl.move(gamepad.leftX(), gamepad.leftY()); pl.suck( gamepad.X.pressed() ); pl.blow( gamepad.O.pressed(), beat.isKick() ); } else { pl.keyMove(); pl.keySuck(); pl.keyBlow(beat.isKick()); } } // make new pulsers from beat if there are fewer than maxPulsers on the board if ( pulsers.size() < maxPulsers ) { if ( beat.isKick() ) { if ( kickWait == 0 ) { if ( debug ) println("Adding a kick."); float x = random(kickRadius, width-kickRadius); float y = random(kickRadius, height-kickRadius); while ( nest.isVisible() && dist(nest.x(), nest.y(), x, y) < nestSize + kickRadius ) { x = random(kickRadius, width-kickRadius); y = random(kickRadius, height-kickRadius); } pulsers.add(new Pulser(KICK, x, y)); kickWait = kickInterval; } else kickWait--; } if ( beat.isSnare() ) { if ( snareWait == 0 ) { if ( debug ) println("Adding a snare."); float x = random(snareRadius, width-snareRadius); float y = random(snareRadius, height-snareRadius); while ( nest.isVisible() && dist(nest.x(), nest.y(), x, y) < nestSize + snareRadius ) { x = random(snareRadius, width-snareRadius); y = random(snareRadius, height-snareRadius); } pulsers.add(new Pulser(SNARE, x, y)); snareWait = snareInterval; } else snareWait--; } if ( beat.isHat() ) { if ( hatWait == 0 ) { if ( debug ) println("Adding a hat."); float x = random(hatRadius, width-hatRadius); float y = random(hatRadius, height-hatRadius); while ( nest.isVisible() && dist(nest.x(), nest.y(), x, y) < nestSize + hatRadius ) { x = random(hatRadius, width-hatRadius); y = random(hatRadius, height-hatRadius); } pulsers.add(new Pulser(HAT, x, y)); hatWait = hatInterval; } else hatWait--; } } // make new pickups every 30 seconds if ( pick == null && playTime() > 59000 && playTime() % 30000 < 200 ) { pick = new PickUp(); println("Made a pickup"); } // manage pickup if ( pick != null && pick.isDead() ) pick = null; if ( pick != null ) { pick.update(); pick.interact(pl); if ( pick.isFree() ) pl.interact(pick); pick.render(); } // manage the nest nest.update(); if ( nest.isVisible() ) { if ( beat.isKick() ) nest.spawnRing(); if ( pick != null ) nest.tryCatch(pick); } else if ( nest.hiddenFor() > 3 && bumpers.size() == 0 ) { boolean found = false; for (int i = 0; !found && i < 5; i++) { found = true; nest.move(); // test for overlap with skulls for (int j = 0; found && j < skulls.size(); j++) { skull = (Deathskull)skulls.get(j); if ( dist(nest.x(), nest.y(), skull.x(), skull.y()) < nest.radius() + skull.radius() ) found = false; } for (int j = 0; found && j < suckers.size(); j++) { sucker = (Sucker)suckers.get(j); if ( dist(nest.x(), nest.y(), sucker.x(), sucker.y()) < nest.radius() + sucker.radius() ) found = false; } for (int j = 0; found && j < blowers.size(); j++) { blower = (Blower)blowers.get(j); if ( dist(nest.x(), nest.y(), blower.x(), blower.y()) < nest.radius() + blower.radius() ) found = false; } for (int j = 0; found && j < bumpers.size(); j++) { bump = (Bumper)bumpers.get(j); if ( dist(nest.x(), nest.y(), bump.x(), bump.y()) < nest.radius() + bump.radius() ) found = false; } for (int j = 0; found && j < pulsers.size(); j++) { puls = (Pulser)pulsers.get(j); if ( dist(nest.x(), nest.y(), puls.x(), puls.y()) < nest.radius() + puls.radius() ) found = false; } } if ( found ) nest.show(); } // make new deathskull, maybe if ( skulls.size() + suckers.size() + blowers.size() < maxEnemies && prob(1) ) { skulls.add(new Deathskull()); } // manage the deathskulls for (int i = 0; i < skulls.size(); i++) { skull = (Deathskull)skulls.get(i); if ( skull.isOffScreen() ) skull.kill(); if ( skull.isDead() ) skulls.remove(i--); else { pl.interact(skull); skull.update(); skull.render(); } } // make a new sucker/blower, maybe if ( skulls.size() + suckers.size() + blowers.size() < maxEnemies && prob(1) ) { suckers.add(new Sucker()); } // manage the suckers for (int i = 0; i < suckers.size(); i++) { sucker = (Sucker)suckers.get(i); if ( sucker.isOffScreen() ) sucker.kill(); if ( sucker.isDead() ) suckers.remove(i--); else { pl.interact(sucker); sucker.update(); sucker.render(); } } if ( skulls.size() + suckers.size() + blowers.size() < maxEnemies && prob(1) ) { blowers.add(new Blower()); } // manage the blowers for (int i = 0; i < blowers.size(); i++) { blower = (Blower)blowers.get(i); if ( blower.isOffScreen() ) blower.kill(); if ( blower.isDead() ) blowers.remove(i--); else { pl.interact(blower); blower.update(); blower.render(); } } // manage bumpers for (int i = 0; i < bumpers.size(); i++) { bump = (Bumper)bumpers.get(i); if ( bump.isDead() ) bumpers.remove(i--); else { for (int j = 0; j < skulls.size(); j++) bump.interact((Deathskull)skulls.get(j)); for (int j = 0; j < suckers.size(); j++) bump.interact((Sucker)suckers.get(j)); for (int j = 0; j < blowers.size(); j++) bump.interact((Blower)blowers.get(j)); bump.interact(pl); bump.update(); bump.render(); } } if ( time ) timer = millis(); // pulsing, nest interaction, player interaction, enemy interaction, // collision and rendering for (int i = 0; i < pulsers.size(); i++) { puls = (Pulser)pulsers.get(i); // do all the stuff that doesn't require interaction if ( puls.isDying() ) { puls.render(); puls.deathTick(); continue; } if ( puls.isDead() ) { pulsers.remove(i--); continue; } puls.update(); // pulse according to type switch(puls.type) { case KICK: if ( beat.isKick() ) puls.pulse(); break; case SNARE: if ( beat.isSnare() ) puls.pulse(); break; case HAT: if ( beat.isHat() ) puls.pulse(); break; } // collide with other pulsers for (int j = i+1; j < pulsers.size(); j++) puls.interact( (Pulser)pulsers.get(j) ); // interact with player if ( puls.isFree() ) pl.interact(puls); puls.interact(pl); // interact with the nest if ( nest.isVisible() ) nest.tryCatch(puls); // interact with enemies for (int j = 0; j < skulls.size(); j++) { skull = (Deathskull)skulls.get(j); puls.interact(skull); if ( skull.awareOf(puls) ) skull.target(puls); } for (int j = 0; j < suckers.size(); j++) { sucker = (Sucker)suckers.get(j); puls.interact(sucker); if ( sucker.isSucking() && sucker.awareOf(puls) ) sucker.interact(puls); } for (int j = 0; j < blowers.size(); j++) { blower = (Blower)blowers.get(j); puls.interact(blower); if ( blower.isBlowing() && blower.awareOf(puls) ) blower.interact(puls); } for (int j = 0; j < bumpers.size(); j++) { bump = (Bumper)bumpers.get(j); bump.interact(puls); } if ( puls.isOnWall() ) puls.wallBounce(); puls.render(); } if ( time ) println(frameCount + ": managing pulsers took " + (millis()-timer)); if ( nest.isVisible() ) nest.render(); pl.render(); if ( playing ) { image(words[13], 500, 0, words[13].width/2, words[13].height/2); printNumber(totalCaught, 890, 5, 0.5, 0); score.display(); } if ( screenStats ) { fill(255, 0, 0); textFont(arial); textSize(24); textAlign(LEFT); text("Frame Rate: " + frameRate, 5, height - 35); text("Total pulsers: " + pulsers.size(), 5, height - 15); } if ( debug ) { println(Runtime.getRuntime().freeMemory()); println("End draw, frame " + frameCount); } } int playTime() { return millis() - playTimer; } void printNumber(int n, float x, float y, float sc, int fadeAmt) { float spacing = 70*sc; String num = str(n); if ( n < 0 ) tint(255, 0, 0, 255 - fadeAmt*3); else tint(255, 255, 255, 255 - fadeAmt*3); for (int i = num.length()-1; i >= 0; i--) { int nInd = parseInt(num.charAt(i))-48; if ( nInd == -3 ) { PImage tmp = words[10]; image(tmp, x + spacing*3.2 + (i-num.length())*spacing, y + 30*sc, tmp.width*sc, tmp.height*sc); } else { PImage tmp = words[nInd]; image(tmp, x + spacing*3 + (i-num.length())*spacing, y, tmp.width*sc, tmp.height*sc); } } noTint(); } boolean prob(int p) { return millis() % 100 < p; } void keyPressed() { if ( key == CODED ) { switch(keyCode) { case UP: pl.up = true; break; case RIGHT: pl.right = true; break; case DOWN: pl.down = true; break; case LEFT: pl.left = true; break; } } else { if ( key == 'a' ) pl.suck = true; else if ( key == 's' ) pl.blow = true; else if ( key == 'g' ) drawGlow = !drawGlow; else if ( key == 'h' ) drawGhost = !drawGhost; else if ( key == 'r' && makeMovie ) record = true; else if ( key == 't' && makeMovie ) { record = false; mm.finishMovie(); } else if ( key == '1' ) evnt.trigger(0); else if ( key == '2' ) evnt.trigger(1); else if ( key == '3' ) evnt.trigger(2); else if ( key == '4' ) evnt.trigger(3); else if ( key == '5' ) evnt.trigger(4); else if ( key == '6' ) evnt.trigger(5); } } void keyReleased() { if ( key == CODED ) { switch(keyCode) { case UP: pl.up = false; break; case RIGHT: pl.right = false; break; case DOWN: pl.down = false; break; case LEFT: pl.left = false; break; } } else { if ( key == 'a' ) pl.suck = false; else if ( key == 's' ) pl.blow = false; } } public void audioInputData(AudioInput in) { beat.detect(in); } public void stop() { Ess.stop(); super.stop(); }