/* built with Studio Sketchpad:
* https://sketchpad.cc
*
* observe the evolution of this sketch:
* https://studio.sketchpad.cc/sp/pad/view/ro.SD254$LJZYi/rev.3867
*
* authors:
*
* Zach Denton
* license (unless otherwise specified):
* creative commons attribution-share alike 3.0 license.
* https://creativecommons.org/licenses/by-sa/3.0/
*/
Ship player;
ArrayList boxes;
ArrayList walls;
float boxIncidence;
int lastTime = 0;
int lastWall = 0;
int lastScore = 0;
int wallWidth;
int wallSize = 50;
float speed;
float keyX = 0.8;
float keyZ = 0.9;
float friction = 0.3;
float cameraRotation;
float boxStart = -1000;
float nearClipping = 500;
int score;
PFont font = loadFont("Tahoma");
int SPACE = 32; // spacebar
void setup() {
size(640, 480, OPENGL);
background(0);
fill(200);
pushMatrix();
translate(-2*width, 3*(height/4)+25, boxStart);
rotateX(radians(90));
rect(0, 0, 5*width, -2*boxStart);
popMatrix();
lights();
reset();
}
void reset() {
player = new Ship(new PVector(width/2, 3*(height/4)+25, 200));
boxes = new ArrayList();
walls = new ArrayList();
wallWidth = width;
score = 0;
boxIncidence = 0.05;
speed = 10;
cameraRotation = 0;
}
void draw() {
background(0);
cameraZ = (height/2.0) / tan(PI*60.0 / 360.0);
beginCamera();
camera(width/2.0, height/2.0, cameraZ, width/2.0, 3*(height/4.0), 0, 0, 1, 0);
rotateZ(radians(cameraRotation));
endCamera();
perspective(PI/3, width/height, cameraZ/10.0, cameraZ*10.0);
fill(200);
pushMatrix();
translate(-2*width, 3*(height/4)+25, boxStart);
rotateX(radians(90));
rect(0, 0, 5*width, -2*boxStart);
popMatrix();
lights();
if (player.alive) {
player.draw();
} else {
playerDied();
}
for (int i = 0; i < boxes.size(); i++) {
Box box = (Box) boxes.get(i);
if (box.alive) {
box.draw();
}
}
for (int i = 0; i < walls.size(); i++) {
Box box = (Box) walls.get(i);
if (box.alive) {
box.draw();
}
}
int currentTime = millis();
if (currentTime > lastTime + 30) {
update();
lastTime = currentTime;
}
makeWalls();
}
void makeWalls() {
int currentWall = millis();
if (currentWall > lastWall + 200) {
walls.add(new Box(new PVector((width/2)-(wallWidth/2) - (wallSize/2), 3 * (height / 4) + 10, boxStart)));
walls.add(new Box(new PVector((width/2) + (wallWidth/2) + (wallSize/2), 3 * (height / 4) + 10, boxStart)));
lastWall = currentWall;
}
}
void update() {
if (player.alive) {
player.update();
incrementScore();
}
if (keyPressed) {
if (keyCode == LEFT || key == 'a') {
cameraRotation = constrain(cameraRotation += 0.2, 0, 10);
}
if (keyCode == RIGHT || key == 'd') {
cameraRotation = constrain(cameraRotation -= 0.2, -10, 0);
}
} else {
if (cameraRotation > 0) {
cameraRotation -= 1.5;
if (cameraRotation < 0) {
cameraRotation = 0;
}
} else {
cameraRotation += 1.5;
if (cameraRotation > 0) {
cameraRotation = 0;
}
}
}
if (random(1) < boxIncidence) {
boxes.add(new Box(new PVector(random(0, width), 3 * (height / 4) + 10, boxStart)));
}
for (int i = 0; i < boxes.size(); i++) {
Box box = (Box) boxes.get(i);
if (box.alive) {
box.update();
} else {
boxes.remove(i);
}
}
for (int i = 0; i < walls.size(); i++) {
Box box = (Box) walls.get(i);
if (box.alive) {
box.update();
} else {
walls.remove(i);
}
}
}
void playerDied() {
fill(255, 20, 0);
String notice;
if (score == 1) {
notice = "You scored " + score + " point.";
}
else {
notice = "You scored " + score + " points.";
}
pushMatrix();
translate(0, 0, 200);
textAlign(CENTER);
textFont(font, 24);
text(notice, width/2, 3*(height/4)-48);
textFont(font, 18);
text("Press the Spacebar to restart.", width/2, 3*(height/4)-24);
popMatrix();
noFill();
}
void incrementScore() {
int currentScore = millis();
if (currentScore > lastScore + 1000) {
score++;
lastScore = currentScore;
if (score % 10 == 0) {
boxIncidence += 0.01;
speed += 1.0;
}
}
}
void keyPressed() {
if (keyCode == SPACE) {
reset();
}
player.keyPressed();
}
void keyReleased() {
player.keyReleased();
}
class Ship {
PVector position, velocity, acceleration;
boolean alive;
Ship(PVector p) {
position = p;
velocity = new PVector();
acceleration = new PVector();
alive = true;
}
void draw() {
stroke(0);
beginShape(TRIANGLES);
vertex(position.x - 10, position.y, position.z + 10);
vertex(position.x + 10, position.y, position.z + 10);
vertex(position.x, position.y - 10, position.z);
vertex(position.x, position.y, position.z - 20);
vertex(position.x, position.y - 10, position.z);
vertex(position.x - 10, position.y, position.z + 10);
vertex(position.x + 10, position.y, position.z + 10);
vertex(position.x, position.y - 10, position.z);
vertex(position.x, position.y, position.z - 20);
endShape();
}
void update() {
velocity.add(acceleration);
position.add(velocity);
if (outOfBounds()) {
alive = false;
}
if (velocity.x > 0) {
velocity.x -= friction;
if (velocity.x < 0) {
velocity.x = 0;
}
}
if (velocity.x < 0) {
velocity.x += friction;
if (velocity.x > 0) {
velocity.x = 0;
}
}
}
boolean outOfBounds() {
if (position.x > (width/2) + (wallWidth/2) + (wallSize/2) ||
position.x < (width/2) - (wallWidth/2) - (wallSize/2)) {
return true;
}
return false;
}
void keyPressed() {
if (keyCode == LEFT || key == 'a') {
acceleration.x = -keyX;
}
if (keyCode == RIGHT || key == 'd') {
acceleration.x = keyX;
}
}
void keyReleased() {
if (keyCode == RIGHT || keyCode == LEFT || key == 'a' || key == 'd') {
acceleration.x = 0;
}
}
}
class Box {
PVector position, velocity;
int size = 40;
boolean alive = true;
color boxColor = color(random(50), random(200), random(255));
Box(PVector p) {
position = p;
velocity = new PVector(0, 0, speed);
}
void draw() {
noStroke();
fill(boxColor);
pushMatrix();
translate(position.x, position.y, position.z);
sphere(size);
popMatrix();
}
boolean collision() {
if (position.dist(player.position) <= size) {
return true;
}
return false;
}
void update() {
velocity.z = speed;
position.add(velocity);
if (collision()) {
player.alive = false;
}
if (position.z > nearClipping) {
alive = false;
}
}
}