xxxxxxxxxx
244
/////////////////////////////
// //
// FOR PAGE DESIGN. //
// //
/////////////////////////////
let page = 0; // Page tracker
let eyeballPos, pupilRadius, eyeballRadius; //Define the eye ball animation
let serialButton, homeButton; // Buttons
let myFont;
let music;
let bgImage;
/////////////////////////////
// //
// FOR EYE TRACKING. //
// //
/////////////////////////////
let capture = null;
let tracker = null;
let positions = null;
let w = 0, h = 0;
let eyeStayTime = Array(6).fill(0); // Time eye stays in each zone
let startTime = Array(6).fill(null); // Start time for proximity zones
let dimmingCycle = Array(6).fill(false); // Track dimming state for each zone
// Coordinates for 6 zones/coordinates
const zones = [
{ x: 410, y: 211, pin: 2 },
{ x: 350, y: 230, pin: 3 },
{ x: 300, y: 255, pin: 4 },
{ x: 270, y: 185, pin: 5 },
]
function preload() {
music = loadSound('BG.mp3');
myFont = loadFont('LexendZetta-VariableFont_wght.ttf');
bgImage = loadImage("BG.jpg");
}
function setup() {
w = windowWidth;
h = windowHeight;
textFont(myFont);
// Initialize variables for eye animation
eyeballPos = createVector(width / 2, height / 2);
eyeballRadius = 100;
pupilRadius = eyeballRadius / 3;
// Initialize video capture
capture = createCapture(VIDEO);
createCanvas(w, h);
capture.size(w, h);
capture.hide();
frameRate(20);
colorMode(HSB);
// Initialize CLM tracker
tracker = new clm.tracker();
tracker.init();
tracker.start(capture.elt);
// Serial button for page 2
serialButton = createButton("Connect to The Others");
serialButton.position(width / 2 - 50, height / 2 + 150);
serialButton.mousePressed(setUpSerial);
serialButton.hide(); // Initially hidden
// Home button to return to Page 1
homeButton = createButton("Back to Home");
homeButton.position(width - 100, 20);
homeButton.mousePressed(() => (page = 0)); // Return to Page 1
homeButton.hide(); // Initially hidden
// Play music at the start
if (music && !music.isPlaying()) {
music.loop();
}
}
function draw() {
background(30);
if (page === 0) {
// Page 1: Project description
image(bgImage, 0, 0, width, height);
fill(255);
textSize(40);
text("The Others", width / 2, height / 3);
textSize(20);
textAlign(CENTER);
text(
"'What counts is what the heroine provokes,or rather what ___ represents. ___ is the one, or rather the love or fear ___ inspires in the hero, or else the concern ___ feels for ___, or who makes ___ act the way ___ does. In ___ the ___ has not the slightest importance. ― Laura Mulvey",
width / 2 - width/4,
height / 3 + 50,
500
);
textSize(20);
text("Press the right arrow to proceed.", width / 2, height - 100);
// Hide buttons
serialButton.hide();
homeButton.hide();
} else if (page === 1) {
image(bgImage, 0, 0, width, height);
// Page 2: Eye animation with serial button
drawEyeAnimation(); // Draw the eye animation
// Display Serial button and instructions
serialButton.show();
fill(255);
textSize(20);
text("Press the right arrow to proceed to the next page.", width / 2, height / 2 + 200);
// Show Home button
homeButton.show();
} else if (page === 2) {
// Page 3: Webcam feed and eye tracking
translate(w, 0); // Flip canvas for mirror effect
scale(-1.0, 1.0);
image(capture, 0, 0, w, h); // Webcam feed
fill(255);
textSize(24);
textAlign(CENTER);
translate(w, 0); // Flip canvas for mirror effect
scale(-1.0, 1.0);
text("Please Look Up.", width / 2, height / 2);
positions = tracker.getCurrentPosition();
if (positions && positions.length > 0) {
const eye1Center = getPoint(27); // Eye 1 center
const eye2Center = getPoint(32); // Eye 2 center
const eyeCenter = p5.Vector.add(eye1Center, eye2Center).div(2); // Average eye center
console.log(`Eye Center: (${eyeCenter.x}, ${eyeCenter.y})`); // Log eye center coordinates
updateBrightness(eyeCenter); // Update NeoPixel zones
}
// Hide Serial button and show Home button
serialButton.hide();
homeButton.show();
}
}
function readSerial(data) {
console.log("Received from Arduino:", data);
// Example: Handle data in "pin:value" format
const parts = data.split(":");
if (parts.length === 2) {
const pin = parseInt(parts[0]);
const value = parseInt(parts[1]);
console.log(`Pin ${pin} has value ${value}`);
} else {
console.log("Invalid data format:", data);
}
}
function drawEyeAnimation() {
// Center the eyeball on Page 2
eyeballPos.set(width / 2, height / 2);
// Draw eyeball
fill(255);
ellipse(eyeballPos.x, eyeballPos.y, eyeballRadius * 2);
// Pupil position based on mouse
const dx = constrain(mouseX - eyeballPos.x, -eyeballRadius / 2, eyeballRadius / 2);
const dy = constrain(mouseY - eyeballPos.y, -eyeballRadius / 2, eyeballRadius / 2);
const pupilPos = createVector(eyeballPos.x + dx, eyeballPos.y + dy);
fill(0);
ellipse(pupilPos.x, pupilPos.y, pupilRadius * 2); // Pupil
}
function updateBrightness(eyeCenter) {
zones.forEach((zone, i) => {
const distance = eyeCenter.dist(createVector(zone.x, zone.y));
const maxBrightness = 255;
if (distance < 50) {
if (!startTime[i]) startTime[i] = millis();
eyeStayTime[i] = (millis() - startTime[i]) / 1000;
// Breathing effect
if (eyeStayTime[i] > 3) {
dimmingCycle[i] = !dimmingCycle[i]; // Toggle dimming state
startTime[i] = millis(); // Restart timing
}
const brightness = dimmingCycle[i]
? map(eyeStayTime[i], 0, 3, maxBrightness, 50) // Dim
: map(eyeStayTime[i], 0, 3, 50, maxBrightness); // Brighten
sendBrightness(zone.pin, brightness);
} else {
startTime[i] = null;
eyeStayTime[i] = 0;
dimmingCycle[i] = false;
sendBrightness(zone.pin, 0); // Turn off
}
});
}
async function sendBrightness(pin, brightness) {
if (serialActive) {
try {
const msg = `${pin}:${brightness}\n`; // Format the message
await writer.write(msg); // Send data to Arduino
console.log(`Sent to Arduino: ${msg}`);
} catch (err) {
console.error("Error writing to serial:", err);
}
} else {
console.log("Serial connection is not active.");
}
}
function getPoint(index) {
return createVector(positions[index][0], positions[index][1]);
}
function keyPressed() {
if (keyCode === RIGHT_ARROW) {
page = (page + 1) % 3; // Cycle through pages
}
if (key === "f" || key === "F") {
let fs = fullscreen();
fullscreen(!fs); // Toggle fullscreen
}
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
// Reposition buttons
serialButton.position(width / 2 - 50, height / 2 + 150);
homeButton.position(width - 100, 20);
}