Processing App

mail@pastecode.io avatar
unknown
java
2 months ago
32 kB
3
Indexable
Never
PVector camPosition = new PVector(1000, -700, 700);
PVector camPosition1 = new PVector(1000, -700, 700);
PVector lookAt = new PVector(0, 0, -1);
PVector wind = new PVector(5, -8, 0);
Terrain terra = new Terrain();
PImage skyboxImage;

void setup() {
    //fullScreen(P3D);
    frameRate(144);
    size(800, 600, P3D);

    randomSeed(randomSeedValue);
    noiseSeed(noiseSeedValue);
    noiseDetail(noiseOctaves, noiseFalloff);

    skyboxImage = loadImage("hot.jpg");

    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);

    // Draw the skybox
    drawSkySphere(500);  
}

void drawSkySphere(float radius) {
    pushMatrix();
    noStroke();
    translate(camPosition1.x, camPosition1.y, camPosition1.z);
    textureMode(NORMAL);
    texture(skyboxImage);
    sphere(radius);
    popMatrix();
}


class Balloon {
    float x;
    float y;
    float z;
    float radius;
    float angle;
    PVector velocity;
    PVector acceleration;
    float lastWindChangeTime;
    PShape s;

    Balloon(float x, float y, float z, PShape s) {
        this.x = x;
        this.y = y;
        this.z = z;
        this.s = s;
        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);
        rotateY(PI);
        scale(4);

        //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);
        
        shape(s);

        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();
    }
}


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);
    }
}


class Block {
    int x;
    int y;
    float h;
    boolean isTree;
    boolean isFlower;
    int treeSize;
    color treeColor;
    ArrayList<Particle> particles = new ArrayList<>();
    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;
        for (int i = 0; i < 4; i++) {
              float angleInRadians = map(i, 0, 10, 0, TWO_PI); 
              particles.add(new Particle(cubeWidth * cos(angleInRadians), cubeWidth * sin(angleInRadians), 0, this, random(0.5, 1), h/2));
            }
    }
    
    void drawParticles(float posZ) {
      particles.forEach(particle -> particle.display(posZ));
    }
}


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);
// (terrainLength / 10)
        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);
    }
}



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);

int terrainLength = 1000;
int terrainWidth = 1000;

int minTreeHeight = 20;
int maxTreeHeight = 70;

float noiseStep = 0.02;
float noiseScale = 5;
long randomSeedValue = 45; 
long noiseSeedValue = 2544;  
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;


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);
    }
}


class Particle {
    float x, y, z;
    float speed;
    color col;
    float permOffset;
    float offset = 0;
    Block block;

    Particle(float x, float y, float z, Block block, float speed, float treeSize) {
        this.x = x;
        this.y = y;
        this.z = z;
        this.block = block;
        this.speed = speed;
        this.permOffset = -150 - treeSize;
    }

    void update() {
        offset -= speed;
        if (offset < -100) offset = 0;
    }

    void display(float posZ) {
        pushMatrix();
        translate(x, y, posZ + permOffset + offset);
        fill(block.treeColor);
        float scaleDown = map(offset, 0, -150, 1, 10);
        box(10/scaleDown, 8/scaleDown, 8/scaleDown);
        scale(offset);
        popMatrix();
        update();
    }
}


class Terrain {
    ArrayList < Block > blocks = new ArrayList < > ();
    ArrayList < Bird > birds = new ArrayList < > ();
    ArrayList < Butterfly > butterflies = new ArrayList < > ();
    float blue = 100;
    float particleOffset;
    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) > 2000) return;
            
            pushMatrix();

            rotateX(HALF_PI);
            translate(posX, posY, posZ);
            box(cubeWidth, cubeLength, blockHeight);

            if (block.isTree && blockHeight < 350) {
            drawNormalTree(block, posZ);
            block.drawParticles(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);
    }
    
    void drawParticle(float x, float y, float z, color col) {
      pushMatrix();
      translate(x, y, particleOffset);
      particleOffset -= random(0, 0.001);
      fill(col);
      box(10, 10, 10);
      popMatrix();
    }
}



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));
}

Leave a Comment