import ddf.minim.*; /** * Game 16: "Warped!"
*
*
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; 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; AudioSample shotSound; AudioSample exploSound; AudioSample dieSound; AudioSample warpSound; AudioSample dinkSound; PFont font; int NUM_STARS = 50; float MOVEMENT_SPEED = 1.5; float SHOT_SPEED = 6; float SHIPSIZE_X = 30; float SHIPSIZE_Y = 5; float WARN_TIME = 360*2; float WAVE_TIME = 360*5; float LEVEL_GAP_TIME = WAVE_TIME * 3; float wave_timer; int level; int wave; int score; int top; PVector player_pos; float warp_speed; float START_SPEED = 2; ArrayList stars; ArrayList enemies; PVector bullet; int drawing_frame; ParticleList explosions; boolean dead; abstract class Enemy { PVector pos; float timer; float radius; abstract void draw(); abstract boolean tick(); } void setup() { ellipseMode(RADIUS); size(720, 480); frameRate(600); minim = new Minim(this); shotSound = minim.loadSample("shot.wav", 1024); exploSound = minim.loadSample("explo.wav", 1024); dieSound = minim.loadSample("die.wav", 1024); warpSound = minim.loadSample("warp.wav", 1024); dinkSound = minim.loadSample("dink.wav", 1024); font = loadFont("PressStartK-32.vlw"); title = true; } void newGame() { enemies = new ArrayList(); spawnWave(); player_pos = new PVector(width/4, height/2); stars = new ArrayList(); for(int i = 0; i < NUM_STARS; i++) { stars.add(new PVector(random(width), random(height))); } warp_speed = START_SPEED; wave_timer = WAVE_TIME; explosions = new ParticleList(); score = 0; level = 0; wave = 0; dead = false; title = false; } void spawnWave() { float y; switch((int)random(7)) { case 0: //spinners down y = random(height/2); for(int i = 0; i < 5; i++) { enemies.add(new Spinner(new PVector(width+20, y+40*i), WARN_TIME + 180*i)); } break; case 1: //spinners up y = random(height/2)+height/2; for(int i = 0; i < 5; i++) { enemies.add(new Spinner(new PVector(width+20, y-40*i), WARN_TIME + 180*i)); } break; case 2: //spinners level y = random(height); for(int i = 0; i < 5; i++) { enemies.add(new Spinner(new PVector(width+20, y), WARN_TIME + 180*i)); } break; case 3: //rocks for(int i = 0; i < 10; i++) { enemies.add(new Asteroid(new PVector(width+40, random(height)), WARN_TIME + 90*i)); } break; case 4: //metal rocks for(int i = 0; i < 3; i++) { enemies.add(new MetalAsteroid(new PVector(width+40, random(height)), WARN_TIME + 270*i)); } break; case 5: //wavers up y = random(height); for(int i = 0; i < 5; i++) { enemies.add(new Waver(new PVector(width+20, y), WARN_TIME + 180*i, -70)); } break; case 6: //wavers down y = random(height); for(int i = 0; i < 5; i++) { enemies.add(new Waver(new PVector(width+20, y), WARN_TIME + 180*i, 70)); } break; // case default: } } void stop() { exploSound.close(); shotSound.close(); dieSound.close(); warpSound.close(); dinkSound.close(); minim.stop(); super.stop(); } void physicsStep() { explosions.tick(); wave_timer-= warp_speed; if(wave_timer <= 0) { if(wave >= 5 + level) { if(enemies.isEmpty()) { wave_timer = LEVEL_GAP_TIME; wave = 0; if(level == 0) warp_speed += 3; else warp_speed += 1; level++; if(!muted) warpSound.trigger(); } } else { wave++; wave_timer = WAVE_TIME; spawnWave(); } } Iterator ei = enemies.iterator(); while(ei.hasNext()) { Enemy e = (Enemy) ei.next(); if(inRadius(e.pos, player_pos, e.radius) && !dead) { if(!muted) dieSound.trigger(); dead = true; warp_speed = 0;//-warp_speed; explosions.add(new Explosion (player_pos, 200)); // warp_speed = 0; } if(e.tick()) ei.remove(); } for(int i = 0; i < stars.size(); i++) { PVector star = (PVector) stars.get(i); star.x -= warp_speed/NUM_STARS*i; if(star.x < -5*warp_speed) { star.x = width; star.y = random(height); } } if(!dead) { if(keys[UP])player_pos.y -= MOVEMENT_SPEED + level/3.0; if(keys[DOWN])player_pos.y += MOVEMENT_SPEED + level/3.0; if(keys[LEFT])player_pos.x -= MOVEMENT_SPEED + level/3.0; if(keys[RIGHT])player_pos.x += MOVEMENT_SPEED + level/3.0; if(player_pos.x < SHIPSIZE_X) player_pos.x = SHIPSIZE_X; if(player_pos.x > width-SHIPSIZE_X) player_pos.x = width-SHIPSIZE_X; if(player_pos.y < SHIPSIZE_Y) player_pos.y = SHIPSIZE_Y; if(player_pos.y > height - SHIPSIZE_Y) player_pos.y = height - SHIPSIZE_Y; if(bullet != null) { bullet.x += SHOT_SPEED; if(bullet.x > width) bullet = null; } if(keys['Z'] && bullet == null) { if(!muted) shotSound.trigger(); bullet = new PVector(player_pos.x, player_pos.y); } } } void drawingStep() { if(title) { background(0); textFont(font, 32); fill(255); textAlign(CENTER, CENTER); text("Warped!\npress [space] to play", width/2, height/2); } else { if(!paused) drawing_frame++; if(warp_speed == START_SPEED) background(0); else{ fill(0, 96); rect(0, 0, width, height); } for(int i = 0; i < stars.size(); i++) { PVector star = (PVector) stars.get(i); noFill(); strokeWeight(1); stroke(255.0/NUM_STARS*i, 64+255.0/NUM_STARS*i, 255); line(star.x, star.y, star.x + 1 + 4*warp_speed/NUM_STARS*i, star.y); } for(int i = 0; i < enemies.size(); i++) { Enemy e = (Enemy) enemies.get(i); e.draw(); } if(bullet != null) { stroke(255, 230, 192); fill(255); strokeWeight(2); ellipse(bullet.x, bullet.y, 10, 3); } if(!dead) { fill(192); noStroke(); strokeWeight(1); ellipse(player_pos.x, player_pos.y, SHIPSIZE_X, SHIPSIZE_Y); fill(sin(drawing_frame)*255+128, 255*sin(drawing_frame)+360, 255); triangle(player_pos.x - SHIPSIZE_X*1.3, player_pos.y, player_pos.x - SHIPSIZE_X/2, player_pos.y - SHIPSIZE_Y,player_pos.x - SHIPSIZE_X/2, player_pos.y + SHIPSIZE_Y); fill(192); triangle(player_pos.x + SHIPSIZE_X/2, player_pos.y, player_pos.x - SHIPSIZE_X/2, player_pos.y, player_pos.x - SHIPSIZE_X/2, player_pos.y - SHIPSIZE_X/2); triangle(player_pos.x + SHIPSIZE_X, player_pos.y, player_pos.x - SHIPSIZE_X/2, player_pos.y, player_pos.x - SHIPSIZE_X, player_pos.y + SHIPSIZE_X/3); } explosions.draw(); textFont(font, 16); textAlign(LEFT, TOP); fill(255); top = max(top, score); text("Score: "+score+"\nTop: "+top, 8, 8); if(dead) { textAlign(CENTER, CENTER); textFont(font, 16); text("GAME OVER\n press [space] to play again", width/2, height/2); } if(level > 0 && wave == 0 && wave_timer > WAVE_TIME) { textAlign(CENTER, CENTER); textFont(font, 32); text("Sector Clear!\nwarp to next sector", width/2, height/2); } if(level > 0 && wave == 0 && wave_timer < WAVE_TIME) { fill(255, 0, 0); textAlign(CENTER, CENTER); textFont(font, 32); text("Error!\nwarp malfunction", width/2, height/2); } } } void draw() { while(physics_ms_last + PHYS_MS < millis()) { if(!paused && !title) { 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 == ' ' && (dead || title)) newGame(); if(theKey == 'P' && !dead && !title) paused = !paused; if(theKey == 'M') muted = !muted; } void up(int theKey) { println(theKey + " up"); }