Your browser does not support the canvas tag.

previous        Show / Hide Source        Download        next
/*****************************************************************************************************
 __    __  __    __  ______    ________   _______   ________  ______     ______    _______  ________
 |  |__|  ||  |__|  ||   _  |_ |      __| |    ___| |     ___||   _  |_  |  __  |  |   ____||      __|
 |   __   ||__    __||  |_|  _||   __|   |   _|    |     |___ |  |_|  _||  |__|  ||   |     |   __|
 |  |  |  |   |  |   |   ___|  |  |_____ |  |       |____    ||   ___|  |   __   ||   |____ |  |_____
 |  |  |  |   |__|   |__|      |________||__|       _____|   ||__|      |__|  |__| |_______||________|
 |__|  |__|                                        |_________|
 
 by Klayton Cheuk
 October, 2016
 
 Experience quantum tunnelling!
 Press space to travel forwards with increasing speed.
 Press shift to travel in reverse with increasing speed.
 Press the directional buttons while moving forward to
 turn the tunnel, and the spaceship's direction.
 ******************************************************************************************************/


// declare variables for speed
float speed;
int acceleration;

// declare booleans for button inputs
boolean up, down, left, right, forward, backward;


// declare the ring array
ring[] rings;

// declare the ship
ship mainShip;

void setup() {
  size(800, 600);

  // initialization of variables
  speed = 0;
  acceleration = 0;
  rings = new ring[7];
  mainShip = new ship();

  // initialize, place the rings
  for (int i=0; i < rings.length; i++) {
    rings[i] = new ring(color(random(100, 255), random(100, 255), random(100, 255)));
    rings[i].grow((i+1)*150, false, false, false, false);
  }
}

void draw() {
  background(10, 10, 10);

  // detect button inputs
  detectInput();

  // check current acceleration and modify speed accordingly
  speed = speed + (checkAcceleration()) * 0.1;

  // turn ship
  mainShip.turn(right, left, up, down);

  // grow and display rings
  growRings();
  displayRings();

  // display ship
  mainShip.display();

  up = false;
  down = false;
  right = false;
  left = false;
}

void detectInput() {
  if (keyPressed) {
    if (key == ' ') {
      forward = true;
    }
    if (key == CODED) {
      if (keyCode == UP) {
        up = true;
      }
      if (keyCode == DOWN) {
        down = true;
      }
      if (keyCode == RIGHT) {
        right = true;
      }
      if (keyCode == LEFT) {
        left = true;
      }
      if (keyCode == SHIFT) {
        backward = true;
      }
    }
  }
}

float checkAcceleration() {

  // if the spacebar is pressed, increase the speed.
  if (forward) {
    acceleration += 2;
    forward = false;
    key = 'n';
    return acceleration;
  }

  // if SHIFT is pressed, decrease the speed.
  if (backward) {
    acceleration =- 2;
    backward = false;
    key = 'n';
    return acceleration;
  } 
  // otherwise there is no acceleration.
  return acceleration = 0;
}

void growRings () {
  for (int i=0; i < rings.length; i++) {
    rings[i].grow(speed, right, left, up, down);
  }
}

void displayRings() {
  for (int i=0; i < rings.length; i++) {
    rings[i].display();
  }
}
class ring {

  // declare class variables
  color c;
  float size;
  float speed;  
  PVector position;
  boolean right, left, up, down;

  // constructor
  ring (color c_) {
    c = c_;
    size = 0;
    position = new PVector(width/2, height/2);
  }

  // function to calculate ring growth
  void grow(float speed_, boolean right_, boolean left_, boolean up_, boolean down_) {
    speed = speed_;
    right = right_;
    left = left_;
    up = up_;
    down = down_;
    // add the speed to the size of the ring
    size = size + speed;

    // if the ring is too large
    if (size > 1050) {
      // reset it
      size = 0;
      c = color(random(100, 255), random(100, 255), random(100, 255));
      position = new PVector(width/2, height/2);

      // check for any turn inputs to spawn ring in correct position
      if (right) {
        position.x = -(size/1.75)+width;
      }
      if (left) {
        position.x = size/1.75;
      }
      if (up) {
        position.y = size/1.75;
      }
      if (down) {
        position.y = -(size/1.75)+height;
      }
    }

    // slide rings towards center.
    if (position.x < width/2) {
      position.x = size/1.75;
    }

    if (position.x > width/2) {
      position.x = -(size/1.75)+width;
    }

    if (position.y < height/2) {
      position.y = size/1.75;
    }

    if (position.y > height/2) {
      position.y = -(size/1.75)+height;
    }

    // because of floats being inaccurate?? catch floats close to the center.
    if (position.x < width/2+10 && position.x > width/2-10) {
      position.x = width/2;
    }

    if (position.y < height/2+10 && position.y > height/2-10) {
      position.y = height/2;
    }

    // if the ring becomes too small
    if (size < 0) {
      // reset it on the other end.
      size = 1050;
      c = color(random(100, 255), random(100, 255), random(100, 255));
      position = new PVector(width/2, height/2);
    }
  }

  // display the ring
  void display() {    
    stroke(c);
    strokeWeight(size/25);
    noFill();
    ellipse(position.x, position.y, size, size);
  }
}
class ship {

  // declare variables
  PVector position;
  boolean right, left, up, down;


  // constructor
  ship () {
    position = new PVector(width/2, height/2+75);
  }

  // check for a turn and modify position
  void turn(boolean right_, boolean left_, boolean up_, boolean down_) {
    right = right_;
    left = left_;
    up = up_;
    down = down_;

    // if right is pressed, move left
    if (right && position.x >= width/2-200) {
      position.x -= 25;
    }
    // if right is released, move back
    else if (right == false && position.x < width/2) {
      position.x += 25;
    }

    // if left is pressed, move right
    if (left && position.x <= width/2+200) {
      position.x += 25;
    }
    // if left is released, move back
    else if (left == false && position.x > width/2) {
      position.x -=25;
    }

    // if up is pressed, move down
    if (up && position.y <= height/2+175) {
      position.y += 25;
    }
    // if  up is released, move back
    else if (up == false && position.y > height/2+50) {
      position.y -= 25;
    }

    //if down is pressed, move up
    if (down && position.y >= height/2-150) {
      position.y -= 25;
    }
    // if up is released, move back
    else if (down == false && position.y < height/2+50) {
      position.y += 25;
    }
  }

  // display ship
  void display() {
    noStroke();
    fill(255, 255, 255);
    triangle((position.x)+10, (position.y)-10, (position.x)-10, (position.y)-10, (position.x/2)+200, ((position.y/2)+150));
    triangle((position.x), (position.y)-10, (position.x), (position.y)-20, (position.x/2)+200, (position.y/2)+150);
    fill(100, 100, 100);
    triangle((position.x)+10, (position.y)-10, (position.x)-10, (position.y)-10, position.x, (position.y)-20);
    fill(255, 255, 255);
    ellipse(position.x, position.y-14, 5, 5);
  }
}