Cosmic Cycler


About this creative coding animation.

It was made with Processing programming code and Kdenlive video editor.
I learned PShape and PVector in this example code.
Thank you sir Daniel Shiffman for nice tutorials.
PShape
https://processing.org/tutorials/pshape/
PVector
https://processing.org/tutorials/pvector/

And thanks to nice music:
Riser by Evan Schaeffer
2017/02/21
http://freemusicarchive.org/music/Evan_Schaeffer/Glow_1216/Evan_Schaeffer_-_04_-_Riser
Riser by Evan Schaeffer is licensed under a Attribution License.
For more permissions:
contact artist
クリエイティブ・コモンズ・ライセンス

Processing code example.

// Cosmic Cycler
// Processing 3.2.1
// 2017.04.18

import java.util.Random;

World wd;
Cycler cl;
BigObject bo;
Shooting st;

float SKY_WIDTH = 600;
float SKY_HEIGHT = 340;

/* ---------------------------------------------------------------------- */
class World {

  Star st;
  PVector[] locateStars;
  float[] colorStars;
  int numStars;

  World() {

    numStars = 50;

    st = new Star();
    st.setBodyFill(0, 90, 80, 100);

    float divWidth = SKY_WIDTH * 2.5 / numStars;
    locateStars = new PVector[numStars];
    colorStars = new float[numStars];
    for (int i = 0; i < numStars; ++i) {
      locateStars[i] = new PVector(
                                   -SKY_WIDTH * 1.25 + divWidth * (i + random(0, 0.25)),
                                   map(random(1.), 0., 1., -SKY_HEIGHT, -100.),
                                   map(random(1.), 0., 1., -900., -500.)
                                );
      colorStars[i] = random(360);
    }

  }

  void redraw() {
    lightFalloff(1.0, 0.00005, 0.000002);
    pointLight(0, 0, 100, 0, 0, 100);
    camera(0, 0, 80,
           0, 0, 0,
           0, 1, 0);
    background(0, 0, 0);
  }

  void twilight() {
    float cntColor = 0.;
    float cntSaturation = 0.;
    float cntBright = 0.;
    strokeWeight(3);
    for (float i = -SKY_HEIGHT; i < SKY_HEIGHT; ++i) {
      cntColor += 0.13;
      cntSaturation += 0.07;
      cntBright += 0.07;
      stroke(
             230 + cntColor,
             100 - cntSaturation,
             50 + cntBright,
             100
             );
      pushMatrix();
      translate(0, i, -500);
      line(-SKY_WIDTH, 0, SKY_WIDTH, 0);
      popMatrix();
    }
  }

  void starlysky() {
    float divColor = (frameCount % 3600) / 10;
    for (int i = 0; i < numStars; ++i) {
      st.changeColor((colorStars[i] + divColor) % 360);
      pushMatrix();
      translate(locateStars[i].x, locateStars[i].y, locateStars[i].z);
      st.twinkle();
      popMatrix();
    }
  }


}

/* ---------------------------------------------------------------------- */
class Cycler {

  Star[] st;
  float[] rotateNoise;
  PVector[] locateStars, velocityStars;
  int numStars = 2;
    
  Cycler() {
    st = new Star[numStars];
    rotateNoise = new float[numStars];
    locateStars = new PVector[numStars];
    velocityStars = new PVector[numStars];
    for (int i = 0; i < numStars; ++i) {
      st[i] = new Star();
      rotateNoise[i] = random(10);
      locateStars[i] = new PVector(-SKY_WIDTH - 1000, 0, 0);
      velocityStars[i] = new PVector(0, 0, 0);
    }
  }

  void resetCourse() {
    float lx = SKY_WIDTH / 2;
    float ly = map(random(1.), 0., 1., 0., SKY_HEIGHT / 8);
    float lz = map(random(1.), 0., 1., -200., -80.);
    float vx = map(random(1.), 0., 1., -0.5, -1.0);
    float vy = map(random(1.), 0., 1., -0.4, 0.3);
    float vz = 0;
    float bodyColor = random(360);
    for (int i = 0; i < numStars; ++i) {
      st[i].setBodyFill(
                        (bodyColor + i * 180) % 360,
                        60,
                        80,
                        100
                        );
      locateStars[i].set(
                         lx + i * (10 + random(10)),
                         ly + i * (5 + random(5)),
                         lz + i * 10
                         );
      velocityStars[i].set(
                           vx,
                           vy,
                           vz
                           );
    }
  }
  
  void cycling() {
    noStroke();
    float[] rotateValue = new float[numStars];
    PVector locateAfter = new PVector(0, 0, 0);
    for (int i = 0; i < numStars; ++i) {
      if (locateStars[i].x < -SKY_WIDTH / 2 - 30 || abs(locateStars[i].y) > SKY_HEIGHT / 2 + 30) {
        resetCourse();
      }

      rotateValue[i] = noise(rotateNoise[i]);
      
      
      // Star
      pushMatrix();
      translate(locateStars[i].x, locateStars[i].y, locateStars[i].z);
      st[i].resetColor();
      st[i].rotate(radians(-rotateValue[i] * 3));
      st[i].twinkle();
      popMatrix();

      // After Image
      locateAfter = locateStars[i].copy();
      for (int j = 0; j < 3; ++j) {
        locateAfter.sub(PVector.mult(velocityStars[i], 3));
        pushMatrix();
        translate(locateAfter.x, locateAfter.y, locateAfter.z);
        st[i].changeBright(36. - j * 8);
        st[i].twinkle();
        popMatrix();
      }

      
      rotateNoise[i] += 0.0005;
      locateStars[i].add(PVector.mult(velocityStars[i], 1 + rotateValue[i] / 4));
    }
  }

}

/* ---------------------------------------------------------------------- */
class BigObject {

  Star st;
  Moon mn;
  float stBright, stdivBright, stBrightMax, stBrightMin;
  float mnBrightMax, mnBrightMin;
    
  BigObject() {
    stBrightMax = 90;
    stBrightMin = 50;
    stBright = stBrightMin;
    stdivBright = -1;
    st = new Star();
    st.setBodyFill(
                   230,
                   90,
                   50,
                   100
                   );
    st.changeSize(12);
    st.rotate(radians(60));

    mnBrightMax = 80;
    mnBrightMin = 0;
    mn = new Moon();
    mn.setBodyFill(
                   0,
                   60,
                   80,
                   100
                   );
  }

  void rise() {
    stBright += stdivBright;
    if (stBright < stBrightMin) {
      stdivBright = 0.01;
    } else if (stBright > stBrightMax) {
      stdivBright = -0.03;
    }
    st.changeBright(stBright);
    mn.changeBright(map(stBright, stBrightMin, stBrightMax, mnBrightMax, mnBrightMin));

    pushMatrix();
    translate(0, 0, -100);
    mn.twinkle();
    translate(-140, -60, -50);
    st.rotate(-0.0002);
    st.twinkle();
    popMatrix();
  }

}

/* ---------------------------------------------------------------------- */
class Shooting {

  Star meteor;
  Star[] dusts;
  PVector gravity;
  PVector locateMeteor, velocityMeteor;
  PVector[] locateDusts, velocityDusts;
  float[] rotateDusts, brightDusts;
  int numDusts = 100;
  int numDrawDusts;
    
  Shooting() {
    // Shooting Star
    meteor = new Star();
    meteor.changeSize(4.0);
    meteor.setBodyFill(
                   0,
                   0,
                   100,
                   100
                   );
    locateMeteor = new PVector(-SKY_WIDTH - 1000, 0, 0);
    velocityMeteor = new PVector(0, 0, 0);
    gravity = new PVector(0, 0, 0);

    // Star Dusts
    dusts = new Star[numDusts];
    rotateDusts = new float[numDusts];
    brightDusts = new float[numDusts];
    locateDusts = new PVector[numDusts];
    velocityDusts = new PVector[numDusts];
    for (int i = 0; i < numDusts; ++i) {
      dusts[i] = new Star();
      dusts[i].setBodyFill(
                     random(360),                     
                     100,
                     60,
                     100
                     );
      rotateDusts[i] = map(random(1.), 0., 1., -2., 2.);
      brightDusts[i] = 0;
      locateDusts[i] = new PVector(0, 0, 0);
      velocityDusts[i] = new PVector(0, 0, 0);
    }
    numDrawDusts = 0;
  }

  void resetCourse() {
    // Shooting Star
    float lx = map(random(1.), 0., 1., -SKY_WIDTH / 8, SKY_WIDTH / 2);
    float lz = map(random(1.), 0., 1., -500., -300.);
    float ly = lz * 0.6;
    float vx = map(random(1.), 0., 1., -0.5, -3.0);
    float vy = map(random(1.), 0., 1., 0.8, 2.0);
    float vz = -lz / 120;
    float gy = map(vy, 1.0, 2.0, 0.01, 0.04);

    if (random(10) < 6) {
      lz = lz * 0.1;
      vz = -vz * 0.8;
      vy = vy * 2;
      gy = -gy * 0.05;
    }

    meteor.setBodyFill(
                       random(360),                     
                       60,
                       80,
                       100
                       );
    locateMeteor.set(lx, ly, lz);
    velocityMeteor.set(vx, vy, vz);
    gravity.set(0, gy, 0);

    // Star Dusts
    for (int i = 0; i < numDusts; ++i) {
      dusts[i].resetSize();
      dusts[i].changeSize(0.6);
    }
    numDrawDusts = 0;
    
  }

  void shoot() {
    // Shooting Star
    if (frameCount % 210 == 0) { 
      if (locateMeteor.x < -SKY_WIDTH / 2 - 100 || locateMeteor.y > SKY_HEIGHT / 2 + 100) {
        resetCourse();
      }
    }
    velocityMeteor.add(gravity);
    locateMeteor.add(velocityMeteor);
    pushMatrix();
    translate(locateMeteor.x, locateMeteor.y, locateMeteor.z);
    meteor.rotate(radians(3));
    meteor.twinkle();
    popMatrix();

    // Star Dusts
    if (numDrawDusts >= numDusts) {
      numDrawDusts = numDusts;
    } else {
        locateDusts[numDrawDusts] = locateMeteor.copy();
        locateDusts[numDrawDusts].sub(PVector.mult(velocityMeteor, 10));
        velocityDusts[numDrawDusts].set(
                                        map(random(1.), 0., 1., -3., 3.),
                                        map(random(1.), 0., 1., -2., 0.),
                                        0
                                        );
        brightDusts[numDrawDusts] = 60;
        ++numDrawDusts;
    }
    for (int i = 0; i < numDrawDusts; ++i) {
      brightDusts[i] = brightDusts[i] * 0.97;
      dusts[i].changeBright(brightDusts[i]);
      velocityDusts[i].mult(0.95);
      locateDusts[i].add(velocityDusts[i]);
      
      pushMatrix();
      translate(locateDusts[i].x, locateDusts[i].y, locateDusts[i].z);
      dusts[i].changeSize(0.99);
      dusts[i].rotate(radians(rotateDusts[i]));
      dusts[i].twinkle();
      popMatrix();
    }

  }

}

/* ---------------------------------------------------------------------- */
abstract class CelestialBody {

  PShape aBody;
  float bodyColor, bodySaturation, bodyBright, bodyAlpha;
  
  CelestialBody() {
    aBody = pscreateBody();
    bodyColor = 0;
    bodySaturation = 0;
    bodyBright = 0;
    bodyAlpha = 0;
  }

  abstract PShape pscreateBody();

  void setBodyFill(float pcolor, float psaturation, float pbright, float palpha) {
    bodyColor = pcolor;
    bodySaturation = psaturation;
    bodyBright = pbright;
    bodyAlpha = palpha;
    resetColor();
  }

  void resetColor() {
    aBody.setFill(color(bodyColor, bodySaturation, bodyBright, bodyAlpha));
  }

  void changeColor(float scolor) {
    aBody.setFill(color(scolor, bodySaturation, bodyBright, bodyAlpha));
  }

  void changeBright(float sbright) {
    aBody.setFill(color(bodyColor, bodySaturation, sbright, bodyAlpha));
  }

  void resetSize() {
    aBody.resetMatrix();
  }

  void changeSize(float sscale) {
    aBody.scale(sscale);
  }

  void rotate(float rad) {
    aBody.rotateZ(rad);
  }

  void twinkle() {
    shape(aBody);
  }

}



/* ---------------------------------------------------------------------- */
class Star extends CelestialBody {
  
  Star() {
    super();
  }

  PShape pscreateBody() {
    float vertexRadius = 0;
    float maxRadius = 10;
    int vertexNum = 10;

    noStroke();
    PShape psStar = createShape();
    psStar.beginShape();
    for (int i = 0; i <= vertexNum; ++i) {
      if (i%2 == 0) {
        vertexRadius = maxRadius;
      } else {
        vertexRadius = maxRadius / 1.8;
      }
      psStar.vertex(
                    vertexRadius * cos(radians(-90 + 360 / vertexNum * i)),
                    vertexRadius * sin(radians(-90 + 360 / vertexNum * i))
                    );
    }
    psStar.endShape(CLOSE);
    return psStar;
  }

}

/* ---------------------------------------------------------------------- */
class Moon extends CelestialBody {

  Moon() {
    super();
  }

  PShape pscreateBody() {
    noStroke();
    PShape psMoon = createShape(ELLIPSE, 0, 0, 100, 100);
    return psMoon;
  }

}

/* ---------------------------------------------------------------------- */
void setup() {
  size(1280, 720, P3D);
  colorMode(HSB, 360, 100, 100, 100);
  blendMode(LIGHTEST);
  hint(DISABLE_DEPTH_TEST);
  smooth();
  background(0, 0, 0);
  frameRate(30);

  wd = new World();
  cl = new Cycler();
  bo = new BigObject();
  st = new Shooting();
}

void draw() {

  wd.redraw();
  wd.twilight();
  wd.starlysky();

  bo.rise();
  cl.cycling();
  st.shoot();

  /*
    saveFrame("frames/####.png");
    if (frameCount >= 5402) {
    exit();
    }
  */
}

/*
Copyright (C) 2017- deconbatch

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see 
*/



Next Post Previous Post
No Comment
Add Comment
comment url