Skip to content

Instantly share code, notes, and snippets.

@KrabCode
Last active December 9, 2017 21:42
Show Gist options
  • Save KrabCode/80425fc8a64190b3ee15e477490f864e to your computer and use it in GitHub Desktop.
Save KrabCode/80425fc8a64190b3ee15e477490f864e to your computer and use it in GitHub Desktop.
simple helicopter game
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