Midterm Project: Speedrunning Procrastination

CONCEPT

You know when you sit at your desk, open up your assignments on your laptop, and after thinking about what it is you have to do, you finally come to the conclusion: “Man, I could really go for a walk right now”? I know it all too well. I did the same with my midterm project, going on walks on and around campus, beyond the barriers across the welcome center (definitely not trespassing), above the highway behind campus, below the tunnel across the highway, but not starting my project. I’d listen to my playlist on Spotify while looking at the stars in the light-polluted Abu Dhabi sky, or at the stunning night skyline from the bridge on the highway (again don’t call the cops). Struggling to settle on an idea, I finally thought of making the exact thing that I was using to procrastinate on starting work in the first place – an interactive music library interface, just like Spotify. Now I could procrastinate while working, if that makes sense.

WORKFLOW

I had come up with an idea, sure, but I soon realized that to actually bring my idea to life, it was ME who would have to work, to write code endlessly, to face disappointment because of errors, to fix said errors, to do it all over again God knows how many times. Grappling with the truth, I started first with loading whatever I would need for my project: album cover art, that font Spotify uses, the actual songs I would have in the library (definitely not downloaded from a sketchy website that might as well have phished me). I picked the songs very intricately to kind of form a parallel with the stages of procrastination as experienced by me:


Gangtey- aswekeepsearching

This song by Indian band aswekeepsearching represents for me the stage where my assignment’s deadline is far away and not thinking about it poses no immediate threat. The repeated mystifying chants are melancholic, but calm.

 


Kalga – aswekeepsearching

By the same band, this one represents the shift from the calm to the storm. It starts off calm but is then interrupted by loud drums and vocals, representing the interruption of calm by dread when the realization of incoming deadlines hits.

 

 

Nahin Milta – Bayaan

Nahin Milta, by Pakistani bad Bayaan, is a song about acceptance following hopelessness. Which in the sense of procrastination is pretty self-explanatory…

 

 

 

Tasveer – Mooroo

Another melancholic but calm song, this one you’d listen to while finally working on your assignment, maybe even singing along with it. Maybe don’t look too much into the lyrics though, because it can get sad. Tasveer means picture, and Mooroo sings about spent memories only living in pictures after they are lived.

Ayi Bahaar – Kashmir

This upbeat song is about the coming of spring. You guessed it – you’ve finally finished your assignment, and things aren’t too bad after all. There is still good in the world.

 

 

Here is the  playlist that I’ve used in my sketch:

After loading everything, I had to think of the logic behind different functions of a music player: play, pause, skip, go back, add to favorites, etc. At one point I was convinced that I would in no way be able to do all that because I could not for the life of me figure out how to implement  it. A few long walks later, I decided to start writing in the hopes that it would come to me itself; and come to me it did. I implemented the whole music player as  a class with methods for displaying relevant information like images, shapes, text, etc. It starts at a screen that introduces the concept and requires you to click to begin the experience. You can return to the screen from the music player by pressing any key on the keyboard. In the player, you can pause and play songs, skip to the next song, go back to the previous song, repeating the same 5 songs without going out of bounds. The code aspect can be understood using the comments on my sketch, the link to which I have provided below:

https://editor.p5js.org/haroonshafi/sketches/9mTUs7KrB

SKETCH

Here is how I wanted my sketch to look like:

Here is the sketch:

I am quite proud of finally figuring out the million conditions for implementing playback options. Embedded below are specific parts of the code: the first one that displays the details for a single song and the second skips the current song.

case 0:
        background("#484848"); // set background according to colour of album cover

        push(); // drop down icon
        strokeWeight(4);
        stroke("#373737");
        line(this.x, 0.7 * height, (width * 8) / 9, 0.7 * height);
        stroke(220);
        line(
          // duration slider constantly updating as time passes using the ratio of two methods as follows
          this.x,
          0.7 * height,
          (gangteyAudio.currentTime() / gangteyAudio.duration()) *
            (7 / 9) *
            width +
            (1 / 9) * width,
          0.7 * height
        );
        pop();

        textFont(gothamBlack);
        textSize(16);
        fill(240);
        text(songNames[songNum], this.x, this.y); // displaying name of song
        textFont(gothamThin);
        textSize(12);
        fill(220, 220, 220, 150);
        text(artistNames[songNum], this.x, this.y + 20); // displaying artist name

        textSize(10); // the following code displays the time of the song and its duration in minutes and instead of showing it in seconds by default by using modulus and integer division functions
        text(
          Math.floor(gangteyAudio.currentTime() / 60),
          this.x,
          0.7 * height + 15
        );
        text(":", this.x + 7, 0.7 * height + 15);
        if (Math.floor(gangteyAudio.currentTime() % 60) < 10) {
          text("0", this.x + 10, 0.7 * height + 15);
          text(
            Math.floor(gangteyAudio.currentTime() % 60),
            this.x + 17,
            0.7 * height + 15
          );
        } else {
          text(
            Math.floor(gangteyAudio.currentTime() % 60),
            this.x + 10,
            0.7 * height + 15
          );
        }
        text(
          Math.floor(gangteyAudio.duration() / 60),
          (8 / 9) * width - 15,
          0.7 * height + 15
        );
        text(":", (8 / 9) * width - 8, 0.7 * height + 15);
        text(
          Math.floor(gangteyAudio.duration() % 60),
          (8 / 9) * width - 5,
          0.7 * height + 15
        );

        if (gangteyAudio.isPlaying()) {
          // for alternating between the pause/play icon shape
          fill(220);
          noStroke();
          circle(width * 0.5, height * 0.85, 60);
          fill(0);
          rect(width * 0.5 - 8, height * 0.85 - 12, 4, 24);
          rect(width * 0.5 + 4, height * 0.85 - 12, 4, 24);
        } else {
          fill(220);
          noStroke();
          circle(width * 0.5, height * 0.85, 60);
          fill(0);
          triangle(
            width * 0.5 - 6,
            height * 0.85 + 10,
            width * 0.5 - 6,
            height * 0.85 - 10,
            width * 0.5 + 10,
            height * 0.85
          );
        }

        image(
          // displaying album cover
          gangteyImage,
          (1 / 9) * width,
          0.2 * width,
          (7 / 9) * width,
          (7 / 9) * width
        );
        break;
if (
      // if forward icon pressed
      mouseIsPressed &&
      mouseY > height * 0.85 - 12 &&
      mouseY < height * 0.85 + 12 &&
      mouseX > width * 0.7 - 10 &&
      mouseX < width * 0.7 + 12
    ) {
      greenFlag = 1; // reset heart flag to clear as song changes
      switch (
        songNum // stop song currently playing
      ) {
        case 0:
          if (gangteyAudio.isPlaying()) {
            gangteyAudio.stop();
          }
          break;
        case 1:
          if (kalgaAudio.isPlaying()) {
            kalgaAudio.stop();
          }
          break;
        case 2:
          if (nahinMiltaAudio.isPlaying()) {
            nahinMiltaAudio.stop();
          }
          break;
        case 3:
          if (tasveerAudio.isPlaying()) {
            tasveerAudio.stop();
          }
          break;
        case 4:
          if (ayiBahaarAudio.isPlaying()) {
            ayiBahaarAudio.stop();
          }
          break;
      }
      if (songNum == 4) {
        // update index to next index by incrementing
        songNum = 0;
      } else {
        songNum += 1;
      }
      switch (
        songNum // play song from next index
      ) {
        case 0:
          if (gangteyAudio.isPlaying() == false) {
            gangteyAudio.play();
          }
          break;
        case 1:
          if (kalgaAudio.isPlaying() == false) {
            kalgaAudio.play();
          }
          break;
        case 2:
          if (nahinMiltaAudio.isPlaying() == false) {
            nahinMiltaAudio.play();
          }
          break;
        case 3:
          if (tasveerAudio.isPlaying() == false) {
            tasveerAudio.play();
          }
          break;
        case 4:
          if (ayiBahaarAudio.isPlaying() == false) {
            ayiBahaarAudio.play();
          }
          break;
      }
    }

I think it is possible to enhance the functionality even more, for example by enabling shuffle, but this specific playlist is meant to be listened to in its exact order so maybe next time! Other than that, I am quite satisfied that even though I didn’t think it possible in the beginning, by revisiting the concepts and spending hours revising everything we’ve learnt so far and even checking out some other concepts, in the end I was able to bring my concept to life. Also, you guys should definitely put this playlist on while on a walk and maybe tell me what you thought about it! Hope you like the experience!

Midterm Project: I’m Not/Too Bored

Concept:

Boredom is a state of mind that craves some type of change. I ask myself sometimes when was the last time I have gotten bored. My answer would be is that I do not remember. While discussing other’s people state or level of boredom, I can see a glimpse of the different life each one of us has. As well as the pace humans like to take for themselves.

In my game I’m Not/Too Bored I wanted to create a dialogue between characters that experince different life pace than others. Each holds a unique lifestyle that changes how they decide to go on with their way of living. While engaging in a conversation with three people, I want to gain data, that shouldn’t be too seriously taken, to showcase the level of boredom the player might experince in life. I could also add a little input that could help them as I myself never get bored.

Process:

I started with the type of questions I wanted to ask, but I also didn’t want to make them way too deep; mostly because the results are not serious.

I started by coming up with NPC designs both in a small miniture version and the speaking version.

Drawing the background was fun as it was the first time drawing in pixels.

 

 

Code:

Coding could be said as the most diffecult and least enjoyable part. However I did manege to add my images, sound, and font to my likings.

 

In the code below is how I made my characters clickable so they could answer the questions.

    // Check if a character is clicked and handle interactions
    if (
      mouseX > 50 &&
      mouseX < 50 + hugo.width &&
      mouseY > 135 &&
      mouseY < 135 + hugo.height
    ) {
      // Handle interactions for Hugo character
      // Display questions for Hugo and handle answers
    } else if (
      mouseX > 280 &&
      mouseX < 280 + rene.width &&
      mouseY > 162 &&
      mouseY < 162 + rene.height
    ) {
      // Handle interactions for Rene character
      // Display questions for Rene and handle answers
    } else if (
      mouseX > 0 &&
      mouseX < fuLi.width &&
      mouseY > 0 &&
      mouseY < fuLi.height
    ) {
      // Handle interactions for Fuli character
      // Display questions for Fuli and handle answers
    }
  }
}

This is the class where the questions were saved:

class Questions {
  constructor() {
    this.characterQuestions = {
      hugo: [
        { question: "Is it easy for you to concentrate on your activities?", options: ["Yes", "No", "Maybe/Sometimes"] },
        { question: "Frequently when you're working do you find yourself worrying about other things?", options: ["Yes", "No", "Maybe/Sometimes"] },
        { question: "Does time always seem to be passing slowly?", options: ["Yes", "No", "Maybe/Sometimes"] },
      ],
      rene: [
        { question: "Do you often find yourself at 'loose ends,' not knowing what to do?", options: ["Yes", "No", "Maybe/Sometimes"] },
        { question: "Do you often get trapped in situations where you find yourself doing meaningless things?", options: ["Yes", "No", "Maybe/Sometimes"] },
        { question: "Does having to look at someone's home movies or travel pics bore you tremendously?", options: ["Yes", "No", "Maybe/Sometimes"] },
      ],
      fuli: [
        { question: "Do you find it easy to entertain yourself?", options: ["Yes", "No", "Maybe/Sometimes"] },
        { question: "In any situation, you can usually find something to do or see to keep yourself interested.", options: ["Yes", "No", "Maybe/Sometimes"] },
        { question: "Much of the time you just sit around doing nothing, and you are very good at being patient.", options: ["Yes", "No", "Maybe/Sometimes"] },
      ],
    };
  }

  getQuestion(character, questionIndex) {
    return this.characterQuestions[character][questionIndex];
  }

  calculateResults(answers) {
    const counts = { Yes: 0, No: 0, 'Maybe/Sometimes': 0 };

    answers.forEach(answer => {
      counts[answer]++;
    });

    const maxCount = Math.max(...Object.values(counts));
    const majorityAnswer = Object.keys(counts).find(key => counts[key] === maxCount);

    return majorityAnswer;
  }
}

// Export the Questions class for use in sketch.js
module.exports = Questions;

Possible Improvement:

I wish I could go around the local server issues when it comes to displaying my images.

I want only for certain keys to play the sound not all of them.

I wanted to showcase the results in a different way.

 

Edit: https://editor.p5js.org/mariamalkhoori/sketches/L-i2O01PV

Midterm Project: The Sea

I frequent a tiny film theater back home. For a while, they were streaming old films from the French New Wave every day, and I would stop in after school to watch Breathless or Children of Paradise and whatnot. But my favorite out of them all was The 400 Blows. I still remember that little yellow text at the bottom of the screen. I guess a lot of people do. That’s why you’ll see film text on nearly every poetry post on Instagram these days. Celebrity photographer @sarahbahbah made a whole career off of it. See below a still from  The 400 Blows:

Karina died. And I don’t know what that means. I don’t know what to do about it. I don’t know what to do about any of it. Fucking Palestine. Allen Iverson never won a championship. Everyone sucks. Even as I write this, you’re not going to understand what I’m saying. And that sucks too. There’s this great Samuel Beckett quote: “You’re on Earth. There’s no cure for that.” And how true that is! The night after Karina died, we went to the ocean. I don’t want to talk about it too much because it’s not really something that can be talked about. But I tried to code what I had seen at the ocean that night. I’ll let what I made speak for itself:

In my last Midterm update, I posted about a morphing mandalas video I had seen on Youtube. It was mesmerizing. I tried to emulate that by coding the pulsating circles. At some points, the project looks like a big eye:

Sometimes, the abyss will creep up on you. That’s why the saying goes, “The abyss stares back,” because it really does. I hope my project conveyed that. I coded the pulsing circle, the changing text, and the sound in separate tabs before combining them together, just to make sure I understood the logic of everything that was going on before overwhelming myself. I’ve posted the links to each here:

https://editor.p5js.org/EloraTrotter/sketches/UtiZG2jDy
https://editor.p5js.org/EloraTrotter/sketches/yKrbaYS2A
https://editor.p5js.org/EloraTrotter/sketches/EMQC92jbz
https://editor.p5js.org/EloraTrotter/sketches/PLBd_2y6e

And while I am, uh, proud, of what I made. I also recognize that my code is very inefficient. For example:

var maxDiameter;
var secondmaxDiameter;
var thirdmaxDiameter;
var fourthmaxDiameter;
var fifthmaxDiameter;
var sixthmaxDiameter;
var seventhmaxDiameter;
var eightmaxDiameter;
var theta;

function setup() {
  createCanvas(900, 500);
  
// establish the parameters for the max diameter of each circle
  maxDiameter = 1000;
  secondmaxDiameter = 700;
  thirdmaxDiameter = 600;
  fourthmaxDiameter = 300;
  fifthmaxDiameter = 150;
  sixthmaxDiameter = 90;
  seventhmaxDiameter = 50;
  eighthmaxDiameter = 20;

And:

// calculate the diameter of the circle
//height/2 + sin(theta) * amplitude
  var diam = 100 + sin(theta) * maxDiameter;
  var seconddiam = 100 + sin(theta) * secondmaxDiameter;
  var thirddiam = 100 + sin(theta) * thirdmaxDiameter;
  var fourthdiam = 100 + sin(theta) * fourthmaxDiameter;
  var fifthdiam = 100 + sin(theta) * fifthmaxDiameter;
  var sixthdiam = 100 + sin(theta) * sixthmaxDiameter;
  var seventhdiam = 100 + sin(theta) * seventhmaxDiameter;
  var eighthdiam = 100 + sin(theta) * eighthmaxDiameter;

// draw the circles
  stroke(0);
  strokeWeight(0);
  fill(40);
  ellipse(width / 2, height / 2, diam, diam);
  fill(35);
  ellipse(width / 2, height / 2, seconddiam, seconddiam);
  fill(30);
  ellipse(width / 2, height / 2, thirddiam, thirddiam);
  fill(25);
  ellipse(width / 2, height / 2, fourthdiam, fourthdiam);
  fill(20);
  ellipse(width / 2, height / 2, fifthdiam, fifthdiam);
  fill(15);
  ellipse(width / 2, height / 2, sixthdiam, sixthdiam);
  fill(10);
  ellipse(width / 2, height / 2, seventhdiam, seventhdiam);
  fill(2);
  ellipse(width / 2, height / 2, eighthdiam, eighthdiam);

See how I list everything out one by one when I could sort it into different classes, etc. To be honest, even though I bare-bones know what I should do to make the code cleaner, I have no idea how. And the idea of not having every single line of code cut clear in front me line by line, one by one, was quite overwhelming.

I guess I’m proud that I was able to do any of this. This life is a weird one. There’s this great Emil Cioran quote that goes: “If your hardships do not make you grow, and do not put you in a state of energetic euphoria, but rather depress and embitter you, know that you have no spiritual vocation.” Kawhi Leonard still played basketball the night his dad died. I was watching a playoff game last summer, and the commentator said about Kevin Durant or someone else, “He never gets tired!” And isn’t that exactly what we demand from each other? If you, for a moment, expose your exhaustion, we know: You have no spiritual vocation. That’s our judgment anyways. And why humans are so compelled towards judgement rather than understanding, I don’t understand that either. Every man must decide for himself whether he has a spiritual vocation. Lord, that’s something I’m figuring out these days.

MID TERM – Metaportal

MIDTERM

Metaportal : The brain spa

 

Concept

The Metaportal stands out as more than just your average project – it’s a creative endeavor that goes far beyond merely combining different artworks. This undertaking pays meticulous attention to every single component, ensuring that no detail is left to chance. From the welcoming and user-friendly interface to the delightful surprises cleverly hidden within each project, it’s clear that this is a labor of love.

Imagine it as a portal, leading you into a fresh realm of art, focus, and entertainment. As you explore, you’ll find yourself captivated by the fusion of creativity and functionality, where every aspect has been carefully tailored to enhance your experience. So, it’s not just a project; it’s a journey into an entirely new dimension of artistic expression, concentration, and sheer enjoyment.

The project’s concept revolved around the creation of an immersive gateway to showcase various distinct visual designs. It all began with the development of numerous visual art pieces employing tools like sine, cosine, angles, orbitControl, rotateX, and rotateY. After a prolific phase of crafting diverse visual designs, the objective shifted towards elevating the presentation. The aim was to construct a unified platform where each artwork could be elegantly exhibited, much like individual pieces of art.

the work of art

After extensive brainstorming and numerous iterations, I devised a captivating and aesthetic solution: a dynamically rotating “space” themed background, which I chose as the project’s main page. With the background in place, my next challenge was to create the entry points or “buttons” for users to explore and view the different art pieces. Given the uniqueness of each artwork, a conventional side-by-side display was not suitable. Instead, I opted to craft distinct 3D spherical structures using the same elements as the background. This choice lent a cohesive and consistent appearance to the main page. Notably, there were no previews of the artwork; instead, I incorporated question marks within these spheres, which, upon clicking, would transition users to the respective art pieces, enticing users to delve further into the virtual space.

After successfully creating the main page and investing countless hours in debugging, the next step was to introduce audio to the project. I decided to use a no-copyright interstellar-themed instrumental track to complement the visuals. The real challenge arose when I aimed to link the spheres with question marks to other art pieces, each presenting its own unique set of visuals. It was a daunting task, and I spent hours searching for a suitable function within p5.js that would allow me to create hyperlinks for transitioning between these projects. While I did find the “CreateA” function, which was helpful for establishing links from the main page to the intended sketch, I encountered a significant roadblock: p5.js did not support the ability to navigate back to the main page seamlessly. This limitation posed a considerable obstacle, particularly because I had opted not to use separate pages due to the project’s rendering-intensive nature. Combining all the visual projects in a single file was not a viable solution, as it would overwhelm p5.js and result in crashes. After enduring hours of stress and frustration, I finally discovered that the only viable approach was to circumvent the p5.js terminal entirely. In a determined effort to overcome this challenge, I downloaded all the p5.js project files I had and imported them into Visual Studio Code. While I continued to work with the p5.js language, I was no longer reliant on their terminal. In this new environment, I successfully managed to establish the desired interconnections between all the projects.

Afterwards, I focused on incorporating audio into the visual art pieces, which added an even more artistic dimension to the project. Given the uniqueness of each artwork, it necessitated selecting audio that harmonized with the colors, tempo, and patterns of each piece. As someone who enjoys instrumental music, particularly the saxophone, I began exploring a variety of non-copyrighted pieces for use in the project. Once I had gathered a selection, I aimed not only to create a visually appealing and aesthetically pleasing experience for users but also to infuse a bit of my personality into it, making it truly my own. To achieve this, I handpicked a few songs that I personally love, such as “Sway” by Michael Bublé and some tracks by Amr Diab, like “Tamally Maak,” in their instrumental versions. I opted for this approach to ensure that users could be fully immersed in the experience, regardless of their familiarity with the songs being played. For those who recognized the selected pieces, it would also serve as a delightful easter egg! Since I found the visual art to be highly enjoyable and calming, I also incorporated some lofi music into a few of my projects for the user to relax and have it as a background music.

The Main page – (p5 Incomplete)

click this link to open the p5 project on github

https://zuett.github.io/Intro-midterm/

 

Reflection

I’m thrilled about the prospect of advancing this project, as I envision it evolving into a captivating immersive visual experience. The idea is to create an application that users can seamlessly run in the background on a secondary screen, enabling them to enhance their focus on work and find moments to unwind in the midst of their daily tasks.

Imagine users being able to effortlessly integrate this immersive experience into their work environment. As they navigate their tasks and responsibilities on their primary screen, this secondary visual journey would serve as a calming and engaging companion. It will not only elevate their concentration but also provide an escape into a world of soothing illusions, offering a mental retreat right at their fingertips. This concept is a fusion of work and relaxation, a unique blend of productivity and serenity. Users can toggle their attention between their primary work and this immersive backdrop as needed, seamlessly transitioning from deep concentration to brief mental respites. It’s all about creating a harmonious balance, where work and relaxation coexist in perfect synergy. As I continue working on this project, the goal is to develop an extensive array of visually captivating scenes and experiences, each carefully designed to induce a sense of calm, creativity, and inspiration. These scenes will be more than just eye candy; they will be crafted to promote mental well-being, helping users recharge and refocus whenever they need it. In essence, this immersive background experience is not just a tool but a companion, a portal to a world of tranquility and aesthetic delight, ready to aid users on their journey towards enhanced productivity and a balanced, focused mind.

Iron Knock- Midterm Project

The name of my project originated from a saying back home used to describe the sounds of the steelpan being played, or the steel pan being tuned.

My project aimed to introduce users to the steelpan, the national instrument of Trinidad and Tobago, and provide them with an immersive experience of this unique musical creation. The steelpan’s distinct melodic, tonal, and rhythmic qualities have garnered global fascination and serve as a prominent cultural symbol of Trinidad and Tobago. Originally crafted from items like frying pans, dustbin lids, and oil drums in the 1930s, the steelpan has evolved into finely tuned sheet metal instruments.

Listening to the steelpan evokes a childlike sense of wonder, in me, and I think every other Trinbagonian. While it may sound like a cliché description of the emotional connection to music, it holds a profound truth, especially for Trinbagonians. The steelpan’s significance extends beyond its musical charm, intertwining with the cultural heritage and historical resistance against slavery in Trinidad and Tobago.

 

The vibrant chaos witnessed at events like Panorama captures the essence of steelpan music. It’s a beautiful chaos where everyone, regardless of age, is in motion. Steelpan is an integral part of the Trinbagonian identity, and I sought to convey this dynamic energy through the moving background, creating an immersive feeling that aligns with the live performances involving this extraordinary instrument.

The sketch revolves around a steelpan instrument and is divided into an introduction screen, instructions screen and a game screen. The introduction screen offers options to start, end, or view instructions. Transitions between these states are controlled through flags (isIntroduction, isInstructions, isPlaying). In the game screen, there’s a scrolling background, and users can click on different segments of the steelpan to produce sounds. The instrument comprises three rows, and each row, represents the pitch, with the outer row, being the lowest, and the inner row, being the highest as these notes are smaller. The code checks the mouse’s proximity to trigger sound playback, and this is essentially how the user utilizes the sketch.

The part I’m most proud of is the Steelpan class in the p5.js sketch. It plays a vital role in managing and rendering the steelpan instrument, handling data about rows, labels, angles, and radii. The draw method takes care of the visual representation, managing row iteration, position calculation, and segment colour changes upon mouse hover. This class adheres to object-oriented principles, ensuring well-structured and maintainable code for the steelpan instrument.

class SteelPan {
  constructor(outerCount, middleCount, coreCount, outerRadius, middleRadius, coreRadius) {
    this.outerCount = outerCount;
    this.middleCount = middleCount;
    this.coreCount = coreCount;
    this.totalNotes = outerCount + middleCount + coreCount;
    this.outerLabels = ["A", "D", "G", "C", "F", "B♭", "E♭", "G#", "C#", "F#", "B", "E"];
    this.middleLabels = ["Am", "Dm", "Gm", "Cm", "Fm", "B♭m", "E♭m", "G#m", "C#m", "F#m", "Bm", "Em"];
    this.coreLabels = ["e", "d", "c", "e♭", "c#"];
    this.angleIncrementOuter = TWO_PI / outerCount;
    this.angleIncrementMiddle = TWO_PI / middleCount;
    this.angleIncrementCore = TWO_PI / coreCount;
    this.outerRadius = outerRadius;
    this.middleRadius = middleRadius;
    this.coreRadius = coreRadius;
  }

  draw() {
    fill(100, 100, 100);
    stroke(10);
    ellipse(width / 2, height / 2, 400, 400);

    // Draw the outer row
    for (let i = 0; i < this.outerCount; i++) {
      let angleOuter = i * this.angleIncrementOuter;
      let x = width / 2 + cos(angleOuter) * this.outerRadius;
      let y = height / 2 + sin(angleOuter) * this.outerRadius;
      let circleSize = 50;

      if (dist(mouseX, mouseY, x, y) < circleSize / 2) {
        fill('grey'); // Change to a darker color when hovering
      } else {
        fill('white'); // Default color
      }

      ellipse(x, y, circleSize, 70);
      fill(255);
      textSize(14);
      textAlign(CENTER, CENTER);
      text(this.outerLabels[i], x, y);
    }

    // Draw the middle row
    for (let i = 0; i < this.middleCount; i++) {
      let angleMiddle = i * this.angleIncrementMiddle;
      let x = width / 2 + cos(angleMiddle) * this.middleRadius;
      let y = height / 2 + sin(angleMiddle) * this.middleRadius;
      let circleSize = 50;

      if (dist(mouseX, mouseY, x, y) < circleSize / 2) {
        fill('darkgrey'); // Change to a darker color when hovering
      } else {
        fill('black'); // Default color
      }

      ellipse(x, y, circleSize, 40);
      fill(255);
      textSize(14);
      textAlign(CENTER, CENTER);
      text(this.middleLabels[i], x, y);
    }

    // Draw the core row
    for (let i = 0; i < this.coreCount; i++) {
      let angleCore = i * this.angleIncrementCore;
      let x = width / 2 + cos(angleCore) * this.coreRadius;
      let y = height / 2 + sin(angleCore) * this.coreRadius;
      let circleSize = 30;

      if (dist(mouseX, mouseY, x, y) < circleSize / 2) {
        fill('darkred'); // Change to a darker color when hovering
      } else {
        fill(255, 0, 0); // Default color
      }

      ellipse(x, y, circleSize, circleSize);
      fill(255);
      textSize(14);
      textAlign(CENTER, CENTER);
      text(this.coreLabels[i], x, y);
    }
  }
}

Moreover, I take pride in successfully managing the specific sounds assigned to each note in the steelpan. Proper labelling and space allocation were crucial, and the effort put into uploading each note and linking it to the sketch brought the project to life, achieving the desired outcome. This, however, was by far the most tedious process, and the most challenging, because my initial plan to source the notes via an online website failed. So instead, I had a family member play each individual note on the steelpan, record it and send it to me.

To enhance this project, I have several goals in mind. Firstly, I aim to refine the note playing functionality to allow for overlapping sounds, ensuring a seamless musical experience. This will enable me to capture the authentic rhythm and intricacies of the steelpan, encompassing elements like melody, rhythm, and harmony. Additionally, I want to introduce a multiplayer aspect by using the steelpan class to create multiple pans. This would provide users with a glimpse into the dynamics of a real Steelpan band.

Despite the challenges, I take pride in the outcome of this project. It served as a combination of the knowledge I’ve acquired over the past seven week, plus some. It highlights my integration of various concepts and techniques and reflects my dedication to my home, Trinidad, and Tobago. Below is the embedded sketch.

MIDTERM PROJECT “AURA”

https://editor.p5js.org/dianadonatella/sketches/0Rv4DeXZ_

Concept:

My project was inspired by a series of paintings that I created over the last couple of weeks. I am not sure why exactly, but this style of painting really speaks to me.  It allows me to freely paint using as many colors as my heart desires. It was once stated to me that my pieces reminded people of energies, specifically auras. This idea became the foundation of my midterm project. My initial goal was to create a sketch that allowed for user input to type in an initial of their name and generate a unique interpretation of their aura both visually and sonically. Unfortunately due to the amount of errors and complications I faced during this process the idea has slightly shifted.  Now the user can actually build their own depiction of their aura by typing in single letters to generate a concoction of colors and sounds. Though this wasn’t the initial idea, I actually think this process is much more interactive for the user, giving the user more control of how they want their “aura” to look or sound.

The program starts with the following opening image:

I made this image in Canva with their free gradient backgrounds and added the butterfly and text as well!

The user then has access to the user input when they click generate, which generates the base color of their sketch. In the box directly next to it, the user can input ONE capitalized letter at a time, creating a wall of color and sound to build what their aura looks and sounds like.

What I have implemented into my code from class!

Within my code I have made use of CSV files and images:

function preload() {
  bg = loadImage('gradient.png')
  initials = loadTable("initials.csv", "csv", "header");

I used sound (specifically .wav files):

 
//continuation of the preload section
songA = loadSound("A.wav");
  songB = loadSound("B.wav");
  songC = loadSound("C.wav");
  songD = loadSound("D.wav");
  songE = loadSound("E.wav");
  songF = loadSound("F.wav");
  songG = loadSound("G.wav");
  songH = loadSound("H.wav");
  songI = loadSound("I.wav");
  songJ = loadSound("J.wav");
  songK = loadSound("K.wav");
  songL = loadSound("L.wav");
  songM = loadSound("M.wav");
  songN = loadSound("N.wav");
  songO = loadSound("O.wav");
  songP = loadSound("P.wav");
  songQ = loadSound("Q.wav");
  songR = loadSound("R.wav");
  songS = loadSound("S.wav");
  songT = loadSound("T.wav");
  songU = loadSound("U.wav");
  songV = loadSound("V.wav");
  songW = loadSound("W.wav");
  songX = loadSound("X.wav");
  songY = loadSound("Y.wav");
  songZ = loadSound("Z.wav");

I used functions:

//function for main page (SIMPLE EXAMPLE
function main_page() {
  // sets up variables to get the alphabet and color columns
  alphabet = initials.getColumn("alphabet");
  color1 = initials.getColumn("color1");
  color2 = initials.getColumn("color2");
  color3 = initials.getColumn("color3");

I used conditional statements:

if (initial === "A") {
   songA.playMode("untilDone");
   songA.play();

 }
 if (initial === "B") {
   songB.playMode("untilDone");
   songB.play();
   
 }

 if (initial === "C") {
   songC.playMode("untilDone");
   songC.play();
 }

 if (initial === "D") {
   songD.playMode("untilDone");
   songD.play();
 }

 if (initial === "E") {
   songE.playMode("untilDone");
   songE.play();
 }

 if (initial === "F") {
   songF.playMode("untilDone");
   songF.play();
 }

 if (initial === "G") {
   songG.playMode("untilDone");
   songG.play();
 }

 if (initial === "H") {
   songH.playMode("untilDone");
   songH.play();
 }

 if (initial === "I") {
   songI.playMode("untilDone");
   songI.play();
 }

 if (initial === "J") {
   songJ.playMode("untilDone");
   songJ.play();
 }

 if (initial === "K") {
   songK.playMode("untilDone");
   songK.play();
 }

I used User input/buttons/text:

//function for homescreen 
function homescreen() {
  fill("white");
  square(0, 0, width);
  background(bg);

  fill(0);
 
  text("Click generate & type in a letter!", width/7.5, 20);
  textAlign(CENTER);
  textSize(14);
  
  input = createInput();
  input.position(20, 30);
  button = createButton("generate");

I used arrays:

// an arrray to store the Particles
let particles = []; // variable for the particles
const num = 3500; // how many particles will be displayed

 

An extra step! (USING LOGIC PRO X and PLUGINS)

This is the DAW that I used to create the Sounds/Chords for my project. They are all synthesizers!

Parts you are proud of or challenges you have overcome:

I am really happy that I was able to achieve a similar interpretation of my painted pieces. I feel that not including a background and letting the perlin noise loop really brought the stroke affect and colors out of my paintings.

for (let i = 0; i < num; i++) {
    let p = particles[i];
    square(p.x, p.y, 2);

    color1 = color(colors_for_sample[0]);
    color2 = color(colors_for_sample[1]);

    fill(lerpColor(color1, color2, noise(p.x * noiseScale, p.y * noiseScale))); // lerpColor() function is used to interpolate two colors to find a third color between them.
    noStroke();

    let n = noise(p.x * noiseScale, p.y * noiseScale); //Multiplies the x-coordinate of the point p by a value noiseScale.... Multiplies the y-coordinate of the point p by the same value noiseScale. X and y coordinates are mutiplied by the noise scale before passed onto the noise. Basically generates random-like values based on the input coordinates and maps out the coordinates before the noise is generated
    let a = TAU * n; //TAU = 2PI & n = value calculated in previous line
    p.x += cos(a); // incrementing the x and y coordinates of a point based on the cosine and sine of angle (a)
    p.y += sin(a);
  }

I really wish that my code didn’t have to be so redundant when including the sound files. Having lines like these:

if (initial === "A") {
    songA.playMode("untilDone");
    songA.play();

  }
  if (initial === "B") {
    songB.playMode("untilDone");
    songB.play();
    
  }

  if (initial === "C") {
    songC.playMode("untilDone");
    songC.play();
  }

  if (initial === "D") {
    songD.playMode("untilDone");
    songD.play();
  }

  if (initial === "E") {
    songE.playMode("untilDone");
    songE.play();
  }

  if (initial === "F") {
    songF.playMode("untilDone");
    songF.play();
  }

really stunted my mobility within the code, made figuring out errors 1,000,o00 times harder, was very overwhelming to look at, and took so much extra time to write out, (even if copy and pasted).

In the future, I would really like to work on expanding on this project and creating a better set up around the user input, since it’s a bit plain and doesn’t really contain a means of restarting the sketch. My sketch overall is really lacking user input which is such a key aspect of any interactive piece, so for that I am a bit disappointed with my project.

Midterm Final

                                                                  PuzzlePlay

This project idea sprang from something personal and relatable – my sister’s love for solving puzzles. It always fascinates me yet triggers me how she has the patience and dedication to tackle intricate puzzles. It got me thinking, why not bring that captivating experience into the digital realm? I want to create a digital puzzle game that captures the essence of those satisfying moments when you piece together the final part of a puzzle.

The concept of the game is to offer players an engaging and mentally stimulating experience. We’ve all experienced the satisfaction of solving a puzzle, and it’s this joy that served as our inspiration. The game is designed to provide players with a series of puzzles that vary in complexity. It’s a journey through creativity and problem-solving.

Coding, Logic, and Planning:
My journey in developing this puzzle game involved a bit of trial and error. It commenced with two drafts, each aimed at refining and enhancing the user experience. Initially, I allowed users to adjust the number of columns and rows within the puzzle, providing them with a sense of control over the challenge level. It was a good start, but I soon realized I could infuse more excitement into the gameplay.

That’s when the concept of progressive difficulty levels took shape. Instead of sticking with static user-defined settings, I decided to make the game more engaging. By adjusting the number of puzzle pieces, I introduced a system where each level offered a fresh challenge, making the game more exhilarating as players advanced. This change not only improved the game’s overall flow but also elevated the overall gaming experience.

In the initial stages, the game featured a flower image, a mere placeholder. However, as the project evolved, I decided to swap it out for images that resonate with me on a personal level. Drawing from my passions for photography, art, and horseriding.

 

Draft 1
Process
Final

As I developed this puzzle game, I planned the logic to offer players a compelling and progressively challenging experience. The heart of this game lies in its puzzles and how users engage with them as they progress through different levels. Each level presents a unique grid size and time frame, with Level 1 granting players 5 minutes, Level 2 extending the challenge to 10  minutes, and Level 3 pushing their limits with 15 minutes to solve the puzzle. This escalating difficulty curve keeps players engaged and motivated to sharpen their puzzle-solving skills.

To accommodate these time limits and provide feedback to the player, I incorporated an intelligent system of game states. When players successfully solve a puzzle within the given time, they are rewarded with a “Congratulations” page. However, if they run out of time or fail to complete the puzzle, a “You Lost” page is displayed. I further enhanced the player experience by allowing them to restart the game by pressing “R” or returning to the home screen by hitting the space bar. These features allow players to navigate the game according to their preferences, ensuring an enjoyable and engaging gaming experience.

I’ve created all my backgrounds through Canva and then uploaded them into my code here are some examples:

Challenges:

Image Manipulation and Sizing was the most challenging part for me when I was working on the code. I struggled with it because resizing images while maintaining their aspect ratios and making sure they fit the game’s grid properly required a good deal of trial and error. It was a bit tricky to get the images to display correctly without distortion or going beyond the bounds of the grid. However, through experimentation and some research, I was able to overcome this challenge and get the images to work as intended in my game.

// Preload all the images and sounds
function preload() {
  bg_main_Page = loadImage("/images/Main_Page1.png");
  bg_instructions_Page = loadImage("/images/Instructions_Page1.png");
  bg_Congrats_Page = loadImage("/images/Congrats_Page1.png");
  bg_Lost_Page = loadImage("/images/Lost_Page1.png");

  levels.level1.image = loadImage("/images/paint.jpg", () => {
    levels.level1.image.resize(400, 400);
  });

  levels.level2.image = loadImage("/images/horse.jpeg", () => {
    levels.level2.image.resize(450, 450);
  });

  levels.level3.image = loadImage("/images/carpet.jpg", () => {
    levels.level3.image.resize(400, 400);
  });
}

In this part of the code, I loaded different images using the loadImage function and then used the .resize() method on these images to adjust their dimensions. Image resizing is done to fit these images into specific dimensions before using them in the game.

Areas for improvement, future work:

In terms of areas for improvement and future work, I’d like to focus more on enhancing the visual aspect of the game. Currently, the game uses a black background for the puzzle grid, which is rather plain. To make the game more visually appealing, I would consider creating unique and visually engaging backgrounds for each level. For instance, I could design backgrounds that complement the theme of the puzzle, creating a more immersive experience for the players. Additionally, I’d extend this effort to the main screen as well, making it more captivating and visually appealing to draw players into the game right from the start. Improving the visual elements would not only enhance the game’s aesthetics but also contribute to a more enjoyable and engaging gaming experience.

References:

https://observablehq.com/@kjhollen/loading-data-and-images-in-p5-js-with-observable

 

Final Midterm: Generative Gallery: A Digital Art Experience

Concept: 

Whenever I step into an art gallery, I am captivated by the stories each artwork tells, the vibrant strokes on the canvas, and the interplay of light and shadow. Inspired by these immersive experiences, I wanted to recreate a similar atmosphere, merging the tranquility of a gallery with the excitement of interaction. My vision for the p5.js Art Gallery centered around creating a dynamic and immersive digital space that embodies the essence of generative art. Influenced by the interplay of light and space, I aimed to design an environment that encourages exploration and creative expression. Extensive research into contemporary digital art installations and interactive galleries inspired the overall concept, guiding me in the creation of an engaging and visually captivating experience for visitors.

The central idea behind my project is to encourage users to explore the art at their own pace and immerse themselves in the diverse creations on display. To achieve this, I plan to incorporate interactive elements such as virtual paintings that users can admire, virtual sculptures they can examine from all angles, and informational pop-ups that offer insights into each artwork. By subtly integrating these interactive features, I aim to evoke curiosity and invite users to engage with the art, thereby fostering a unique and personalized gallery experience for each visitor.

Wireframes I drew for my project:


In planning the sketch, my approach involved meticulous consideration of user experience and interaction design.. By integrating logical operations, including conditional statements, loops, and rendering functions, I aimed to ensure a seamless and engaging user journey within the gallery. Hand sketches and diagrams were instrumental in mapping out the flow of user interactions and visualizing the logical structure of the coding process, facilitating a more systematic development approach.

The pictures of the art gallery are all drawn by me using online tools. I carefully made the inside and outside parts, paying close attention to the lights, light switch, floor, and the way out. Using my creativity and computer skills, I worked hard to create a detailed and accurate representation of the gallery.

Parts I’m Proud of and Challenges Overcome:

  • Figuring out when the mouse touches the artwork:

I’m proud of this code because it lets the artwork respond when I click the mouse near it. This part specifically deals with showing the spiral artwork on the screen and checking if I’m clicking near it.

// Function to render the spiral
function renderSpiral(x, y, r) {
  push(); // Save the current drawing style settings and transformations
  translate(x + sposX, y); // Move the origin to the specified position
  image(frameIMG[1], -r / 1.8, -r / 1.8, r * 1.1, r * 1.1); // Display the image with the specified dimensions
  pop(); // Restore the previous drawing style settings and transformations

  // If mouse pressed
  if (mouseX < x + sposX + r/2 && // Check if the mouse's X position is within the specified range
      mouseX > x + sposX - r/2 && // Check if the mouse's X position is within the specified range
      mouseY < y + r/2 && // Check if the mouse's Y position is within the specified range
      mouseY > y - r/2 && // Check if the mouse's Y position is within the specified range
      mouse) { // Check if the mouse is pressed
      rect(0, 0, width, height); // Draw a rectangle covering the entire canvas
      for (var i = 0; i < spiral.length; i++) {
        push(); // Save the current drawing style settings and transformations
          spiral[i].render(width / 2.5, height / 3, r / 5); // Call the render function for the spiral object
        pop(); // Restore the previous drawing style settings and transformations
      }

 

This code checks if I’m clicking near the artwork by looking at where I click and comparing it with the artwork’s position and size. If I click close to the artwork, it shows more spirals on the screen, giving a cool effect that changes when I interact. Making this work well was a bit tough. I had to make sure the program could understand where I’m clicking and when it’s close to the artwork. Getting the right balance between showing the spirals and detecting my clicks accurately was important to make sure the interaction feels smooth and fun.

  • Switching the user perspective from scene-to-scene.

I’m proud of this code because it helps smoothly switch what I see in the program, going from one scene to another without any sudden jumps. This part, called ‘Screen,’ takes care of showing different pictures and managing the sounds in the background.

// Check if the screen is outside or inside
if (screen == 0) {
  push(); // Save the current drawing style settings and transformations
  // Display image outside screen
  image(sIMG[0], 0, 0, width, height);
  pop(); // Restore the previous drawing style settings and transformations

  // Display principal text
  push();
  translate(width / 2, height / 1.1);
  image(sIMG[2], -100, -15, 200, 30); // Display the image with specified dimensions and position
  pop();

  // Render Art Gallery
  agRender(); // Call function to render the art gallery
} else {
  push(); // Save the current drawing style settings and transformations
  // Display image inside the screen with dynamic x-position
  image(sIMG[1], sposX, 0, width * 2.5, height);
  pop(); // Restore the previous drawing style settings and transformations
}

 

The above codeIt makes sure that the sound keeps playing smoothly in the background while I move between scenes, making the whole experience more immersive and enjoyable.When I’m outside in the program (screen = 0), it shows the right picture and puts the main text in the correct place, making it look nice and organized. Making this work well was a bit tricky. I had to make sure that the images changed in a way that didn’t feel sudden or strange, and that the background sound kept playing without any interruptions. Finding the right balance between the pictures and the sound was important to make the whole experience feel smooth and natural.

  • I made sure to focus on small details. For instance, when you hover over the door, it creates a knocking sound, but it won’t keep making that sound repeatedly as long as you hover over it. The knocking will only happen again if you move your cursor out of the door and then back onto it. Also, I made sure that the initial music only plays the first time the door is opened, and it doesn’t play every time after that. This way, the music doesn’t overlap with itself. Also I added a sound effects for the light switch, moving to the right and left etc.

 

Areas for Improvement and Future Work:

Moving forward, there are several areas in my project that I recognize could be refined to enhance the overall user experience and elevate the sophistication of the artworks. One key aspect for improvement lies in enriching the interactive elements within the gallery. For instance, I plan to incorporate more diverse and dynamic interactions with the displayed artworks, enabling users to manipulate shapes, colors, and other visual elements to create a more engaging and immersive experience. By introducing additional interactive features like the ability for users to leave virtual notes or comments on specific art pieces.

Looking ahead, my future work on the project will revolve around integrating advanced generative art techniques to create more intricate and visually captivating artworks. I am particularly interested in exploring the application of complex algorithms and procedural generation methods to produce intricate patterns, textures, and visual effects, thereby adding depth and sophistication to the displayed artworks. I am also keen on delving into the use of machine learning algorithms to develop art that dynamically adapts and evolves in response to user interactions or external stimuli, thereby creating a highly immersive and personalized art experience.

 

Final Project:

 

References:

  • https://editor.p5js.org/mk7592/sketches/Q3_SYFuO6

Final Midterm Project: Street Crash: A Journey into the World of Retro Arcade Racing Games

Concept and Artistic Vision

I’ve always been captivated by the world of arcade games, especially those that revolve around cars and racing. My love for these games and my fascination with car races reached a peak this year when I watched the exhilarating “Gran Turismo” movie. When it came time to choose a topic for my midterm project, my passion for cars led me to one clear path: creating a car-related game.

Drawing from my experience in an “Introduction to Computer Science” course during my freshman year, where I had to create a game using Python’s Processing library, I decided to explore the world of programming languages more deeply. However, I quickly realized that working with JavaScript, especially in the context of p5.js, was a different ballgame altogether. My quest for inspiration led me to various online car racing codes, but none of them truly excited me. This realization prompted me to embark on a journey to create something truly unique and personal, drawing on my own ideas and designs. Below is an image of my old car game project using Python:

Coding Translation, Logic, and Planning

As I delved into writing the code for my car game, I drew on the knowledge I gained in my class. I leveraged concepts such as shapes, loops, functions, arrays, generative text, loading images, and audio, and even delved into computer vision using the webcam. The experience was a blend of creativity and coding, and I began by sketching my final draft to visualize each aspect of the game. Here’s a glimpse of my sketch:

To truly make my game unique, I decided to create my own designs for every element. I used a familiar tool, “Scratch,” which I had used during my high school years, to sketch my own cars, roads, titles, and more. Here are some of my sketches and how they look in the game:

With all the designs in place, I embedded them into the code and used arrays to store them efficiently. One feature I’m incredibly proud of is the ability to take a picture of the player and place it in the top left corner of the game. This concept was inspired by my experience with arcade games that would capture a photo of the player’s face and display it in the game, making it clear who was in control. This added an engaging and visually fascinating element to the game.

Gameplay and Features

The game starts with a set of basic instructions on how to play. Players use the arrow keys to control their car. The objective is to avoid collisions, as any contact with another object or car leads to a game over. Additionally, players must manage their fuel levels, as running out of fuel also results in a game over.

There are three exciting levels to the game, each offering a unique experience:

  1. Easy Mode: This is the regular mode where the game is a continuous loop, and it doesn’t end until the player loses.
  2. Hard Mode: In this mode, I’ve introduced a unique twist. The car moves backward, and the gameplay occurs in the dark, adding an extra layer of challenge and excitement.
  3. Race Mode: This is a newly added feature where players have a target to reach. It’s not an infinite or continuous loop; instead, the goal is to reach a score of 100 to win the game. It’s an engaging mode that introduces a winning target to the gameplay.

Here is my Final Project Embedded Sketch

Edit Link

Parts to be Proud Of and Overcoming Challenges

One element of my code that I’m particularly proud of is the intricate logic for bot generation, movement, and collision detection. The player’s car movement and its interactions with the street and gasoline collection also added a layer of excitement to the project. Here’s a snippet of the code that demonstrates this achievement:

//Cars
function bots() {
  // Set the initial position of the bot randomly within the canvas.
  this.pos = createVector(random(0, width), random(-size * 10, -size * 100));
  // Set the size of the bot (width and height).
  this.r = createVector(size * 5, size * 8.5);
  // Set the initial sprite for animation.
  this.sprite = 0;
  // Set a timer for sprite animation.
  this.time = 0;
  // Set a random color for the car.
  this.c = createVector(
    floor(random(0, 2) * 175),
    floor(random(0, 2) * 175),
    floor(random(0, 2) * 175)
  );

...

    // Check for collision with the player.
    if (
      p.pos.x - p.r.x / 2 < this.pos.x + this.r.x / 2 &&
      p.pos.x + p.r.x / 2 > this.pos.x - this.r.x / 2 &&
      p.pos.y - p.r.y / 2 < this.pos.y + this.r.y / 2 &&
      p.pos.y + p.r.y / 2 > this.pos.y - this.r.y / 2
    ) {
      // Play a sound when a collision occurs and set the screen to 2.

      songs[1].play();
      screen = 2;
    }
  };
}

...

// Gasoline object constructor function.
function Gas() {
  // Set the initial position of the gasoline randomly within the canvas.
  this.pos = createVector(random(0, width), random(-100, -2000));
  // Set the size of the gasoline (width and height).
  this.r = createVector(30, 40);

  // Render function for drawing the gasoline on the canvas.
  this.render = function () {
    push();
    translate(this.pos.x, this.pos.y);
    image(botsIMG[2], -this.r.x / 2, -this.r.y / 2, this.r.x, this.r.y);
    pop();
  };

  // Update function for updating the gasoline's position and behavior.
  this.update = function () {
    //Mode = 1
    if (mode == 1) {
      //Move
      this.pos.y -= vel / 100;
      if (this.pos.y + this.r.y / 2 < 0) {
        this.pos = createVector(
          random(0, width),
          random(width + 100, width + 2000)
        );
      }
    } else {
      //Mode = 0
      //Move
      this.pos.y += vel / 100;
    // Reset the gasoline's position if it goes off the screen vertically.
      if (this.pos.y - this.r.y / 2 > width) {
        this.pos = createVector(random(0, width), random(-100, -2000));
      }
    }

    // Check for collision with the player.
    if (
      p.pos.x - p.r.x / 2 < this.pos.x + this.r.x / 2 &&
      p.pos.x + p.r.x / 2 > this.pos.x - this.r.x / 2 &&
      p.pos.y - p.r.y / 2 < this.pos.y + this.r.y / 2 &&
      p.pos.y + p.r.y / 2 > this.pos.y - this.r.y / 2
    ) {
            // Play a sound, increase the gas, and reset the gasoline's position.

      songs[0].play();
      gas += 100;
      this.pos = createVector(random(0, width), random(-100, -2000));
    }

Another aspect that fills me with pride is the implementation of webcam computer vision. It elevates the gaming experience, making it more engaging and unique. Here’s a snippet of the code showcasing this feature:

// Declare global variables to hold video capture and image data
let video;
var img;

//Picture setup
function pictureSetup() {
  video = createCapture(VIDEO); // Create a video capture element and assign it to the 'video' variable

  video.size(size *40, size *40);
  video.hide();
}
// Capture a snapshot from the webcam and assign it to the 'img' variable
function picture() {
  //Set image webcam
  img = video.get();
}

Areas for Improvement and Future Work:

While I’m satisfied with the current state of my game, there are areas that I believe can be further enhanced. First, I’d like to experiment with colors and themes to make the game more visually engaging. Perhaps, as players progress through levels, the game’s theme could shift from daylight to nighttime, adding a dynamic element to the gameplay. Additionally, incorporating power-ups, introducing multiple levels, and improving the graphics could take the gaming experience to the next level.

References

Azimov, Bob. “LkvG5pT5g.” p5.js Web Editor, 2023, https://editor.p5js.org/azimovbob/sketches/LkvG5pT5g.

Carvalho, Kelly. “tDFpv6VLi.” p5.js Web Editor, 2023, https://editor.p5js.org/kellycarvalho2024/sketches/tDFpv6VLi.

Zohaib Naz. “CarRacing-p5.” GitHub, https://github.com/mzohaibnaz/CarRacing-p5.

 

Midterm Project: “BOOGIE BOX”

https://editor.p5js.org/Saiki/sketches/3jMTkdbOt

CONCEPT 

As mentioned earlier, the concept of my drum machine was inspired by playing around with online drum pads/drum machines on the internet. After discovering p5.Sound, I wanted to challenge myself and gain a better understanding of audio programming while also creating music. It seemed like a fun idea to pursue.

For the artistic vision of the project, I drew inspiration from the minimalist design often used by electronic music producers. The default Helvetica font is popular in this style, and it complemented the minimal CSS I added, making it easier to define the desired aesthetic.

 

CODING TRANSLATION

The biggest challenge in my code was understanding the p5.Sound library. In hindsight, I realized that using the tone.js library might have made my life easier, but that’s a lesson for another day. One of the main aspects of audio programming was figuring out how to convert the beat array into p5.Phrase and p5.Part processes. Think of p5.Phrase as individual tracks in an audio DAW and p5.Part as the master audio track that encompasses all the multiple drum beat tracks.

Once that was accomplished, the challenge shifted to finding a way to change the value of the array based on mouse clicks on the grid and obtaining the index of the clicked cell to modify the array. After that, my focus shifted to styling the canvas and adding fun functions like shuffle beat. I found that my previous experience with if-else statements and for loops in previous classes greatly aided me in defining these functions.

HIGHLIGHT

The part I am most proud of is figuring out how to change the index of the three drum arrays.

// determines whether a beat/note is played when mouse is clicked on the grid
function mousePressed() {
  // let rowClicked = floor(3*mouseY/height)
  let rowClicked = floor((3 * (mouseY - 50)) / (height - 135));

  // let indexClicked = floor (16*mouseX/width)
  let indexClicked = floor((16 * (mouseX - 50)) / (width - 100));

  if (rowClicked === 0) {
    console.log("1st row" + indexClicked);
    hhPat[indexClicked] = +!hhPat[indexClicked];
  }
  if (rowClicked === 1) {
    console.log("2nd row");
    cPat[indexClicked] = +!cPat[indexClicked];
  }
  if (rowClicked === 2) {
    console.log("3rd row");
    bPat[indexClicked] = +!bPat[indexClicked];
  }

  //   updates the matrix with shapes added/removed
  drawMatrix();
}

 

REFLECTION

In my next iteration of the code, I would like to add a button that clears the code. Additionally, I would like to include more diverse drum sounds that can be selected through a menu. It would be a cool function to be able to change the time signature of the beat setup from 4/4 to 3/4 or 7/8. There is ample room for customization, but for now, I am content with establishing the foundation of this project.