From 1c39199cc32ddfbe523a1181082df7528b252827 Mon Sep 17 00:00:00 2001 From: Daniel <59575049+lumijiez@users.noreply.github.com> Date: Mon, 27 Nov 2023 01:06:16 +0200 Subject: [PATCH] Add files via upload --- Balloon.pde | 85 +++++++++++++ Bird.pde | 308 +++++++++++++++++++++++++++++++++++++++++++++ Block.pde | 16 +++ Butterfly.pde | 67 ++++++++++ Colors.pde | 12 ++ Config.pde | 27 ++++ FlyingCreature.pde | 273 ++++++++++++++++++++++++++++++++++++++++ Main.pde | 77 ++++++++++++ Terrain.pde | 142 +++++++++++++++++++++ Utils.pde | 86 +++++++++++++ 10 files changed, 1093 insertions(+) create mode 100644 Balloon.pde create mode 100644 Bird.pde create mode 100644 Block.pde create mode 100644 Butterfly.pde create mode 100644 Colors.pde create mode 100644 Config.pde create mode 100644 FlyingCreature.pde create mode 100644 Main.pde create mode 100644 Terrain.pde create mode 100644 Utils.pde diff --git a/Balloon.pde b/Balloon.pde new file mode 100644 index 0000000..bb2c6b8 --- /dev/null +++ b/Balloon.pde @@ -0,0 +1,85 @@ +class Balloon { + float x; + float y; + float z; + float radius; + float angle; + PVector velocity; + PVector acceleration; + float lastWindChangeTime; + + Balloon(float x, float y, float z) { + this.x = x; + this.y = y; + this.z = z; + this.radius = 50; + this.velocity = new PVector(0, 0, 0); + this.acceleration = new PVector(0, 0, 0); + this.angle = 0; + } + + void applyForce(PVector force) { + acceleration.add(force); + } + + void applyBuoyancy() { + PVector buoyantForce = new PVector(0, 0, buoyancy); + applyForce(buoyantForce); + } + + void applyDamping() { + PVector dampingForce = velocity.copy().mult(-damping); + applyForce(dampingForce); + } + + void draw() { + pushMatrix(); + + if (millis() - lastWindChangeTime > windChangeInterval) { + wind = PVector.random3D(); + wind.mult(20); + lastWindChangeTime = millis(); + } + + rotateX(HALF_PI); + + z += 2; + + translate(x, y, z); + + fill(255, 0, 0); + noStroke(); + sphere(radius); + stroke(1); + + drawLeg(-radius / 2, -radius / 2); + drawLeg(radius / 2, -radius / 2); + drawLeg(-radius / 2, radius / 2); + drawLeg(radius / 2, radius / 2); + + translate(0, 0, -75); + box(70, 70, 25); + + applyBuoyancy(); + applyDamping(); + + velocity.add(acceleration); + x += velocity.x; + y += velocity.y; + z += velocity.z; + + acceleration.mult(0); + angle += 0.01; + + popMatrix(); + } + + void drawLeg(float x, float y) { + pushMatrix(); + int legHeight = 80; + translate(x, y, -legHeight / 2); + fill(yellow); + box(5, 5, legHeight); + popMatrix(); + } +} diff --git a/Bird.pde b/Bird.pde new file mode 100644 index 0000000..152e214 --- /dev/null +++ b/Bird.pde @@ -0,0 +1,308 @@ +class Bird extends FlyingCreature { + float x; + float y; + float z; + float hp; + float goBackX, goBackY, goBackZ; + float wingAngle = PI; + int wingDirection = 1; + float wingFlapSpeed = 0.05; + float wingFlapRange = QUARTER_PI; + float perlinOffsetX; + float perlinOffsetY; + float perlinOffsetZ; + float actualOffset = 1; + boolean isCatching = false; + boolean needToGoBack = false; + Butterfly butterfly = null; + color fillcolor = color(0, 0, 0); + + Bird(float x, float y, float z) { + super(x, y, z); + this.perlinOffsetX = random(1000); + this.perlinOffsetY = random(1000); + this.perlinOffsetZ = random(1000); + } + + void catchButterfly() { + ArrayList < Butterfly > availableButterflies = new ArrayList < > (); + for (Butterfly butterfly: terra.butterflies) { + if (!butterfly.isBeingCaught) { + availableButterflies.add(butterfly); + } + } + + if (!availableButterflies.isEmpty()) { + int randomIndex = (int) random(availableButterflies.size()); + + Butterfly randomButterfly = availableButterflies.get(randomIndex); + + butterfly = randomButterfly; + isCatching = true; + fillcolor = color(255, 255, 255); + + randomButterfly.isBeingCaught = true; + goBackX = x; + goBackY = y; + goBackZ = z; + } + + } + + void uncatchButterfly() { + terra.butterflies.remove(butterfly); + terra.addButterfly(); + butterfly = null; + isCatching = false; + needToGoBack = true; + fillcolor = color(0, 0, 0); + hp = 100; + } + + void tryGoBack() { + this.hp -= 0.1; + pushMatrix(); + rotateX(HALF_PI); + + if (dist(x, y, z, goBackX, goBackY, goBackZ) > 10) { + int speed = 5; + float dirX = goBackX - x; + float dirY = goBackY - y; + float dirZ = goBackZ - z; + + float magnitude = sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); + dirX /= magnitude; + dirY /= magnitude; + dirZ /= magnitude; + + x += dirX * speed; + y += dirY * speed; + z += dirZ * speed; + } else { + popMatrix(); + needToGoBack = false; + return; + } + + translate(x, y, z); + + translate(0, 0, 20); + float colorValue = map(hp, 0, 100, 0, 1); + colorValue = constrain(colorValue, 0, 1); + + color boxColor = lerpColor(color(255, 0, 0), color(0, 255, 0), colorValue); + fill(boxColor); + rotateX(HALF_PI); + rotateZ(PI); + translate(-hp/2, -10, 0); + text("Not catching!", 0, 0); + translate(0, -10, 0); + text("HP: " + nf(hp, 0, 2), 0, 0); + translate(hp/2, 20, 0); + rotateZ(-PI); + rotateX(-HALF_PI); + rotateZ(HALF_PI); + translate(0, 0, 0); + box(2, hp, 2); + rotateZ(-HALF_PI); + translate(0, 0, 0); + + translate(0, 0, -20); + + fill(fillcolor); + box(10, 10, 10); + + translate(-6, 3, 5); + box(6, 6, 6); + + translate(6, -3, -5); + translate(0, -5, 5); + + float wingFlap = sin(wingAngle) * wingFlapRange; + rotateX(wingFlap); + + wingDirection = (wingAngle >= PI + wingFlapRange || wingAngle <= PI - wingFlapRange) ? -wingDirection : wingDirection; + + wingAngle += wingDirection * wingFlapSpeed; + + fill(fillcolor); + drawWing(10, 30); + + rotateX(-wingFlap); + translate(5, 5); + rotateZ(HALF_PI); + + rotateX(wingFlap); + + drawWing(10, 30); + + popMatrix(); + } + + @Override + void draw() { + this.hp -= 0.1; + + if (!isCatching && random(1) < 0.01) { + catchButterfly(); + } + + if (needToGoBack) { + tryGoBack(); + return; + } + + if (!isCatching) { + pushMatrix(); + rotateX(HALF_PI); + + translate(x, y, z); + + translate(0, 0, 20); + float colorValue = map(hp, 0, 100, 0, 1); + colorValue = constrain(colorValue, 0, 1); + + color boxColor = lerpColor(color(255, 0, 0), color(0, 255, 0), colorValue); + fill(boxColor); + rotateX(HALF_PI); + rotateZ(PI); + translate(-hp/2, -10, 0); + text("Not catching!", 0, 0); + translate(0, -10, 0); + text("HP: " + nf(hp, 0, 2), 0, 0); + translate(hp/2, 20, 0); + rotateZ(-PI); + rotateX(-HALF_PI); + rotateZ(HALF_PI); + translate(0, 0, 0); + box(2, hp, 2); + rotateZ(-HALF_PI); + translate(0, 0, 0); + + translate(0, 0, -20); + + actualOffset += 10; + + z = map(noise(perlinOffsetX, actualOffset * 0.0002), 0, 1, 600, 1200); + x = map(noise(perlinOffsetY, actualOffset * 0.0001), 0, 1, 0, terrainLength * cubeWidth); + y = map(noise(perlinOffsetZ, actualOffset * 0.0001), 0, 1, 0, terrainWidth * cubeWidth); + + fill(fillcolor); + box(10, 10, 10); + + translate(-6, 3, 5); + box(6, 6, 6); + + translate(6, -3, -5); + translate(0, -5, 5); + + float wingFlap = sin(wingAngle) * wingFlapRange; + rotateX(wingFlap); + + wingDirection = (wingAngle >= PI + wingFlapRange || wingAngle <= PI - wingFlapRange) ? -wingDirection : wingDirection; + + wingAngle += wingDirection * wingFlapSpeed; + + fill(fillcolor); + drawWing(10, 30); + + rotateX(-wingFlap); + translate(5, 5); + rotateZ(HALF_PI); + + rotateX(wingFlap); + + drawWing(10, 30); + + popMatrix(); + + } else { + this.hp -= 0.1; + pushMatrix(); + rotateX(HALF_PI); + + float dirX = butterfly.x - x; + float dirY = butterfly.y - y; + float dirZ = butterfly.z - z; + + float magnitude = sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); + dirX /= magnitude; + dirY /= magnitude; + dirZ /= magnitude; + + float speed = 4.0; + + x += dirX * speed; + y += dirY * speed; + z += dirZ * speed; + + translate(x, y, z); + + translate(0, 0, 20); + float colorValue = map(hp, 0, 100, 0, 1); + colorValue = constrain(colorValue, 0, 1); + + color boxColor = lerpColor(color(255, 0, 0), color(0, 255, 0), colorValue); + fill(boxColor); + rotateX(HALF_PI); + rotateZ(PI); + translate(-hp/2, -10, 0); + text("Catching!", 0, 0); + translate(0, -10, 0); + text("HP: " + nf(hp, 0, 2), 0, 0); + translate(hp/2, 20, 0); + rotateZ(-PI); + rotateX(-HALF_PI); + rotateZ(HALF_PI); + translate(0, 0, 0); + box(2, hp, 2); + rotateZ(-HALF_PI); + translate(0, 0, 0); + + translate(0, 0, -20); + + fill(fillcolor); + box(10, 10, 10); + + translate(-6, 3, 5); + box(6, 6, 6); + + translate(6, -3, -5); + translate(0, -5, 5); + + float wingFlap = sin(wingAngle) * wingFlapRange; + rotateX(wingFlap); + + wingDirection = (wingAngle >= PI + wingFlapRange || wingAngle <= PI - wingFlapRange) ? -wingDirection : wingDirection; + + wingAngle += wingDirection * wingFlapSpeed; + + fill(fillcolor); + drawWing(10, 30); + + rotateX(-wingFlap); + translate(5, 5); + + rotateZ(HALF_PI); + rotateX(wingFlap); + + drawWing(10, 30); + + if (dist(x, y, z, butterfly.x, butterfly.y, butterfly.z) < 20) uncatchButterfly(); + + popMatrix(); + } + + if (hp < 0) hp = 100; + } + + @Override + void drawWing(float width, float length) { + beginShape(); + vertex(-width / 2, 0); + vertex(width / 2, 0); + vertex(width / 4, -length); + vertex(-width / 4, -length); + endShape(CLOSE); + } +} diff --git a/Block.pde b/Block.pde new file mode 100644 index 0000000..986007f --- /dev/null +++ b/Block.pde @@ -0,0 +1,16 @@ +class Block { + int x; + int y; + float h; + boolean isTree; + boolean isFlower; + int treeSize; + color treeColor; + Block(int x, int y, float h, color treeColor, int treeSize) { + this.x = x; + this.y = y; + this.h = h; + this.treeColor = treeColor; + this.treeSize = treeSize; + } +} diff --git a/Butterfly.pde b/Butterfly.pde new file mode 100644 index 0000000..d3172b1 --- /dev/null +++ b/Butterfly.pde @@ -0,0 +1,67 @@ +class Butterfly { + float x; + float y; + float z; + float wingAngle = PI; + int wingDirection = 1; + float wingFlapSpeed = 0.05; + float wingFlapRange = QUARTER_PI; + float perlinOffsetX; + float perlinOffsetY; + float perlinOffsetZ; + boolean isBeingCaught = false; + + Butterfly(float x, float y, float z) { + this.x = x; + this.y = y; + this.z = z; + this.perlinOffsetX = random(1000); + this.perlinOffsetY = random(1000); + this.perlinOffsetZ = random(1000); + } + + void draw() { + pushMatrix(); + rotateX(HALF_PI); + + z = map(noise(perlinOffsetX, millis() * 0.0002), 0, 1, 400, 600); + x = map(noise(perlinOffsetY, millis() * 0.0001), 0, 1, 0, terrainLength * cubeWidth); + y = map(noise(perlinOffsetZ, millis() * 0.0001), 0, 1, 0, terrainWidth * cubeWidth); + + fill(0, 191, 255); + translate(x, y, z); + box(3, 3, 3); + translate(-1, 1, 2); + box(2, 2, 2); + translate(1, -2, -1); + + float wingFlap = sin(wingAngle) * wingFlapRange; + rotateX(wingFlap); + + wingDirection = (wingAngle >= PI + wingFlapRange || wingAngle <= PI - wingFlapRange) ? -wingDirection : wingDirection; + + wingAngle += wingDirection * wingFlapSpeed; + + fill(0, 191, 255); + drawWing(3, 5); + + rotateX(-wingFlap); + translate(1, 1); + rotateZ(HALF_PI); + + rotateX(wingFlap); + + fill(0, 191, 255); + drawWing(3, 5); + popMatrix(); + } + + void drawWing(float width, float length) { + beginShape(); + vertex(-width / 2, 0); + vertex(width / 2, 0); + vertex(width / 4, -length); + vertex(-width / 4, -length); + endShape(CLOSE); + } +} diff --git a/Colors.pde b/Colors.pde new file mode 100644 index 0000000..ac56210 --- /dev/null +++ b/Colors.pde @@ -0,0 +1,12 @@ +color yellow = color(255, 255, 0); +color green = color(0, 255, 0); +color blue = color(0, 0, 255); +color red = color(255, 0, 0); +color darkgreen = color(0, 100, 0); +color autumn1 = color(183, 65, 14); +color autumn2 = color(204, 85, 0); +color autumn3 = color(255, 215, 0); +color autumn4 = color(255, 204, 0); +color autumn5 = color(139, 69, 19); +color autumn6 = color(101, 67, 33); +color autumn7 = color(107, 142, 35); diff --git a/Config.pde b/Config.pde new file mode 100644 index 0000000..16f293f --- /dev/null +++ b/Config.pde @@ -0,0 +1,27 @@ +int terrainLength = 1000; +int terrainWidth = 1000; + +int minTreeHeight = 20; +int maxTreeHeight = 70; + +float noiseStep = 0.02; +float noiseScale = 5; +long randomSeedValue = 55; +long noiseSeedValue = 254; +int noiseOctaves = 4; +float noiseFalloff = 0.5; + +int cubeWidth = 20; +int cubeLength = 20; +float cubeSize = 100; + +float camSpeed = 20; +float sensitivity = 0.01; +float pitch = 0; +float yaw = 0; +int farPlaneDistance = 4000; + +float maxForce = 0.1; +float buoyancy = -0.02; +float damping = 0.995; +float windChangeInterval = 3000; diff --git a/FlyingCreature.pde b/FlyingCreature.pde new file mode 100644 index 0000000..29a5fbe --- /dev/null +++ b/FlyingCreature.pde @@ -0,0 +1,273 @@ +abstract class FlyingCreature { + float x; + float y; + float z; + float hp; + float goBackX, goBackY, goBackZ; + float wingAngle = PI; + int wingDirection = 1; + float wingFlapSpeed = 0.05; + float wingFlapRange = QUARTER_PI; + float perlinOffsetX; + float perlinOffsetY; + float perlinOffsetZ; + float actualOffset = 1; + boolean isCatching = false; + boolean needToGoBack = false; + Butterfly butterfly = null; + color fillcolor = color(0, 0, 0); + + FlyingCreature(float x, float y, float z) { + this.x = x; + this.y = y; + this.z = z; + this.perlinOffsetX = random(1000); + this.perlinOffsetY = random(1000); + this.perlinOffsetZ = random(1000); + } + + void catchButterfly() { + ArrayList < Butterfly > availableButterflies = new ArrayList < > (); + for (Butterfly butterfly: terra.butterflies) { + if (!butterfly.isBeingCaught) { + availableButterflies.add(butterfly); + } + } + + if (!availableButterflies.isEmpty()) { + int randomIndex = (int) random(availableButterflies.size()); + + Butterfly randomButterfly = availableButterflies.get(randomIndex); + + butterfly = randomButterfly; + isCatching = true; + fillcolor = color(255, 255, 255); + + randomButterfly.isBeingCaught = true; + goBackX = x; + goBackY = y; + goBackZ = z; + } + + } + + void uncatchButterfly() { + terra.butterflies.remove(butterfly); + terra.addButterfly(); + butterfly = null; + isCatching = false; + needToGoBack = true; + fillcolor = color(0, 0, 0); + hp = 100; + } + + void tryGoBack() { + this.hp -= 0.1; + pushMatrix(); + rotateX(HALF_PI); + + if (dist(x, y, z, goBackX, goBackY, goBackZ) > 10) { + int speed = 5; + float dirX = goBackX - x; + float dirY = goBackY - y; + float dirZ = goBackZ - z; + + // Normalize the direction vector + float magnitude = sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); + dirX /= magnitude; + dirY /= magnitude; + dirZ /= magnitude; + + x += dirX * speed; + y += dirY * speed; + z += dirZ * speed; + } else { + popMatrix(); + needToGoBack = false; + x = goBackX; + y = goBackY; + z = goBackZ; + return; + } + + translate(x, y, z); + + translate(0, 0, 20); + float colorValue = map(hp, 0, 100, 0, 1); + colorValue = constrain(colorValue, 0, 1); + + color boxColor = lerpColor(color(255, 0, 0), color(0, 255, 0), colorValue); + fill(boxColor); + box(2, hp / 10, 2); + + translate(0, 0, -20); + + fill(fillcolor); + box(10, 10, 10); + + translate(-6, 3, 5); + box(6, 6, 6); + + translate(6, -3, -5); + translate(0, -5, 5); + + float wingFlap = sin(wingAngle) * wingFlapRange; + rotateX(wingFlap); + + wingDirection = (wingAngle >= PI + wingFlapRange || wingAngle <= PI - wingFlapRange) ? -wingDirection : wingDirection; + + wingAngle += wingDirection * wingFlapSpeed; + + fill(fillcolor); + drawWing(10, 30); + + rotateX(-wingFlap); + translate(5, 5); + rotateZ(HALF_PI); + + rotateX(wingFlap); + + drawWing(10, 30); + + popMatrix(); + } + + void draw() { + this.hp -= 0.1; + + if (!isCatching && random(1) < 0.01) { + catchButterfly(); + } + + if (needToGoBack) { + tryGoBack(); + return; + } + + if (!isCatching) { + pushMatrix(); + rotateX(HALF_PI); + + translate(x, y, z); + + translate(0, 0, 20); + float colorValue = map(hp, 0, 100, 0, 1); + colorValue = constrain(colorValue, 0, 1); + + color boxColor = lerpColor(color(255, 0, 0), color(0, 255, 0), colorValue); + fill(boxColor); + box(2, hp / 10, 2); + + translate(0, 0, -20); + + actualOffset += 10; + + z = map(noise(perlinOffsetX, actualOffset * 0.0002), 0, 1, 600, 1200); + x = map(noise(perlinOffsetY, actualOffset * 0.0001), 0, 1, 0, terrainLength * cubeWidth); + y = map(noise(perlinOffsetZ, actualOffset * 0.0001), 0, 1, 0, terrainWidth * cubeWidth); + + fill(fillcolor); + box(10, 10, 10); + + translate(-6, 3, 5); + box(6, 6, 6); + + translate(6, -3, -5); + translate(0, -5, 5); + + float wingFlap = sin(wingAngle) * wingFlapRange; + rotateX(wingFlap); + + wingDirection = (wingAngle >= PI + wingFlapRange || wingAngle <= PI - wingFlapRange) ? -wingDirection : wingDirection; + + wingAngle += wingDirection * wingFlapSpeed; + + fill(fillcolor); + drawWing(10, 30); + + rotateX(-wingFlap); + translate(5, 5); + rotateZ(HALF_PI); + + rotateX(wingFlap); + + drawWing(10, 30); + + popMatrix(); + + } else { + this.hp -= 0.1; + pushMatrix(); + rotateX(HALF_PI); + + float dirX = butterfly.x - x; + float dirY = butterfly.y - y; + float dirZ = butterfly.z - z; + + float magnitude = sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); + dirX /= magnitude; + dirY /= magnitude; + dirZ /= magnitude; + + float speed = 4.0; + + x += dirX * speed; + y += dirY * speed; + z += dirZ * speed; + + translate(x, y, z); + + translate(0, 0, 20); + float colorValue = map(hp, 0, 100, 0, 1); + colorValue = constrain(colorValue, 0, 1); + + color boxColor = lerpColor(color(255, 0, 0), color(0, 255, 0), colorValue); + fill(boxColor); + box(2, hp / 10, 2); + + translate(0, 0, -20); + + fill(fillcolor); + box(10, 10, 10); + + translate(-6, 3, 5); + box(6, 6, 6); + + translate(6, -3, -5); + translate(0, -5, 5); + + float wingFlap = sin(wingAngle) * wingFlapRange; + rotateX(wingFlap); + + wingDirection = (wingAngle >= PI + wingFlapRange || wingAngle <= PI - wingFlapRange) ? -wingDirection : wingDirection; + + wingAngle += wingDirection * wingFlapSpeed; + + fill(fillcolor); + drawWing(10, 30); + + rotateX(-wingFlap); + translate(5, 5); + + rotateZ(HALF_PI); + rotateX(wingFlap); + + drawWing(10, 30); + + if (dist(x, y, z, butterfly.x, butterfly.y, butterfly.z) < 20) uncatchButterfly(); + + popMatrix(); + } + + if (hp < 0) hp = 100; + } + + void drawWing(float width, float length) { + beginShape(); + vertex(-width / 2, 0); + vertex(width / 2, 0); + vertex(width / 4, -length); + vertex(-width / 4, -length); + endShape(CLOSE); + } +} diff --git a/Main.pde b/Main.pde new file mode 100644 index 0000000..28a2e11 --- /dev/null +++ b/Main.pde @@ -0,0 +1,77 @@ +PVector camPosition = new PVector(1000, -700, 700); +PVector lookAt = new PVector(0, 0, -1); +PVector wind = new PVector(5, -8, 0); +Terrain terra = new Terrain(); +Balloon balloon = new Balloon(50 * 20, 50 * 20, 20 * 20); + +void setup() { + fullScreen(P3D); + frameRate(144); + //size(800, 600, P3D); + + randomSeed(randomSeedValue); + noiseSeed(noiseSeedValue); + noiseDetail(noiseOctaves, noiseFalloff); + + terra.setup(); + terra.reloadTrees(); +} + +void keyPressed() { + if (keyCode == UP) { + noiseScale += 0.25; + terra.reloadTrees(); + } else if (keyCode == DOWN) { + noiseScale -= 0.25; + terra.reloadTrees(); + } +} + +void draw() { + background(173, 216, 230); + lights(); + + yaw += -1 * sensitivity * (mouseX - pmouseX); + pitch += sensitivity * (mouseY - pmouseY); + + pitch = constrain(pitch, -HALF_PI + 0.01, HALF_PI - 0.01); + + float cosPitch = cos(pitch); + float sinPitch = sin(pitch); + float cosYaw = cos(yaw); + float sinYaw = sin(yaw); + + lookAt.x = sinYaw * cosPitch; + lookAt.y = sinPitch; + lookAt.z = cosYaw * cosPitch; + + if (keyPressed) { + if (key == 'g') terra.applyGravity(); + + if (key == 'w') camPosition.add(PVector.mult(lookAt, camSpeed)); + + if (key == 's') camPosition.sub(PVector.mult(lookAt, camSpeed)); + + if (key == 'a') { + PVector left = lookAt.cross(new PVector(0, -1, 0)); + camPosition.add(PVector.mult(left, camSpeed)); + } + + if (key == 'd') { + PVector right = lookAt.cross(new PVector(0, -1, 0)); + camPosition.sub(PVector.mult(right, camSpeed)); + } + + if (key == 'r') terra.blocks.get(0).x += 1; + if (key == 'f') terra.blocks.get(0).y += 1; + } + + camera(camPosition.x, camPosition.y, camPosition.z, camPosition.x + lookAt.x, camPosition.y + lookAt.y, camPosition.z + lookAt.z, 0, 1, 0); + perspective(PI / 3.0, float(width) / float(height), 1, farPlaneDistance); + + terra.drawTerrain(camPosition); + + PVector windForce = wind.copy().mult(0.1); + balloon.applyForce(windForce); + balloon.draw(); +} diff --git a/Terrain.pde b/Terrain.pde new file mode 100644 index 0000000..031bc2d --- /dev/null +++ b/Terrain.pde @@ -0,0 +1,142 @@ +class Terrain { + ArrayList < Block > blocks = new ArrayList < > (); + ArrayList < Bird > birds = new ArrayList < > (); + ArrayList < Butterfly > butterflies = new ArrayList < > (); + float blue = 100; + float bluedirection = -0.25; + + void addButterfly() { + if (butterflies.size() < 10) + butterflies.add(new Butterfly(int(random(1, terrainWidth)) * cubeWidth, int(random(1, terrainLength)) * cubeWidth, 100)); + } + + void addBird() { + if (birds.size() < 10) + birds.add(new Bird(int(random(1, terrainWidth)) * cubeWidth, int(random(1, terrainLength)) * cubeWidth, 1200)); + } + + void generateTerrain() { + for (int i = 0; i < terrainWidth; i++) { + for (int j = 0; j < terrainLength; j++) { + Block block = new Block(i, j, noise(noiseStep * i, noiseStep * j), getRandomTreeColor(), int(random(minTreeHeight + 30, maxTreeHeight))); + blocks.add(block); + if (random(0, 1) < 0.001) addBird(); + if (random(0, 1) < 0.001) addButterfly(); + } + } + } + + void reloadTrees() { + blocks.forEach(block -> { + if ((noiseScale * block.h * cubeSize) > 170) { + if (int(random(0, 101)) < 1) { + block.isTree = true; + block.treeColor = getRandomTreeColor(); + } else + block.isTree = false; + } else + block.isTree = false; + + if (!block.isTree && (noiseScale * block.h * cubeSize) > 170) { + if (int(random(0, 101)) < 1) { + block.isFlower = true; + block.treeColor = getRandomFlowerColor(); + } else + block.isFlower = false; + } else + block.isFlower = false; + }); + } + + void setup() { + generateTerrain(); + reloadTrees(); + } + + void drawTerrain(PVector position) { + blocks.forEach(block -> { + float blockHeight = noiseScale * block.h * cubeSize; + + if (blockHeight < 150) { + fill(0, 0, int(blue)); + if (blue > 220) bluedirection = -0.15; + if (blue < 190) bluedirection = 0.15; + blue += bluedirection; + blockHeight = 135 + blue / 20; + } else if (blockHeight > 150 && blockHeight < 170) { + fill(yellow); + } else if (blockHeight > 350) { + blockHeight *= 1.5; + fill(255, 255, 255); + } else { + fill(green); + } + + float posX = block.x * cubeWidth; + float posY = block.y * cubeLength; + float posZ = blockHeight / 2.0; + + if (dist(posX, 0.0, posY, position.x, 0.0, position.z) > 1500) return; + + pushMatrix(); + + rotateX(HALF_PI); + translate(posX, posY, posZ); + box(cubeWidth, cubeLength, blockHeight); + + if (block.isTree && blockHeight < 350) drawNormalTree(block, posZ); + else if (block.isTree) drawPineTree(block, posZ); + +else if (block.isFlower && blockHeight < 350) drawFlower(block, posZ); + + popMatrix(); + }); + + birds.forEach(bird -> bird.draw()); + butterflies.forEach(butterfly -> butterfly.draw()); + } + + void applyGravity() { + float gravity = 0.001; + blocks.forEach(block -> { + block.h -= gravity; + if (noiseScale * block.h * cubeSize < 170) { + block.isTree = false; + block.isFlower = false; + } + }); + } + + void drawNormalTree(Block block, float posZ) { + fill(222, 184, 135); + translate(0, 0, posZ + 50); + box(cubeWidth, cubeLength, 100); + translate(0, 0, 50); + fill(block.treeColor); + noStroke(); + sphere(block.treeSize); + stroke(1); + } + + void drawPineTree(Block block, float posZ) { + fill(222, 184, 135); + translate(0, 0, posZ + 50); + box(cubeWidth, cubeLength, 100); + translate(0, 0, 50); + fill(0, 100, 0); + noStroke(); + cylinder(50, 1, 100, 50); + stroke(1); + } + + void drawFlower(Block block, float posZ) { + fill(0, 200, 0); + translate(0, 0, posZ + 10); + box(5, 5, 20); + translate(0, 0, 10); + fill(block.treeColor); + noStroke(); + sphere(10); + stroke(1); + } +} diff --git a/Utils.pde b/Utils.pde new file mode 100644 index 0000000..620597a --- /dev/null +++ b/Utils.pde @@ -0,0 +1,86 @@ +void cylinder(float bottom, float top, float h, int sides) { + pushMatrix(); + float angleX = HALF_PI; + float angleY = 0; + rotateX(angleX); + rotateY(angleY); + translate(0, h / 2, 0); + + float angle; + float[] x = new float[sides + 1]; + float[] z = new float[sides + 1]; + + float[] x2 = new float[sides + 1]; + float[] z2 = new float[sides + 1]; + + for (int i = 0; i < x.length; i++) { + angle = TWO_PI / (sides) * i; + x[i] = sin(angle) * bottom; + z[i] = cos(angle) * bottom; + } + + for (int i = 0; i < x.length; i++) { + angle = TWO_PI / (sides) * i; + x2[i] = sin(angle) * top; + z2[i] = cos(angle) * top; + } + + beginShape(TRIANGLE_FAN); + + vertex(0, -h / 2, 0); + + for (int i = 0; i < x.length; i++) { + vertex(x[i], -h / 2, z[i]); + } + + endShape(); + + beginShape(QUAD_STRIP); + + for (int i = 0; i < x.length; i++) { + vertex(x[i], -h / 2, z[i]); + vertex(x2[i], h / 2, z2[i]); + } + + endShape(); + + beginShape(TRIANGLE_FAN); + + vertex(0, h / 2, 0); + + for (int i = 0; i < x.length; i++) { + vertex(x2[i], h / 2, z2[i]); + } + + endShape(); + + popMatrix(); +} + +color getRandomTreeColor() { + int rand = int(random(0, 101)); + + if (rand < 10) return color(255, 69, 0); + if (rand < 20) return autumn1; + if (rand < 30) return autumn2; + if (rand < 40) return autumn3; + if (rand < 50) return autumn4; + if (rand < 60) return autumn5; + if (rand < 70) return autumn6; + if (rand < 80) return autumn7; + + return darkgreen; +} + +color getRandomFlowerColor() { + //float yellowBrightness = 150; + //float rand1 = yellowBrightness + randomGaussian() * 25; + //float rand2 = yellowBrightness + randomGaussian() * 25; + //float rand3 = yellowBrightness + randomGaussian() * 25; + + //rand1 = constrain(rand1, 0, 255); + //rand2 = constrain(rand2, 0, 255); + //rand3 = constrain(rand3, 0, 255); + + return color(random(0, 255), random(0, 255), random(0, 255)); +}