keymanager = new KeyManager();
ground = new Ground(sideLen);
sun = new Sun(2000, 250);
moon = new Moon(2000, 50);
float cameraZ = ((height/2.0) / tan(PI*60.0/360.0));
perspective(PI/3.0, width/height, cameraZ/10.0, cameraZ*1000.0);
for (int i = 0; i < n; i++) {
flowers[i] = new Flower(random(-sideLen/2, sideLen/2), random(-sideLen/2, sideLen/2), 0);
void setBackground(float time, float timeScale) {
color dayColor = color(150, 230, 255);
color nightColor = color(20, 0, 50);
background(lerpColor(nightColor, lerpColor(nightColor, dayColor, cos(PI*time/timeScale)), cos(PI*time/timeScale)));
if (time >= 2*timeScale) {
setBackground(time, timeScale);
translate(width/2, height/2, 0);
rotateX(player.facing.x);
rotateZ(player.facing.z);
sun.update(time, timeScale, useLight);
moon.update(time, timeScale, useLight);
for (int i = 0; i < flowers.length; i++) {
numFlowers = (int)random(1500);
if (keymanager.keys[32] && player.location.z == 0) {
player.acceleration.z = -26;
if (player.acceleration.z != 0) {
player.location.z += player.acceleration.z;
if (player.location.z < 0) {
player.acceleration.z += 2;
player.acceleration.z = 0;
if (player.location.z == 0) {
player.acceleration.x = 0;
player.acceleration.y = 0;
if (keymanager.keys[87]) {
player.location.y += cos(player.facing.z)*player.walkingSpeed;
player.location.x += sin(player.facing.z)*player.walkingSpeed;
player.acceleration.y += cos(player.facing.z)*player.walkingSpeed;
player.acceleration.x += sin(player.facing.z)*player.walkingSpeed;
if (keymanager.keys[83]) {
player.location.y -= cos(player.facing.z)*player.walkingSpeed;
player.location.x -= sin(player.facing.z)*player.walkingSpeed;
player.acceleration.y -= cos(player.facing.z)*player.walkingSpeed;
player.acceleration.x -= sin(player.facing.z)*player.walkingSpeed;
if (keymanager.keys[65]) {
player.location.x += cos(player.facing.z)*player.walkingSpeed;
player.location.y -= sin(player.facing.z)*player.walkingSpeed;
player.acceleration.x += cos(player.facing.z)*player.walkingSpeed;
player.acceleration.y -= sin(player.facing.z)*player.walkingSpeed;
if (keymanager.keys[68]) {
player.location.x -= cos(player.facing.z)*player.walkingSpeed;
player.location.y += sin(player.facing.z)*player.walkingSpeed;
player.acceleration.x -= cos(player.facing.z)*player.walkingSpeed;
player.acceleration.y += sin(player.facing.z)*player.walkingSpeed;
player.location.add(player.acceleration);
if (keymanager.keys[37]) {
if (keymanager.keys[38]) {
if (keymanager.keys[39]) {
if (keymanager.keys[40]) {
if (player.facing.x < 0) {
} else if (player.facing.x > PI) {
float collisionDistance = 500;
if (player.location.x > sideLen/2-collisionDistance) {
player.location.x = sideLen/2-collisionDistance;
} else if (player.location.x < -sideLen/2+collisionDistance) {
player.location.x = -sideLen/2+collisionDistance;
if (player.location.y > sideLen/2-collisionDistance) {
player.location.y = sideLen/2-collisionDistance;
} else if (player.location.y < -sideLen/2+collisionDistance) {
player.location.y = -sideLen/2+collisionDistance;
if (keymanager.keys[16]) {
player.crouchChange = player.playerHeight/2;
player.walkingSpeed = player.regularSpeed/2;
player.walkingSpeed = player.regularSpeed;
Flower(float x, float y, float z) {
void simpleTopFlower(float scale) {
color innerColor = color(random(255),random(255),random(255));
color topColor = color(random(100, 255),random(100, 255),random(100, 255));
innerColor = color(red(topColor)-random(100), green(topColor)-random(100), blue(topColor)-random(100));
stem.setStroke(color(random(50, 150), random(150, 250), random(50, 150)));
stem.strokeWeight(random(2));
int joints = (int)random(5);
for(int i = 0; i < joints; i++) {
x += random(-10*scale, 10*scale);
y += random(-10*scale, 10*scale);
z += random(1*scale, 10*scale);
float[] heights = new float[10];
for (int i = 0; i < lengths.length; i++) {
lengths[i] = random(5*scale, 15*scale);
top.setFill(color(255, 150, 200));
for (int i = 0; i < lengths.length; i++) {
heights[i] = random(-10, 10);
top.vertex(x+lengths[i]*cos(2*PI*i/lengths.length),
y+lengths[i]*sin(2*PI*i/lengths.length), z+heights[i]);
for (int i = 0; i < lengths.length; i++) {
temp = random(2*scale, 8*scale);
inner.setFill(color(255, 225, 150));
inner.setFill(innerColor);
for (int i = 0; i < lengths.length; i++) {
inner.vertex(x+lengths[i]*cos(2*PI*i/lengths.length),
y+lengths[i]*sin(2*PI*i/lengths.length), z+1+7);
points = new PVector[20];
for (int i = 0; i < points.length; i++) {
points[i] = new PVector();
for (int i = 0; i < points.length; i++) {
top.vertex(points[i].x, points[i].y,
top.setFill(color(255, 150, 200));
for (int i = 0; i < lengths.length; i++) {
fill(color(255, 150, 200));
for (int i = 0; i < lengths.length; i++) {
vertex(lengths[i]*sin(2*PI*i/lengths.length),
lengths[i]*sin(2*PI*i/lengths.length), 0);
terrain = createShape(GROUP);
terrain.addChild(createGround(sideLen));
terrain.addChild(createWalls(sideLen, 1000));
PImage groundTexture(float lenSide) {
int sideLen = (int)lenSide/8;
PImage img = createImage(sideLen, sideLen, RGB);
for(int i = 0; i < sideLen; i++) {
for (int j = 0; j < sideLen; j++) {
if (noise(i/10, j/10) < .5) {
img.pixels[i*sideLen+j] = color(150, 255, 130);
img.pixels[i*sideLen+j] = color(255, 0, 0);
PShape createGround(float sideLen) {
PShape g = createShape(RECT, -sideLen/2, -sideLen/2, sideLen, sideLen);
g.setFill(color(150, 255, 130));
PShape createWalls(float sideLen, float h) {
color wallColor = color(100);
PShape w = createShape(GROUP);
PShape temp = createShape();
temp.vertex(-sideLen, -sideLen, 0);
temp.vertex(-sideLen, -sideLen, h);
temp.vertex(sideLen, -sideLen, h);
temp.vertex(sideLen, -sideLen, 0);
temp.vertex(sideLen, sideLen, 0);
temp.vertex(sideLen, sideLen, h);
temp.vertex(sideLen, -sideLen, h);
temp.vertex(sideLen, -sideLen, 0);
temp.vertex(sideLen, sideLen, 0);
temp.vertex(sideLen, sideLen, h);
temp.vertex(-sideLen, sideLen, h);
temp.vertex(-sideLen, sideLen, 0);
temp.vertex(-sideLen, -sideLen, 0);
temp.vertex(-sideLen, -sideLen, h);
temp.vertex(-sideLen, sideLen, h);
temp.vertex(-sideLen, sideLen, 0);
w.addChild(makeTower(-sideLen-towerSide, -sideLen-towerSide, 2*towerSide, h+2*towerSide, towerSide/3, wallColor));
w.addChild(makeTower(sideLen+towerSide, -sideLen-towerSide, 2*towerSide, h+2*towerSide, towerSide/3, wallColor));
w.addChild(makeTower(sideLen+towerSide, sideLen+towerSide, 2*towerSide, h+2*towerSide, towerSide/3, wallColor));
w.addChild(makeTower(-sideLen-towerSide, sideLen+towerSide, 2*towerSide, h+2*towerSide, towerSide/3, wallColor));
PShape makeTower(float x, float y, float sideWidth, float h, float topH, color wallColor) {
PShape tower = createShape(GROUP);
PShape wall = createShape();
wall.vertex(x-sideWidth/2, y-sideWidth/2, 0);
wall.vertex(x-sideWidth/2, y-sideWidth/2, h);
wall.vertex(x-sideWidth/2, y+sideWidth/2, h);
wall.vertex(x-sideWidth/2, y+sideWidth/2, 0);
wall.vertex(x+sideWidth/2, y-sideWidth/2, 0);
wall.vertex(x+sideWidth/2, y-sideWidth/2, h);
wall.vertex(x+sideWidth/2, y+sideWidth/2, h);
wall.vertex(x+sideWidth/2, y+sideWidth/2, 0);
wall.vertex(x+sideWidth/2, y+sideWidth/2, 0);
wall.vertex(x+sideWidth/2, y+sideWidth/2, h);
wall.vertex(x-sideWidth/2, y+sideWidth/2, h);
wall.vertex(x-sideWidth/2, y+sideWidth/2, 0);
wall.vertex(x+sideWidth/2, y-sideWidth/2, 0);
wall.vertex(x+sideWidth/2, y-sideWidth/2, h);
wall.vertex(x-sideWidth/2, y-sideWidth/2, h);
wall.vertex(x-sideWidth/2, y-sideWidth/2, 0);
for(int i = 0; i < keys.length; i++) {
Moon(float h, float sideLen) {
void update(float time, float timeScale, boolean useLight) {
translate(sin(PI*(time/timeScale+1))*10000, 0, cos(PI*(time/timeScale+1))*h);
translate(sin(PI*(time/timeScale+1))*-10000, 0, cos(PI*(time/timeScale+1))*-h);
pointLight(cos(PI*(time/timeScale+1))*50, cos(PI*(time/timeScale+1))*50, cos(PI*(time/timeScale+1))*100, sin(PI*(time/timeScale+1))*10000, 0, cos(PI*(time/timeScale+1))*h);
float playerHeight = 500;
location = new PVector(0, 0, 0);
acceleration = new PVector();
facing = new PVector(HALF_PI, 0, PI);
translate(location.x, location.y, location.z-playerHeight+crouchChange);
translate(-location.x, -location.y, -(location.z-playerHeight+crouchChange));
Sun(float h, float sideLen) {
void update(float time, float timeScale, boolean useLight) {
translate(sin(PI*time/timeScale)*10000, 0, cos(PI*time/timeScale)*h);
translate(sin(PI*time/timeScale)*-10000, 0, cos(PI*time/timeScale)*-h);
pointLight(cos(PI*time/timeScale)*255, cos(PI*time/timeScale)*255, cos(PI*time/timeScale)*255, sin(PI*time/timeScale)*10000, 0, cos(PI*time/timeScale)*h);