The initial idea of this project is a bit different from what I ended up with. The initial idea was designed for two players, each placing one hand on a heart rate monitor. This game uses heart rate data to measure and display the level of affection or excitement between the participants. The faster the heartbeats, the higher the presumed love connection. But after I heard that we’d have to return the items we borrowed from the IM lab I thought it would be better if I order my own two heart rate monitors and solder them myself, then I wouldn’t have to take apart my hard work. With my not-so-good soldering skills I ruined one heart rate monitor and had only one to work with. I had to improvise and solve this issue working with only one heart rate monitor which led to changing the theme of the game a bit. Professor Aaron helped me with coming up with a new game that measures the players Happiness Level by reading their heart rates through the heart monitor. The game was initially supposed to start by pressing on a yellow button but due to time constrains and many other technical difficulties, such as linking the Arduino and the P5 together, I still managed to make it work fine with the keyboard even though I feel like the yellow button gives it more of a “gamey” feel to it which is what I would’ve much preferred.
Arduino Code:
const int buttonPin = 3; // Pin where the button is connected const int heartRatePin = A0; // Analog pin for heart rate sensor int heartRateValue = 0; bool buttonPressed = false; void setup() { pinMode(buttonPin, INPUT_PULLUP); // Set the button pin as input with internal pull-up resistor pinMode(heartRatePin, INPUT); Serial.begin(9600); while (Serial.available() <= 0) { // on/blink while waiting for serial data Serial.println("0,0"); delay(50); } } void loop() { heartRateValue = analogRead(heartRatePin); // Read the value from the heart rate sensor int bpm = calculateBPM(heartRateValue); // Convert the analog reading to BPM // Read button state int buttonState = 1 - digitalRead(buttonPin); while (Serial.available()) { int left = Serial.parseInt(); if (Serial.read() == '\n') { Serial.print(buttonState); Serial.print("0,50"); Serial.println(bpm); } } // Always send the current heart rate and button state } // Function to simulate BPM calculation - replace this with your sensor-specific calculation int calculateBPM(int sensorValue) { return sensorValue / 10; // Simplified calculation for demonstration }
P5.Js Code:
class MainMenu extends Menu { constructor(id) { super(id); this.pos = createVector(width / 2, height / 2.7); this.size = 240; this.strokeCol = color( random(100, 255), random(100, 255), random(100, 255) ); this.hearts = []; for (let i = 0; i < 20; i++) { this.hearts.push({ x: random(width), y: random(height) }); } this.random_seed = random(100, 10000); //use for heard animations in the back this.heartPos = { x: width / 2, y: height * 2 }; } render() { background("#24182e"); textAlign(CENTER, CENTER); textSize(44); textFont(pixel_font); fill("#8249c6"); stroke(this.strokeCol); strokeWeight(4); text("HAPPINESS LEVEL", width / 2, 50); //change strokcol every 20 farmes if (frameCount % 60 == 0) { this.strokeCol = color( random(100, 255), random(100, 255), random(100, 255) ); this.random_seed = random(100, 10000); } textSize(30); stroke(200, 100, 100); push(); randomSeed(this.random_seed); textFont("arial"); for (let h of this.hearts) { for (let h2 of this.hearts) { if (dist(h.x, h.y, h2.x, h2.y) < 10) { strokeWeight(2); line(h.x, h.y, h2.x, h2.y); } } text("♥", h.x, h.y); h.x = lerp(h.x, random(width), 0.01); h.y = lerp(h.y, random(height), 0.01); } pop(); push(); textFont("arial"); textSize(160); this.heartPos.y = lerp(this.heartPos.y, height / 1.5, 0.1); stroke(255); fill("#B28CDEAA"); text("♥", this.heartPos.x, this.heartPos.y); textSize(30); noStroke(); fill(255); textFont(pixel_font); text( "PLACE YOUR FINGER ON THE HEART", this.heartPos.x, this.heartPos.y + 100 ); pop(); noStroke(); } } class GameMenu extends Menu { constructor(id) { super(id); this.heart = new Heart(createVector(width / 2, height / 2.7), 240); } render() { textAlign(CENTER, CENTER); textSize(18); background("#24182e"); fill("#A88DC7"); text("CHECKING YOUR LOVE LEVEL!", width / 2, height - 30); fill("#8249C67C"); textFont("arial"); textSize(34); for (let i = 0; i < 12; i++) { for (let j = 0; j < 8; j++) { let x = map(i, 0, 11, 0, width); let y = map(j, 0, 7, 0, height); if (frameCount % 40 < 20) { if (i % 2 == 0 || j % 2 == 0) { text("♥", x, y); } } else { if (i % 2 != 0 || j % 2 != 0) { text("♥", x, y); } } } } this.heart.render(); } update() { this.heart.update(); // Removed the timer decrement and check } reset() { this.heart = new Heart(createVector(width / 2, height / 2.7), 220); } } class EndMenu extends Menu { constructor(id) { super(id); this.finalScore = null; this.hearts = []; for (let i = 0; i < 2; i++) { this.hearts.push({ x: random(width), y: random(height) }); } this.random_seed = random(100, 10000); //use for heard animations in the back } render() { background("#24182e"); push(); stroke(200, 100, 100); randomSeed(this.random_seed); textFont("arial"); textSize(34); for (let h of this.hearts) { for (let h2 of this.hearts) { if (dist(h.x, h.y, h2.x, h2.y) < 100) { line(h.x, h.y, h2.x, h2.y); } } text("♥", h.x, h.y); h.x = lerp(h.x, random(width), 0.01); h.y = lerp(h.y, random(height), 0.01); } if (frameCount % 60 == 0) { this.random_seed = random(100, 10000); } pop(); fill("#A88DC7"); stroke(255); textFont(pixel_font); textSize(60); textAlign(CENTER, CENTER); text("THANK YOU !", width / 2, 160); noStroke(); textSize(24); // text( // `${this.finalScore}\n\nYOUR COMPATIBILITY SCORE`, // width / 2, // height / 1.5 // ); // push(); // noStroke(); // fill(0); // rect(0, 0, width, height); // fill(255); // textStyle(BOLD); // textAlign(CENTER, CENTER); // textSize(96); // text("GAME OVER", width / 2, height / 4); // textSize(40); // text(`COMPATIBILITY SCORE: ${this.finalScore}`, width / 2, height / 2); // textStyle(NORMAL); textSize(16); text("TRY AGAIN?", width / 2, height - 60); text("Yes", 100, height - 60); text("No", width - 100, height - 60); push(); textFont("arial"); pop(); // textSize(40); // text("YES? OR NO?", width / 2, 640); // pop(); } reset() { this.finalScore = null; } }
 I’m content with the final product despite getting extremely sick two days before the showcase while having other final projects due the day before it. For future improvements I’d like to incorporate my initial idea and also add a different game mode, Lie Detector Mode, which sounds fun to make with using the heart rate monitor. Overall, I feel like I got exposed to many things in this course which makes me much more comfortable with the things we’ve been working with during the entirety of this semester. I’d also like to thank professor Aaron for being extremely patient and helpful with me 🙂