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
*/



