import ddf.minim.*; /** * Game 15: "Grapplish"
* Hold spacebar to lock orbit
* Use left and right arrows to swing
* Ascend as far as possible within the time limit
*
Go play more games at NMcCoy.net!
* Creative Commons License
This work by Nathan McCoy is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License. */ boolean[] keys = new boolean[256]; boolean title; boolean paused; boolean muted; boolean gameover; int drawing_ms_last; int physics_ms_last; int CORE_FPS = 540; int DRAWING_FPS = 60; int PHYSICS_FPS = 180; int DRAW_MS = 1000 / DRAWING_FPS; int PHYS_MS = 1000 / PHYSICS_FPS; Minim minim; ArrayList nodes; PVector player_pos; PVector player_prevpos; float GRAVITY = 0.010; float SWING_STRENGTH = 0.005; PVector active_node; PVector best_node; float radius; float MIN_RADIUS = 14; float camera_offset; PFont font; boolean scored; float camera_creep; float CAMERA_CREEP_ACCEL = 0.00001; int MAX_TIME = 180*90; int time; int NUM_DOTS = 15; void setup() { size(720, 480); frameRate(600); minim = new Minim(this); font = loadFont("PressStartK-32.vlw"); title = true; reset(); } void reset() { nodes = new ArrayList(); player_pos = new PVector(width/2, height/2); player_prevpos = new PVector(width/2, height/2); for(int i = 0; i < NUM_DOTS; i++) nodes.add(new PVector(random(width), -height + i*(height*2)/NUM_DOTS)); camera_creep = 0; camera_offset = 0; gameover = false; time = MAX_TIME; title = paused = true; active_node = null; best_node = null; //else paused = false; } void stop() { minim.stop(); super.stop(); } void physicsStep() { //camera_creep += CAMERA_CREEP_ACCEL; //camera_offset -= camera_creep; PVector temp = new PVector(player_pos.x, player_pos.y); if(player_pos.y < camera_offset + height*3) { player_pos.x += (player_pos.x - player_prevpos.x); player_pos.y += (player_pos.y - player_prevpos.y) + GRAVITY; if(keys[RIGHT]) player_pos.x += SWING_STRENGTH; if(keys[LEFT]) player_pos.x -= SWING_STRENGTH; } else gameover = true; time--; if(time <=0 || gameover) { time = 0; gameover = true; active_node = null; paused = false; } Iterator ni = nodes.iterator(); best_node = null; float bestd = MAX_FLOAT; while(ni.hasNext()) { PVector n = (PVector) ni.next(); float f = PVector.dist(n, player_pos); if(f < bestd && n.y < player_pos.y //&& (!(keys[LEFT] && n.x > player_pos.x) && !(keys[RIGHT] && n.x < player_pos.x)) ) { bestd = f; best_node = n; } } if(active_node != null) { float d = PVector.dist(active_node, player_pos); // radius = max(min(radius - 0.0, d), MIN_RADIUS); //if(keys[DOWN]) radius += 0.3; //if(d > radius) { PVector to_player = PVector.sub(player_pos, active_node); to_player.normalize(); to_player.mult(radius); player_pos = PVector.add(active_node, to_player); } } player_prevpos = temp; scored = false; if(player_pos.y < camera_offset + height/2) { camera_offset = player_pos.y - height/2; scored = true; } ni = nodes.iterator(); while(ni.hasNext()) { PVector n = (PVector) ni.next(); if(n.y > camera_offset + height && n != active_node) { n.x = random(width); n.y = n.y - height*2;//camera_offset - height + random(height); } } } void drawingStep() { background(0); ellipseMode(RADIUS); pushMatrix(); translate(0, -camera_offset); // if(active_node != null) // { // stroke(255); // line(player_pos.x, player_pos.y, active_node.x, active_node.y); // } noStroke(); fill(192); float bestd = MAX_FLOAT; PVector closest = player_pos; strokeWeight(2); Iterator ni = nodes.iterator(); while(ni.hasNext()) { PVector n = (PVector) ni.next(); float d = PVector.dist(n, player_pos); stroke(30000/(d+50), 0, 30000/(d+100)); noFill(); ellipse(n.x, n.y, d, d); fill(30000/(d+50), 0, 30000/(d+100)); noStroke(); float timerat = time / (float)MAX_TIME; ellipse(n.x, n.y, 7*timerat+0.5, 7*timerat+0.5); } // ni = nodes.iterator(); // while(ni.hasNext()) // { // PVector n = (PVector) ni.next(); // noStroke(); // fill(192); // ellipse(n.x, n.y, 7, 7); // // } fill(64, 192, 192); //ellipse(player_pos.x, player_pos.y, 7, 7); noFill(); stroke(0, 255, 255); if(best_node != null) { stroke(255, 192, 0); float d = PVector.dist(best_node, player_pos); ellipse(best_node.x, best_node.y, d, d); } if(active_node != null) { stroke(255, 255, 192); float d = PVector.dist(active_node, player_pos); ellipse(active_node.x, active_node.y, d, d); } popMatrix(); noStroke(); fill(255, 192, 0); if(scored || gameover) fill(255, 255, 192); textFont(font, 8); textAlign(LEFT, TOP); text("Score: "+(int)-camera_offset, 8, 16); fill(255, 192, 0); if(time < MAX_TIME/8 && (time/20)%2 == 0) fill(255, 255, 192); rect(8, 6, (width-16)*time/MAX_TIME, 2); fill(255, 192, 0); if(gameover) text("Press SPACE to play again.", 8, 4); textAlign(CENTER, CENTER); if(title) text("( Grapplish )\npress SPACE to start", width/2, height/2); else if(paused) text("Paused", width/2, height/2); } void draw() { while(physics_ms_last + PHYS_MS < millis()) { if(!paused) { physicsStep(); } physics_ms_last += PHYS_MS; } if(drawing_ms_last + DRAW_MS < millis()) { drawingStep(); drawing_ms_last = millis(); } } void keyPressed() { if(!keys[keyCode]) { keys[keyCode] = true; down(keyCode); } } void keyReleased() { if(keys[keyCode]) { keys[keyCode] = false; up(keyCode); } } void down(int theKey) { println(theKey + " down"); if(theKey == 'P' && !gameover && !title) { paused = !paused; } if(theKey == ' ' && !gameover) { if(title) { title = false; paused = false; } if(!paused) { if(player_pos.y < camera_offset + height) active_node = best_node; if(active_node != null) radius = PVector.dist(active_node, player_pos); } // radius = MAX_FLOAT; // Iterator ni = nodes.iterator(); // while(ni.hasNext()) // { // PVector n = (PVector) ni.next(); // float f = PVector.dist(n, player_pos); // if(f < radius) // { // radius = f; // active_node = n; // } // } } if(theKey == ' ' && gameover && player_pos.y > camera_offset+height) reset(); } void up(int theKey) { if(!paused) { if(!keys[' ']) active_node = null; } println(theKey + " up"); }