Last active
December 9, 2017 21:42
-
-
Save KrabCode/80425fc8a64190b3ee15e477490f864e to your computer and use it in GitHub Desktop.
simple helicopter game
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static void main(String[] args) { | |
PApplet.main("MainApp"); | |
} | |
private Cave cave; | |
private Player player; | |
private boolean gameover = false; | |
private boolean inputLocked = false; | |
private int startGameFramecount = 0; | |
private int score = 0; | |
private boolean firstGame = true; | |
private String lastMessage; | |
private String[] gameoverMessages = new String[]{ | |
"go","yes","fun","yay", | |
"good", "whee", "cool","neat", | |
"great","super","extra","excellent", | |
"sorry", "oh no" | |
}; | |
//called once when app starts | |
public void settings() { | |
// size(800,600); | |
fullScreen(); | |
} | |
//called once when app starts | |
public void setup() { | |
restart(); | |
} | |
private void restart(){ | |
cave = new Cave(); | |
player = new Player(); | |
gameover = false; | |
frameRate(30); | |
background(0); | |
startGameFramecount = frameCount; | |
} | |
//called every frame | |
public void draw() { | |
updateTutorial(); | |
redrawBackground(); | |
player.input(); | |
if(!gameover){ | |
//update game state | |
player.update(); | |
cave.update(); | |
checkCollisions(); | |
//draw game objects | |
cave.draw(); | |
player.draw(); | |
if(player.isDead()){ | |
gameover = true; | |
score = frameCount - startGameFramecount; | |
lastMessage = getRandomGameoverMessage(); | |
lockInput(); | |
} | |
} | |
if(gameover){ | |
drawGameover(); | |
tryUnlockInput(); | |
if(!inputLocked && (keyPressed || (mousePressed && mouseY < height/3))){ | |
restart(); | |
} | |
} | |
tryUnlockInput(); | |
} | |
private void updateTutorial() { | |
if(frameCount - startGameFramecount < 20 && firstGame ){ | |
drawTutorial(); | |
} | |
if(frameCount - startGameFramecount > 20){ | |
firstGame = false; | |
} | |
} | |
private void drawTutorial() { | |
stroke(255); | |
fill(100); | |
textSize(100); | |
rect(0,height/3,width, height); | |
textAlign(CENTER); | |
fill(255); | |
text("press", width/2,height/2); | |
} | |
private void lockInput(){ | |
inputLocked = true; | |
} | |
private void tryUnlockInput() { | |
if(!keyPressed && !mousePressed){ | |
inputLocked = false; | |
} | |
} | |
private void drawGameover(){ | |
rectMode(CORNER); | |
textAlign(CENTER); | |
fill(20); | |
rect(0,0,width, height/3); | |
textSize(60); | |
fill(255); | |
text("start", width/2, height/5); | |
stroke(255); | |
textSize(50); | |
text(score, width/2, height - height/3); | |
textSize(30); | |
text(lastMessage, width/2, height - height/5); | |
textSize(60); | |
} | |
private void redrawBackground(){ | |
noStroke(); | |
fill(0, 100); | |
rectMode(CORNER); | |
rect(0,0,width, height); | |
stroke(0); // just to reset noStroke() | |
} | |
private void checkCollisions(){ | |
if(cave.isCollision(player.getRig(), Obstacle.CEILING)){ | |
//bounce down | |
player.applyForce(new PVector(0,10f)); | |
player.applyDamage(10); | |
} | |
if(cave.isCollision(player.getRig(), Obstacle.FLOOR)){ | |
//bounce up | |
player.applyForce(new PVector(0,-10f)); | |
player.applyDamage(10); | |
} | |
//if(cave.isCollision(player.getRig(), Obstacle.FRUIT)){ | |
//score++ | |
//} | |
} | |
private String getRandomGameoverMessage() { | |
return gameoverMessages[(int) random(gameoverMessages.length)]; | |
} | |
enum Obstacle{FLOOR, CEILING, FRUIT} | |
class Cave { | |
float caveHeight = height/2; | |
int xscl = 10; // x scale | |
int yscl = 15; | |
float flatness = 0.5f; // values from 0 to 1 | |
int wallColor; //changed on first update | |
PVector[] ceiling = new PVector[width/ xscl]; | |
PShape ceilingShape; | |
PShape floorShape; | |
Cave(){ | |
ceiling[0] = generate(0, true); | |
for(int x = 1; x < width/ xscl; x++){ | |
ceiling[x] = generate(x,false); | |
} | |
} | |
void update(){ | |
moveCave(); | |
colorMode(HSB); | |
wallColor = color(255); //color(noise(frameCount/10)*255, 150,255); | |
colorMode(RGB); | |
} | |
void draw(){ | |
shape(getTunnelShape(), 0,0); | |
} | |
private void moveCave() { | |
for(int x = 0; x < width/xscl -1; x++){ | |
ceiling[x].y = ceiling[x+1].y; | |
} | |
ceiling[ceiling.length-1] = generate(width/ xscl, false); | |
} | |
private PShape getTunnelShape() { | |
PShape tnl = createShape(GROUP); | |
ceilingShape = getWall(true); | |
floorShape = getWall(false); | |
tnl.addChild(ceilingShape); | |
tnl.addChild(floorShape); | |
return tnl; | |
} | |
boolean isCollision(PShape shape, Obstacle o) { | |
boolean result = false; | |
if (shape != null && o != null && ceilingShape != null && floorShape != null) { | |
for (int i = 0; i < shape.getVertexCount(); i++) { | |
PVector v = shape.getVertex(i); | |
if (o.equals(Obstacle.CEILING) && ceilingShape.contains(v.x, v.y)) { | |
result = true; | |
break; | |
} | |
if (o.equals(Obstacle.FLOOR) && floorShape.contains(v.x, v.y)) { | |
result = true; | |
break; | |
} | |
} | |
} | |
return result; | |
} | |
private PShape getWall(boolean top){ | |
PShape wall = createShape(PShape.PATH); | |
wall.beginShape(); | |
if(top){ //draw the ceiling | |
for(PVector s : ceiling){ | |
wall.vertex(s.x* xscl, s.y); | |
} | |
//go around the screen and connect back up to the start | |
wall.vertex(width+20, ceiling[ceiling.length-1].y); // connect last ceiling point to end of screen | |
wall.vertex(width+20, -20); //go around the screen to fill the whole space | |
wall.vertex(-20, -20); | |
wall.vertex(-20, ceiling[0].y); | |
}else{ //draw the floor | |
//iterate through the ceiling to create the floor as a mirror image exactly 'caveHeight' points below it | |
for(PVector b : ceiling){ | |
wall.vertex(b.x* xscl, b.y+ caveHeight); | |
} | |
//go around the screen and connect back up to the start | |
wall.vertex(width+20, ceiling[ceiling.length-1].y + caveHeight); | |
wall.vertex(width+20, height+20); | |
wall.vertex(-20, height+20); | |
wall.vertex(-20, ceiling[ceiling.length-1].y + caveHeight); | |
} | |
wall.noFill(); | |
wall.endShape(); | |
wall.setStrokeWeight(5); | |
wall.setStroke(wallColor); | |
return wall; | |
} | |
private PVector generate(int x, boolean init){ | |
PVector c = new PVector(x, 0); //must overwrite y | |
if(init){ | |
c.y = 100; | |
}else{ | |
float previous = ceiling[x-1].y; | |
if(random(1)>0.5f){ | |
c.y = previous+yscl; | |
}else{ | |
c.y = previous-yscl; | |
} | |
if(random(1) > flatness){ | |
c.y = previous; | |
} | |
} | |
//cannot leave screen boundary - check and correct for that | |
if(c.y < 20 ) c.y = 20; | |
if(c.y + caveHeight > height - 20 ) c.y = height - 20 - round(caveHeight); | |
return c; | |
} | |
int getCaveMiddle(){ | |
return (int) (this.ceiling[ceiling.length-1].y + caveHeight/2); | |
} | |
} | |
class Player extends GameObject{ | |
float size = 10; | |
private PShape rig; | |
int maxHealth = 50; | |
int health = 50; | |
boolean invulnerability = false; | |
int invulnerabilityStartFrame; | |
int invulnerabilityDuration = 30; | |
Player(){ | |
pos = new PVector(200, height/2); | |
} | |
void update(){ | |
applyGravity(); | |
spd.add(acc); | |
spd.limit(5); | |
pos.add(spd); | |
acc.mult(0); | |
updateRig(); | |
updateInvulnerability(); | |
} | |
void draw(){ | |
drawPlayer(); | |
drawHealth(); | |
} | |
void drawPlayer(){ | |
if(invulnerability){ | |
rig.setFill(color(255, 0, 0)); | |
rig.setStroke(color(255, 0, 0)); | |
}else{ | |
if(keyPressed || mousePressed && mouseY > height/3){ | |
rig.setFill(color(255)); | |
rig.setStroke(color(255)); | |
}else{ | |
rig.setFill(color(0)); | |
rig.setStroke(color(255)); | |
} | |
} | |
shape(rig); | |
} | |
void drawHealth(){ | |
rectMode(CORNER); | |
if(health>0){ | |
float barWidth = width/maxHealth; | |
noStroke(); | |
for(int x = 0; x < health; x++){ | |
if(health < maxHealth/4){ | |
fill(color(255,0,0)); | |
} | |
else if(health < maxHealth/2) { | |
fill(color(255,255,0)); | |
} | |
else{ | |
fill(color(0,255,0)); | |
} | |
rect(x*barWidth, 0, barWidth, 3); | |
} | |
stroke(0); | |
} | |
} | |
void applyDamage(int damage){ | |
if(!invulnerability){ | |
invulnerability = true; | |
invulnerabilityStartFrame = frameCount; | |
health -= damage; | |
} | |
} | |
void updateInvulnerability(){ | |
if(frameCount > invulnerabilityStartFrame + invulnerabilityDuration){ | |
invulnerability = false; | |
} | |
} | |
void input(){ | |
if(keyPressed || mousePressed && mouseY > height / 3){ | |
applyForce(new PVector(0,-1)); | |
} | |
} | |
PShape getRig() { | |
return rig; | |
} | |
void updateRig() { | |
rig = createShape(PShape.PATH); | |
rig.beginShape(); | |
rig.vertex(pos.x, pos.y); | |
rig.vertex(pos.x+size, pos.y); | |
rig.vertex(pos.x+size, pos.y+size); | |
rig.vertex(pos.x, pos.y+size); | |
rig.endShape(CLOSE); | |
rig.setStrokeWeight(2); | |
} | |
boolean isDead() { | |
return health < 1; | |
} | |
} | |
abstract class GameObject{ | |
PVector pos, spd, acc; | |
public GameObject(){ | |
spd = new PVector(0,0); | |
acc = new PVector(0,0); | |
} | |
void applyForce(PVector f){ | |
acc.add(f); | |
} | |
void applyGravity(){ | |
applyForce(new PVector(0, 0.1f)); | |
} | |
void update(){ | |
} | |
abstract void draw(); | |
} | |
class MonsterFactory{ | |
ArrayList<GameObject> liveMonsters = new ArrayList<GameObject>(); | |
public void update() { | |
} | |
public void draw() { | |
} | |
} | |
class Graviton extends GameObject{ | |
@Override | |
void update() { | |
super.update(); | |
} | |
@Override | |
void draw() { | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment