Press your mouse to add planets and nebulas and use your mouse to hover around the Canvas and explore the universe!!
//Steven Fei & Fanjie Mike Jin
//Section A & C
//Final Project
//zfei@andrew.cmu.edu & fjin@andrew.cmu.edu
var starNumber = 150;//number of the stars on the background
var starsize = 1.5;//size of the stars
var sx = [];//array to define the x position of the stars
var sy = [];//array to define the y position of the stars
var sz = [];//array to define the z position of the stars
var amplitude = 3.14 * 3;//define the moving margin of the stars
var waveSpeed;//define the moving speed of the stars on the background
var theta = 0;//define the moving angle of the stars
var glowDefiner = [];//define the true false value for whether to let the star glow
var glowSize = 22;//glowing size of the stars
var newStars = [];//array for making new stars
var mouseXList = [];//arrays to store mouseX value
var mouseYList = [];//arrays to store mouseY value
var img; //load image for the earth texture mapping
var w = 600 / 7 // devivded the canvas into seven regions and from left to right, the pitches of the piano sound will progressively become higher
var newExplod = [];//array for making new explosion at the background
var mouseXListEx = [];//arrays to store mouseX value
var mouseYListEx = [];//arrays to store mouseY value
function setup() {
//load the background image for the texture mapping of the earth
//coded by Mike
img = loadImage("https://i.imgur.com/lamlO83.jpg");
createCanvas(600, 600,WEBGL);
//create values for the positions of the stars on the background
//coded by Mike
for (var i = 0; i < starNumber; i++){
sx.push(random(-width * 0.75, width * 0.75));
sy.push(random(-height, height));
sz.push(random(-width, height/2));
var toggle = random(1.0);
//define whether the stars on the background will glow
if(toggle < 0.9){
glowDefiner.push(false);
}else{
glowDefiner.push(true);
}
}
for(var j = 0; j < glowDefiner.length; j++){
print(glowDefiner[j]);
}
}
function draw(){
background(0);
noStroke();
normalMaterial();
centerCube();//create a center star to give a sense of what perspective we are looking at
makeCamera();//use the makeCamera function to change the viewport angle
makeearth();
push();
//draw the stars on the background
for(var i = 0; i < starNumber; i++){
//coded by Mike
push();
waveSpeed = map(sz[i], -width, height/2, 15000, 60000);//define the moving speed of the stars
theta += (TWO_PI / waveSpeed);//define the moving angle of the stars
if(theta > amplitude){
theta = -theta;//set the moving margins of the stars
}
sy[i] += sin(theta);//set the moving value to the positions
sx[i] += cos(theta);//set the moving value to the positions
translate(sx[i], sy[i], sz[i]);
if(glowDefiner[i]){
fill(255, 200, 130, 4);
sphere(glowSize);//draw glow light of the sphere
}
fill("white");
smooth();
sphere(starsize);//draw the stars
pop();
}
pop();
//draw some new stars
//coded by Steven
if (mouseXList.length != 0){
for(var k = 0; k < newStars.length; k++){
newStars[k].updateStar();//animate the expansion of the stars
push();
translate(newStars[k].x, newStars[k].y,0);
rotateX(frameCount * 0.05 + k*2);//rotate the new star
rotateY(frameCount * 0.05 + k*2);//rotate the new star
newStars[k].draw();//animate the emergence of the stars
pop();
}
}
if(newStars.length > 4){
newStars.shift();
}
push();
//make the planet
if (mouseXListEx.length != 0){
for(var k = 0; k < newExplod.length; k++){
newExplod[k].updateExplo();//animate the expansion of the stars
push();
translate(newExplod[k].x, newExplod[k].y,0);
rotateX(frameCount * 0.05 + k*2);//rotate the new star
rotateY(frameCount * 0.05 + k*2);//rotate the new star
newExplod[k].draw();//animate the emergence of the stars
pop();
}
}
if(newExplod.length > 2){
newExplod.shift();
}
pop();
}
function makeCamera(){
//coded by Steven
camX = map(mouseX, 0, width, -width/2, width/2);//changing camera position x
camY = map(mouseY, 0, height, -height/2, height/2);//changing camera position y
camZ = height/2;//changing camera position z
camera(camX, camY, camZ,0,0,0,1,1,0);//allow the viewport angle to change
}
//make object to create new stars
function makeNewStar(x, y, radius){
//coded by Mike
var newstar = {x: x,
y: y,
r: radius,
updateStar: updateStar,
draw: drawNewStar};
return newstar;
}
function makeNewExplo(x, y, radius){
//coded by Mike
var newExplo = {x: x,
y: y,
r: radius,
updateExplo: updateExplo,
draw: drawNewExplo};
return newExplo;
}
//function to draw new star
function drawNewStar(){
//coded by Mike
var color1 = random(150, 255);
var color2 = random(100,180);
var color3 = random(100,200);
var density = random(14,20);//allow different numbers of the spheres to appear on the star
for(var i = 0; i < density; i++){
var lengthValue = map(i, 0, density, -PI, PI); //set longitudinal value
for(var j = 0; j< density; j++){
var widthValue = map(j, 0, density, -PI/2, PI/2);// set horizontal value
var pX = this.r * sin(lengthValue) * cos(widthValue);
var pY = this.r * sin(lengthValue) * sin(widthValue);
var pZ = this.r * cos(lengthValue);
push();
fill(color1, color2, color3);
translate(pX, pY, pZ);
sphere(1.6);
pop();
}
}
}
function drawNewExplo(){
//coded by Mike
var color4 = random(100, 255);
var color5 = random(100,180);
var color6 = random(100,200);
var density = random(12, 15);//allow different numbers of the spheres to appear for the explosion
for(var i = 0; i < density; i++){
var lengthValue = map(i, 0, density, -PI, PI); //set longitudinal value
for(var j = 0; j< density; j++){
var widthValue = map(j, 0, density, -PI/2, PI/2);// set horizontal value
var pX1 = this.r * sin(lengthValue) * cos(widthValue * 0.5) * 0.5;
var pY1 = this.r * sin(lengthValue * 0.5) * sin(widthValue) * 0.5;
var pZ1 = this.r * cos(lengthValue);
push();
fill(color4, color5, color6);
translate(pX1, pY1, pZ1);
box(2, 2, 2);
pop();
}
}
}
function updateStar(){
//coded by Mike
this.r += random(0.5,2);//allow the new star to expand
}
function updateExplo(){
//coded by Mike
this.r += random(1,2);//allow the new explosion to expand
}
function mousePressed(){
//coded by Steven
var newStarMaking = [];
var newMouseXList = [];
var newMouseYList = [];
var newExploMaking = [];
var newmouseXListEx = [];
var newmouseYListEx = [];
var clickEx;//check whether there is existing new stars
var click;//check whether there is existing new stars
if(mouseXList.length == 0){
click = 0;
newStarMaking.push(newStars[0]);
newMouseXList.push(mouseXList[0]);
newMouseYList.push(mouseYList[0]);
}
else{
for(var l = 0; l < newStars.length; l++){
var distance = dist(mouseX - width/3, mouseY - height/3, newStars[l].x, newStars[l].y);
if(distance <= 30){
click = 1;
}else{
click = 0;
newStarMaking.push(newStars[l]);
newMouseXList.push(mouseXList[l]);
newMouseYList.push(mouseYList[l]);
}
}
newStars = newStarMaking;
mouseXList = newMouseXList;
mouseYList = newMouseYList;
}
if(click == 0){
mouseXList.push(mouseX - width/3);
mouseYList.push(mouseY - width/3);
var newStar = makeNewStar(mouseX - width/3, mouseY-width/3, 30);
newStars.push(newStar);
}
//add value to empty list
if(mouseXListEx.length == 0){
clickEx = 0;
newExploMaking.push(newExplod[0]);
newmouseXListEx.push(mouseXListEx[0]);
newmouseYListEx.push(mouseYListEx[0]);
}
else{
//assign initiating position according to the mouse postion
for(var w = 0; w < newExplod.length; w++){
var distance = dist(mouseX - width/3, mouseY - height/3, newExplod[w].x, newExplod[w].y);
if(distance <= 30){
clickEx = 1;
}else{
clickEx = 0;
newExploMaking.push(newExplod[w]);
newmouseXListEx.push(mouseXListEx[w]);
newmouseYListEx.push(mouseYListEx[w]);
}
}
//assign values back to the list
newExplod = newExploMaking;
mouseXListEx = newmouseXListEx;
mouseYListEx = newmouseYListEx;
}
//avoid invalid value
if(clickEx == 0){
mouseXListEx.push(mouseX - width/3);
mouseYListEx.push(mouseY - width/3);
var newExplo = makeNewExplo(mouseX - width/3, mouseY-width/3, 300);
newExplod.push(newExplo);
}
}
//function to make a center planet to have some understanding of the perspective
//coded by Mike
function centerCube(){
//make sure the location of the center planet is always at the center of the canvas
push();
var locX = mouseX - height / 2;
var locY = mouseY - width / 2;
ambientLight(50);
directionalLight(255, 0, 0, 0.25, 0.25, 0);
pointLight(0, 0, 255, locX, locY, 250);
ambientMaterial(100);
strokeWeight(0.5);
stroke(255);
smooth();
sphere(40);
pop();
//first ring surronding the planet
push();
rotateZ(frameCount * 0.01);
rotateX(frameCount * 0.01);
rotateY(frameCount * 0.01);
strokeWeight(0.5);
smooth();
stroke(255);
torus(60, 0.5);
pop();
//second ring surronding the planet
push();
rotateZ((100+ frameCount) * 0.01);
rotateX((100 + frameCount) * 0.01);
rotateY((100+ frameCount) * 0.01);
smooth();
strokeWeight(0.5);
stroke(255);
torus(70, 0.5);
pop();
//third ring surronding the planet
push();
rotateZ((200+ frameCount) * 0.01);
rotateX((200 + frameCount) * 0.01);
rotateY((200+ frameCount) * 0.01);
smooth();
strokeWeight(0.5);
stroke(255);
torus(80, 0.5);
pop();
//fourth ring surronding the planet
push();
rotateZ((300+ frameCount) * 0.01);
rotateX((300 + frameCount) * 0.01);
rotateY((300+ frameCount) * 0.01);
smooth();
strokeWeight(0.5);
stroke(255);
torus(90, 1);
pop();
}
//function to make a earth adjacent to the center planet
//coded by Mike
function makeearth(){
push();
translate(width / 2, height / 3, -150);
rotateX(frameCount * 0.05);
rotateY(frameCount * 0.05);
texture(img);
sphere(20);
pop();
}
In this project, we aim to establish an interactive universe made possible by using the P5 3D geometry and 3D lighting. When you are hovering around in this universe, the stars and planets will move according to your mouse position. When you lower the mouse position, the screen will be zoomed out and when you higher the mouse, the screen will zoom in more. When the mouse is pressed, new “stars” which look like the colorful spheres composed of smaller spheres with galaxy-like explosion will happen randomly on the screen and would expand further until they can be seen no more. However, once you click on the screen, you will be able to see them again. The small spheres are glowing on the background to have an interstellar appearance. The center spindle-like sphere and an “Earth” like sphere are created to give us a general understanding of what perspective we are looking at the canvas.