xxxxxxxxxx
621
// Preloading all necessary elements
function preload() {
InfoBackground_img = loadImage("ultradeephubble.jpeg");
saturn_img = loadImage("saturn.jpg");
mars_img = loadImage("mars.png");
rship_img = loadImage("rocket.png");
spaceshipsound = loadSound("spaceship.mp3");
meteor_hit = loadSound("hit.wav");
Font_1 = loadFont("Orbitron-VariableFont_wght.ttf");
Interactive_backgd = loadImage("sensor.png");
note3 = loadSound("pianog.mp3");
note2 = loadSound("si.mp3");
note1 = loadSound("a6.mp3");
music2 = loadSound("spacemusic.mp3");
astro_img = loadImage("astro.png");
galaxy = loadImage("galaxy.jpg");
planet2 = loadImage("purple.png");
planet3 = loadImage("green.png");
satelite = loadImage("sate.png");
meteor = loadImage("meteor.jpg");
}
// Stars array
let stars = [];
// Define the initial state
let state = "Main";
// for meteor sound to be played once
let soundPlayed = false;
// Define some tools
let x3 = 0; // Initial x-position
let rocketSpeed = 1.3; // Constant speed for the rocket
let MainBackground_img;
//interactive elements
let alpha = 255; // This variable represents the potentiometer value
let xPosition = 0; // X-axis position of the ellipse
let yPosition = 0; // Y-axis position of the ellipse
let xMinimum = 25; // min limit of ellipse on X-axis
let xMaximum = 850; // max limit of ellipse on X-axis
let yMinimum = 25; // min limit of ellipse on Y-axis
let yMaximum = 850; // max limit of ellipse on Y-axis
let note1, note2, note3;
let rVal = 0;
let left = 0; // True (1) if mouse is being clicked on left side of screen
let right = 0; // True (1) if mouse is being clicked on right side of screen
//meteors
let astroX, astroY; // Astronaut's position
let meteors = []; // Array to store meteor positions
let numMeteors = 4; // Number of meteors
let meteorSpeed = 5; // Adjust the speed of the meteor
let hit = false; // Flag to check if a collision occurred
// SETUP function
function setup() {
createCanvas(950, 900);
frameRate(30);
// Create initial stars
for (let i = 0; i < 80; i++) {
stars.push(new Star());
}
// Initialize meteor positions
for (let i = 0; i < numMeteors; i++) {
meteors.push({ x: width + i * 200, y: random(0, height) });
}
}
// DRAW function
// use state for three page displays and use a function to display elements in each page
function draw() {
if (state == "Main") {
drawMain(); //main page
} else if (state == "Info") {
drawInfo(); // where you learn about sonification
fill(0);
stroke(111, 78, 55);
strokeWeight(5);
if (!serialActive) {
text("Press Space Bar to select Serial Port", 20, 30);
} else {
text("Connected", 20, 30);
// Print the current values
text("alpha = " + str(alpha), 20, 70); // for potentiometor
}
} else if (state == "Interactive") {
drawInteractive();
if (!serialActive) {
text("Press Space Bar to select Serial Port", 20, 30);
} else {
text("Connected", 20, 30);
xPosition = map(rVal, 0, 1023, xMinimum, xMaximum); //for light sensor
text("rVal = " + str(rVal), 20, 50);
}
}
// Update and display stars on the "Main" page
if (state == "Main") {
for (let star of stars) {
star.update();
star.display();
}
}
// Print mouse coordinates
print("Mouse X = " + mouseX);
print("Mouse Y = " + mouseY);
}
function mouseClicked() {
// Button logic for all buttons
if (
mouseX > 332 &&
mouseX < 656 &&
mouseY > 480 &&
mouseY < 534 &&
state == "Main"
) {
state = "Info";
} else if (
mouseX > 59 &&
mouseX < 290 &&
mouseY > 820 &&
mouseY < 865 &&
state == "Info"
) {
state = "Interactive";
} else if (
mouseX > 696 &&
mouseX < 892 &&
mouseY > 821 &&
mouseY < 870 &&
state == "Interactive"
) {
state = "Main";
} else if (
mouseX > 57 &&
mouseX < 289 &&
mouseY > 817 &&
mouseY < 870 &&
state == "Interactive"
) {
state = "Info";
}
}
//hover for buttons
let hoverState = false;
// ############################### MAIN PAGE #################################
function drawMain() {
background(0);
spaceshipsound.setVolume(0.2);
if (!spaceshipsound.isPlaying()) {
spaceshipsound.play();
spaceshipsound.setVolume(1.5);
} else if (music2.isPlaying() && state !== "Info") {
music2.stop();
}
// Title
stroke(250, 80, 0);
textSize(50);
fill(255);
textFont(Font_1);
text("Sounds in Space", 300, 212);
text("& Sonification", 330, 265);
// Description
stroke(250, 80, 0);
textSize(20);
textFont("Courier New");
fill(255);
text("- Use potentiometer to learn about sonification", 235, 381);
text("- Use light detector to make some notes", 235, 420);
// Images
let x = 1.5;
let y = 20;
image(saturn_img, x, y, 300, 250);
let x2 = 750;
let y2 = 55;
image(mars_img, x2, y2, 200, 100);
// Rocket
x3 += rocketSpeed;
if (x3 > width) {
x3 = -200;
}
image(rship_img, x3, 660, 200, 200);
// Rectangle BUTTON
if (mouseX > 330 && mouseX < 660 && mouseY > 480 && mouseY < 540) {
// Change the size and style of the rectangle when hovered
fill(255, 150, 0);
rect(330, 480, 330 * 1.1, 60 * 1.1);
textSize(30);
textFont(Font_1);
fill(0);
stroke(111, 78, 55);
strokeWeight(5);
text("Click Here to Begin !", 360, 522);
// Set the hover state to true
hoverState = true;
} else {
// Reset the size and style when not hovered
fill(255);
rect(330, 480, 330, 60);
textSize(25);
fill(0);
stroke(111, 78, 55);
strokeWeight(5);
textFont(Font_1);
text("Click Here to Begin !", 360, 515);
// Set the hover state to false
hoverState = false;
}
}
function mousePressed() {
// Check if the mouse is pressed while hovering over the rectangle
if (hoverState) {
// Perform actions when the rectangle is clicked
console.log("Rectangle clicked! Add your code here.");
}
}
// FOR BACKGROUND STARS
class Star {
constructor() {
this.x = random(width);
this.y = random(height);
this.size = random(3, 7);
this.color = color(random(230), random(180), random(255));
}
update() {
// Stars fall vertically
this.y += random(1, 2);
// Wrap around when stars go beyond the canvas
if (this.y > height) {
this.y = 0;
}
}
display() {
fill(this.color);
noStroke();
ellipse(this.x, this.y, this.size, this.size);
}
}
// ############################### INFORMATION PAGE #################################
function drawInfo() {
if (spaceshipsound.isPlaying() && state !== "Main") {
// Stop the sound if it's playing and the state is not "Main"
spaceshipsound.stop();
music2.play();
music2.setLoop(true);
music2.setVolume(0.5);
}
background(0);
fill(255);
textSize(16);
text("- Use Potentiometer to avoid meteors and learn! -", 445, 28);
// HOVER FOR BUTTONS
if (mouseX > 58 && mouseX < 285 && mouseY > 820 && mouseY < 867) {
stroke(250, 80, 0);
strokeWeight(8);
// Draw the rectangle
fill(255, 150, 0);
rect(58, 820, 240, 60);
textFont(Font_1);
textSize(20);
fill(0);
stroke(111, 78, 55);
strokeWeight(5);
text("Sonification Demo !", 74, 853);
// Set the hover state to true
hoverState = true;
} else {
stroke(250, 80, 0);
strokeWeight(8);
// Draw the rectangle
fill(255);
rect(58, 820, 230, 50);
textFont(Font_1);
textSize(20);
fill(0);
stroke(111, 78, 55);
strokeWeight(5);
text("Sonification Demo !", 74, 853);
// Set the hover state to true
hoverState = false;
}
//ELEMENTS FOR EACH TEXT
fill(255);
image(planet2, 143, 150);
planet2.resize(125, 125);
image(planet3, 575, 575);
planet3.resize(125, 125);
image(satelite, 379, 375);
satelite.resize(125, 125);
image(galaxy, 750, 760);
galaxy.resize(120, 120);
//the potentiometer goes from 0 to 1023 and color goes from 0 to 255, so it is good to use the map function
//MAPPING VALUES FROM POTENTIOMETER
let mappedX = map(alpha, 0, 1023, xMinimum, xMaximum);
let mappedY = map(alpha, 0, 1023, yMinimum, yMaximum);
// updating the position of the astro to check for clash with meteor
astroX = mappedX;
astroY = mappedY;
// Update Meteors
for (let i = 0; i < numMeteors; i++) {
meteors[i].x -= meteorSpeed;
if (meteors[i].x < 0) {
meteors[i].x = width;
meteors[i].y = random(0, height);
}
// Check for Collision
let distance = dist(astroX, astroY, meteors[i].x, meteors[i].y);
if (distance < 35) {
// Adjust the value based on your astronaut and meteor sizes
hit = true;
hitTime = millis(); // Record the time of the hit for the text to appear and disapper
}
}
// Display Text on Collision for 2 seconds
if (hit && !soundPlayed) {
fill(255, 0, 0);
textSize(25);
text("Stay away from meteors!", 395, 82);
meteor_hit.play();
meteor_hit.setVolume(0.5);
soundPlayed = true;
// Check if 2 seconds have passed
if (millis() - hitTime > 2000) {
hit = false; // Reset the hit flag after 2 seconds
}
}
// Display Astronaut
fill(255, 0, 255, map(alpha, 0, 1023, 0, 255));
image(astro_img, astroX, astroY, 70, 70);
// Display Meteors
for (let i = 0; i < numMeteors; i++) {
image(meteor, meteors[i].x, meteors[i].y, 40, 40); // Adjust the size as needed
}
//Text of each element (planet/satelite..) using potentiometer
if (alpha > 120 && alpha < 190) {
fill(255);
noStroke();
textSize(17);
text("In space, the absence of air means you can't hear sounds,", 238, 135);
text("not even your own voice. Contrary to movie depictions,", 238, 160);
text(
"without spacesuit sound systems, communication in the vast",
238,
185
);
text("silence of space is a silent adventure!", 238, 210);
} else if (alpha > 400 && alpha < 481) {
fill(255);
noStroke();
textSize(17);
text("No air or medium in outer space means", 458, 355);
text("no transmission of sound waves or vibrations", 458, 380);
text("that our ears interpret as sound, making it silent.", 458, 405);
} else if (alpha > 640 && alpha < 725) {
fill(255);
noStroke();
textSize(16.5);
text("Sonification transforms data from outer space", 15, 533);
text("into audible sounds, offering a unique cosmic symphony.", 15, 558);
text("It connects us to the universe on a deeper level,", 15, 583);
text("Turning astronomical data into", 15, 608);
text("an immersive auditory experience.", 15, 633);
} else if (alpha > 911 && alpha < 1020) {
fill(255);
noStroke();
textSize(16);
// First line
text("NASA utilizes sonification in black hole studies,", 330, 691);
text("transforming data from observations into sound.", 330, 713);
// Second line
text("Which helps scientists analyze gravitational interactions", 330, 738);
text("and energetic phenomena.", 330, 763);
// Third line
text("In pulsar star studies, sonification is employed", 330, 788);
text("to convert data collected from pulsars into sound.", 330, 813);
// Fourth line
text("This technique aids scientists in detecting", 330, 838);
text("rhythmic pulses from neutron stars.", 330, 860);
}
}
// ############################### SONIFICATION DEMO WITH LIGHT SENSOR ####################
function drawInteractive() {
if (spaceshipsound.isPlaying() && state !== "Main") {
// Stop the sound if it's playing and the state is not "Main"
spaceshipsound.stop();
} else if (music2.isPlaying() && state !== "Info") {
// Stop the sound if it's playing and the state is not "info"
music2.stop();
}
image(Interactive_backgd, 1, 1, 950, 900);
// Draw the waveform based on the mapped distance
stroke(255);
strokeWeight(4);
fill(255);
let startX = 215; // Adjust this value to set the starting x-coordinate
let endX = 719; // Adjust this value to set the ending x-coordinate
beginShape();
for (let i = startX; i <= endX; i++) {
let amplitude = map(rVal, 0, 1023, 0.4, 2.0); // Adjust the range for desired amplitude
let y = height / 2 + sin((i - startX) * 0.1) * 50 * amplitude;
vertex(i, y);
}
endShape();
noStroke();
fill(255);
textSize(23);
text(
"Stars distance and brightness can be detected through sonification",
90,
132
);
// Draw the rectangle HOVER BUTTON
if (mouseX > 58 && mouseX < 285 && mouseY > 820 && mouseY < 867) {
stroke(250, 80, 0);
strokeWeight(8);
fill(255, 150, 0);
rect(58, 820, 240, 60);
hoverState = true;
} else {
stroke(250, 80, 0);
strokeWeight(8);
fill(255);
rect(58, 820, 230, 50);
hoverState = false;
}
if (mouseX > 695 && mouseX < 896 && mouseY > 820 && mouseY < 867) {
stroke(250, 80, 0);
strokeWeight(8);
fill(255, 150, 0);
rect(695, 820, 210, 60);
hoverState = true;
} else {
stroke(250, 80, 0);
strokeWeight(8);
fill(255);
rect(695, 820, 200, 50);
hoverState = false;
}
textFont(Font_1);
textSize(20);
fill(0);
stroke(111, 78, 55);
strokeWeight(5);
text("Main Page ", 744, 853);
textSize(18);
text("Back to Instructions", 76, 853);
fill(255);
strokeWeight(4);
// Play notes based on light distance with smooth transitions (3 notes)
if (rVal < 450 && !note1.isPlaying()) {
note1.play();
note2.stop();
note3.stop();
} else if (rVal >= 500 && rVal < 780 && !note2.isPlaying()) {
note2.play();
note1.stop();
note3.stop();
} else if (rVal >= 800 && !note3.isPlaying()) {
note3.play();
note1.stop();
note2.stop();
}
}
// to pair serial
function keyPressed() {
if (key == " ") {
// important to have in order to start the serial connection!!
setUpSerial();
}
}
function readSerial(data) {
////////////////////////////////////
//READ FROM ARDUINO HERE
////////////////////////////////////
if (data != null) {
// make sure there is actually a message
// split the message
let fromArduino = split(trim(data), ",");
// if the right length, then proceed
if (fromArduino.length == 2) {
rVal = int(fromArduino[0]);
alpha = int(fromArduino[1]);
}
//////////////////////////////////
//SEND TO ARDUINO HERE (handshake)
//////////////////////////////////
let sendToArduino = left + "," + right + "\n";
writeSerial(sendToArduino);
}
}
// Arduino code
/*// Inputs:
// - A0 - sensor connected as voltage divider (e.g. potentiometer or light sensor)
// - A1 - sensor connected as voltage divider
//
// Outputs:
// - 2 - LED
// - 5 - LED
int leftLedPin = 2;
int rightLedPin = 5;
void setup() {
// Start serial communication so we can send data
// over the USB connection to our p5js sketch
Serial.begin(9600);
// We'll use the builtin LED as a status output.
// We can't use the serial monitor since the serial connection is
// used to communicate to p5js and only one application on the computer
// can use a serial port at once.
pinMode(LED_BUILTIN, OUTPUT);
// Outputs on these pins
pinMode(leftLedPin, OUTPUT);
pinMode(rightLedPin, OUTPUT);
// Blink them so we can check the wiring
digitalWrite(leftLedPin, HIGH);
digitalWrite(rightLedPin, HIGH);
delay(200);
digitalWrite(leftLedPin, LOW);
digitalWrite(rightLedPin, LOW);
// start the handshake
while (Serial.available() <= 0) {
digitalWrite(LED_BUILTIN, HIGH); // on/blink while waiting for serial data
Serial.println("0,0"); // send a starting message
delay(300); // wait 1/3 second
digitalWrite(LED_BUILTIN, LOW);
delay(50);
}
}
void loop() {
// wait for data from p5 before doing something
while (Serial.available()) {
digitalWrite(LED_BUILTIN, HIGH); // led on while receiving data
int left = Serial.parseInt();
int right = Serial.parseInt();
if (Serial.read() == '\n') {
digitalWrite(leftLedPin, left);
digitalWrite(rightLedPin, right);
int sensor = analogRead(A0);
delay(50);
int sensor2 = analogRead(A1);
delay(5);
Serial.print(sensor);
Serial.print(',');
Serial.println(sensor2);
}
}
digitalWrite(LED_BUILTIN, LOW);
}
*/