Midterm Project – Kathak : The Art of Storytelling through Dance

CONCEPT:

My midterm project attempts to showcase the beauty of the Indian classical dance of Kathak. The project was ideated based on my experience pursuing the dance form for six years. Living in the UAE, I saw learning Kathak as a way to discover and connect to my cultural roots. The graceful yet swift movements and the jingling of the footbells in Kathak always leave me awestruck.

MAIN IDEA:

The project depicts an interactive book that provides insight into some of the fundamental movements of Kathak. Flipping through the pages, the user encounters interactive animations that add visual detail to the description provided. Below is the basic layout of each page that I had in mind as I began the project.

I wanted to depict the dance movements realistically and decided to adopt the concept of sprite sheets for this task. I began working on the project by collecting all relevant media including images for the spritesheets. It was challenging to create the sprite sheets as I had to ensure that the sizes of the images were all the same. Below are the sprite sheets used in the project.

CODING:

The project has been implemented using object-oriented programming. I have created a separate class for each page. This approach helped me organize the various functions involved. The main highlight of my project is the execution of spritesheets based on the example discussed in class.

Using sprite sheets, I was able to have a layer of interactivity on each page. The animations allow the user to view the demonstration of each dance movement at their own pace using the arrow keys. The functionality of the keys was created using the following code.

function keyPressed() {
  if (currentPage === 1) {
    if (keyCode === RIGHT_ARROW) {
      step1 = (step1 + 1) % sprites1.length; //Determines the frame number
      pages[currentPage].display(); // Redraws the page to update sprite animation
    } 
  }
  if (currentPage === 2) {
    if (keyCode === RIGHT_ARROW) {
      step2 = (step2 + 1) % sprites2.length;
      pages[currentPage].display(); 
    } 
    
  }
  if (currentPage === 3) {
    if (keyCode === LEFT_ARROW) {
      step3 = (step3 + 1) % sprites3.length;
      pages[currentPage].display();
    } 
  }
  if (currentPage === 3) {
    if (keyCode === RIGHT_ARROW) {
      step4 = (step4 + 1) % sprites4.length;
      pages[currentPage].display(); 
    } 
  }
}

PROJECT SKETCH:

Throughout the project, I paid attention to details such as the fonts and choice of images which helped make the project visually appealing. The background music is a classical composition involving the Tabla and Sitar, two instruments that form an integral part of any Kathak performance.

CHALLENGES:

The first major challenge that I faced was in trying to change the screen for each page. I overcame this challenge by creating separate classes for each page. Also, I had initially imagined an animation to depict the page flip, however due to my limited knowledge of the use of videos in p5, I was unable to implement it.

IMPROVEMENT:

An improvement that I would like to bring about in this project would be to include the corresponding sound of footbells for each  movement on the page about footwork. I tried implementing this idea but was not able to achieve the desired result.

Overall, I believe the project is simple yet unique and involves most of the concepts covered in class. It was a great learning experience which enabled me to tackle all concepts at once.

 

 

Midterm Project-Final Report:

Concept:

In one of Daniel’s-“The Funny Guy” videos he created something like a buzzing bee effect and I really liked his reaction to it so I thought of making a game that uses the idea of a buzzing bee. For my midterm project, I created a game that mimics the behavior of a bee.

I decided to create a game with a bee theme to immerse the user into the game by making them swerve falling blocks.  This is a simple game with 8 different levels that increase in difficulty as you progress. this is to prevent the user from getting bored early.

Design:

Initially, I thought of drawing the background for each level and then uploading the picture onto p5 but then that did not look so good.

But then this was not nice so I decided to go with a different design. I decided to just use a simple design and add a cool background with the bee theme. something like a honey comb. The rest of the design was mainly thoughts of how to structure the whole game into classes and what each class would end up doing.

Challenging Parts of this project:

The most challenging part of this project was preloading the different files that I imported into the project. This took me h0urs to figure out and a piece of advice is to always preload all the imports in one class and not various classes.

function preload(){
  //in this preload function we will load all the uploads we need before we even start the game. The folder name is always mentioned before the file name to help the compiler to know the location of the file we want to add.
  B1=loadImage("Background/B1.jpg");//these sets are for the background
  B2=loadImage("Background/B2.jpg");
  B3=loadImage("Background/B3.jpg");
  B4=loadImage("Background/B4.jpg");
  B5=loadImage("Background/B5.jpg");
  B6=loadImage("Background/B6.jpg");
  B7=loadImage("Background/B7.jpg");
  B8=loadImage("Background/B8.jpg");
  IB=loadImage("Background/IB.jpg");
  GB=loadImage("Background/GB.jpg");
  F1=loadFont("Fonts/Font1.ttf");//these sets are for the fonts 
  F2=loadFont("Fonts/Font2.ttf");
  S1=loadSound("Sounds/unplay.mp3");//these sets are for the sounds 
  S2=loadSound("Sounds/select.mp3");
  S3=loadSound("Sounds/hover.mp3");
  S4=loadSound("Sounds/hit.mp3");
  S5=loadSound("Sounds/play.mp3");
  P1=loadImage("Players/bee.png");// this one is to load the player png
}

Another recent challenge was the implementation of the sounds. I learnt something new with this challenge that to pass a variable by reference we do not need to create a variable in class as in “this.variablename” we just have to pass the variable and use it in the class by reference. In that case, the main variable is affected by what ever we do. This helps prevent creating duplicates of the same sound.

S4.play();//play the hit sound
       S1.play();//play the sound played when not playing. In this case I use S4 and not this,S4 because i want to access an object by reference to have control of the object that was initially playing in the game regardless of the objects location. creating this.S4 will create a copy and we would either start the sound or end up playing over another preexisting sound 
       S5.pause();//pause the in game sound... yeah the annoying one

Another tricky aspect was the collision and the deletion of the blocks after they cross the end of the canvas. In my case, each level has its own threshold that needs to be attained before the level is incremented. Silly me, I wanted to incorporate this in another class which wasted a lot of my time all for nothing. I realized that in as much as you want your work to look clean and separated you should know that you can utilize a class as much as you want and that there is nothing wrong with having a large class. Also about the collision, The “png” was resized to be a square so in order to get the collision effect, I had to use the “dist” function in my case to aid me to draw the circle that would be used to detect the intersection

  collision(){//this method is the one that checks if the play has collided with the falling blocks. It does this by going through the array and checking if the arrays height and width in accordance to the x and y coordinate intersect with the players circular dimensions.
    for(let i=0;i<this.lvl;i++){
      if(
        mouseX+10>this.blockArray[i].x&&mouseX-10<this.blockArray[i].x+this.blockArray[i].w&&
        mouseY+10>this.blockArray[i].y+5&&mouseY-10<this.blockArray[i].y+this.blockArray[i].h-5){//if there is an intersection,



deleteBlock(){//this method deletes blocks...used to delete blocks when they cross the height of the canvas.
    for(let i=0;i<(this.lvl);i++){
      if(this.blockArray[i].getY()>height){//if the top of the object for each object in the array has passed the height of the canvas
        this.score++;//increment the score by one.
        //for every level there is a score boundary that one is suppose to reach to move to the next level the if else code block below sets every level's boundary and increments the number of blocks for each level while increasing the level.
        if(this.lvl==1&&(this.score%3)==0){//if the score is 3, and we are on level one, increase the level and add one block object to the array
          this.blockArray[this.lvl]=new Block(this.lvl);//add the block
          this.blockArray[this.lvl].setBlock();//setting the new block that has been added
          this.blockArray[this.lvl].drawBlock();//draw the block that was jusr added
          this.lvl++//increment the lvl
        }
        else if(this.lvl==2&&(this.score%13)==0){//similar to above and below but each statement has its own treshold
          this.blockArray[this.lvl]=new Block(this.lvl);
          this.blockArray[this.lvl].setBlock();
          this.blockArray[this.lvl].drawBlock();
          this.lvl++
        }
        else if(this.lvl==3&&(this.score%23)==0){
          this.blockArray[this.lvl]=new Block(this.lvl);
          this.blockArray[this.lvl].setBlock();
          this.blockArray[this.lvl].drawBlock();
          this.lvl++
        }
        else if(this.lvl==4&&(this.score%33)==0){
          this.blockArray[this.lvl]=new Block(this.lvl);
          this.blockArray[this.lvl].setBlock();
          this.blockArray[this.lvl].drawBlock();
          this.lvl++
        }
        else if(this.lvl==5&&(this.score%45)==0){
          this.blockArray[this.lvl]=new Block(this.lvl);
          this.blockArray[this.lvl].setBlock();
          this.blockArray[this.lvl].drawBlock();
          this.lvl++
        }
        else if(this.lvl==6&&(this.score%60)==0){
          this.blockArray[this.lvl]=new Block(this.lvl);
          this.blockArray[this.lvl].setBlock();
          this.blockArray[this.lvl].drawBlock();
          this.lvl++
        }
        else if(this.lvl==7&&(this.score%80)==0){
          this.blockArray[this.lvl]=new Block(this.lvl);
          this.blockArray[this.lvl].setBlock();
          this.blockArray[this.lvl].drawBlock();
          this.lvl++
        }
        else if(this.lvl==8&&(this.score%100)==0){
          this.blockArray[this.lvl]=new Block(this.lvl);
          this.blockArray[this.lvl].setBlock();
          this.blockArray[this.lvl].drawBlock();
          this.lvl++
          if(this.lvl==9){//since level 8 is the last level, if, the level goes to level 9, decrement the level back to level 8.
            this.lvl--;//decrement the level
        }
         }
        delete this.blockArray[i];//if the block has passed the height, delete the block object,
        this.blockArray[i]=new Block(this.lvl);//create a new object and replace it with the old one that was deleted
        this.blockArray[i].setBlock();//set block to give it a new x coordinate and y coordinate and size etc. we donot draw the block because we need to draw it just once 
       }
   }
  }

Another major challenge was figuring out how the background moves which also took a lot of time to understand but it was cool after implementing it. However I realized that at the page_end and the page_front, the distinction is visible so next time I will look for Images that have this incorporated.

image(this.BG,0,this.y1,width,height);//create image at this.y1
   image(this.BG,0,this.y2,width,height);//create image at this.y2
   this.y1 -= this.scrollspeed;//decrement the speedd for both
   this.y2 -= this.scrollspeed;

   if (this.y1 < -height){//if the top of this background is at -height reset it to height
     this.y1 = height;
   }
   if (this.y2 < -height){//repeat the above for this y2 too
     this.y2 = height;
   }
 }

Project Snapshots:

Thoughts for the Future:

I hope that in future I can fix or get Backgrounds that do not have visible transitions. And also I hope to be able to incorporate motion detecting to allow the user to control the player by just moving their head.

Final work:

 

Midterm Project – Move to the beat

Concept:

For my midterm project, i wanted to create a record player with a character dancing to the music that it played, why? because if there is something that i am interested in, that would be music and i wanted to display my love for music in this code. The experience begins with a record in the middle with two buttons, one is “Play/Stop” and the other is “Restart”and a character on top of the record. When the “Play/Stop” button is pressed the record starts spinning and starts to play the mp3 file of a sample i created by the software “Logic” in the same time the character, lets call him “Joey” starts dancing to the beat. When the “Play/Stop” button is pressed again the mp3 file and the spinning record animation pauses. For the second button  “Restart” , this button restarts the experience to the beginning , the mp3 file is 54 seconds long .

As for research, i searched for spinning record codes on YouTube, i got some results and i liked the way it looked, it was close to the idea i had in my head. As for the simplicity of the code and my current skills, that is the best i could do, but i am very happy with way it turned out.

I began creating sketches on Adobe Illustrator, which led me to my final design.

Logic file:

Sprite sheet website:

https://www.spriters-resource.com/game_boy_gbc/dancedancerevolutiongbjpn/sheet/156290/

extra research :

https://www.easytechjunkie.com/what-is-a-record-player.htm

From class:

  • push() and Pop() : push() to save the current drawing style and pop() to restore the previous drawing style
  • mouseClicked() : to check if the mouse click is within the boundaries of the Play/Stop button and Restart button.
  • preLoad() : “loadSound” and “loadImage”  to check before calling the sound and image to load and run the code

 

My Sketch: “Move To The Beat”


My code :

// Declare a variable to store the button object
let btn;

let btnReplay;

// Variables to control rotation animation
let p = 0; // Flag to control animation playback (0: stopped, 1: playing)
let replay = 0; // Flag to control replay
let angle = 0; // Angle for rotating the shape

let imgs = []; // Array to store images

let mySound; // Sound object

function preload() {
  mySound = loadSound('data/music.mp3'); // Load the music file before running the code

  for (let i = 0; i <= 40; i++) {
    imgs[i] = loadImage('data/part' + i + '.png'); // Load a series of images before runninng the code
  }
}

function setup() {
  createCanvas(500, 500); // Create a 500x500 pixel canvas
  background("#408080"); // Set the background color to a shade of blue-green same as the background of the spritesheet character
  btn = new Button(250, 400, 120, 50, "Play/Stop"); // Create a button object for Play/Stop
  btnReplay = new Button(250, 460, 100, 50, "Restart"); // Create a button object for Restart
}

let f = 0; // Frame counter

function draw() {
  record(250, 250); // Call the record function to draw a rotating shape
  btn.show(); // Display the Play/Stop button
  btnReplay.show(); // Display the Restart button

  // Check if the animation is playing, and update the frame counter
  if (p == 1) {
    if (frameCount % 10 == 0) {
      f = (f + 1) % 40;
    }
  }

  image(imgs[f], 225, 60); // Display the current image frame

  // Check if the music is playing, and update the animation playback flag
  if (mySound.isPlaying()) {
    p = 1;
  } else {
    p = 0;
  }
}

// Function to draw a rotating shape
function record(x, y) {
  push();
  translate(x, y); // Translate the origin to the specified position

  // If p is set to 1, increment the angle for rotation
  if (p == 1) {
    angle += 0.1;
  }
  rotate(angle); // Rotate the subsequent shapes based on the angle

  fill(0); // Fill color for the central ellipse
  ellipse(0, 0, 200, 200); // Draw a central ellipse

  noFill();
  stroke(100); // Set stroke color
  strokeWeight(5); // Set stroke weight

  // Draw four arcs to create a pattern
  arc(0, 0, 150, 150, 0, PI / 4);
  arc(0, 0, 120, 120, PI / 4, PI / 2);
  arc(0, 0, 100, 100, PI, (3 * PI) / 2);
  arc(0, 0, 150, 150, PI / 2, PI);

  pop(); // Restore the previous drawing settings
}

// Function to respond to mouse clicks
function mouseClicked() {
  // Check if the mouse click is within the boundaries of the Play/Stop button
  if (
    mouseX > btn.x - btn.w / 2 &&
    mouseX < btn.x + btn.w / 2 &&
    mouseY > btn.y - btn.h / 2 &&
    mouseY < btn.y + btn.h / 2
  ) {
    // Toggle the value of p to start or stop the rotation animation
    if (p == 1) {
      mySound.pause(); // Pause the music
      p = 0; // Stop the animation
    } else {
      mySound.pause(); // Pause the music
      mySound.play(); // Start playing the music
      p = 1; // Start the animation
    }
  }

  // Check if the mouse click is within the boundaries of the Restart button
  if (
    mouseX > btnReplay.x - btnReplay.w / 2 &&
    mouseX < btnReplay.x + btnReplay.w / 2 &&
    mouseY > btnReplay.y - btnReplay.h / 2 &&
    mouseY < btnReplay.y + btnReplay.h / 2
  ) {
    mySound.stop(); // Stop the music
    mySound.play(); // Start playing the music
    p = 1; // Start the animation
  }
}
// Define a class called Button
class Button {
    // Constructor that initializes button position (x, y) and dimensions (w, h)
    constructor(x, y, w, h, text) {
        this.x = x; // X-coordinate of the button
        this.y = y; // Y-coordinate of the button
        this.w = w; // Width of the button
        this.h = h; // Height of the button
        this.text = text;   //text inside the button
    }

    // Method to display the button
    show() {
        // Save the current drawing style
        push();

        // Set the rectangle drawing mode to center
        rectMode(CENTER);

        // Set the fill color
        fill(200, 230, 150);

        // Check if the mouse is within the button's boundaries
        if (mouseX > this.x - this.w / 2 && mouseX < this.x + this.w / 2 && mouseY > this.y - this.h / 2 && mouseY < this.y + this.h / 2) {
            // If the mouse is inside, change the fill color to a darker shade
            fill(200, 180, 50);
        }

        // Draw a rectangle with rounded corners at the specified position and dimensions
        rect(this.x, this.y, this.w, this.h, 10);

        fill(255);
        textAlign(CENTER,CENTER);
        textSize(25);
        text(this.text,this.x,this.y);

        // Restore the previous drawing style
        pop();
    }
}

Part of my Code that I am proud of / difficulties:

That would be the variable p, getting it to be controlled with the mouseClicked function. Also variable p controls the animations. this was a journey of trial and error until i made it work. Another is fidgeting with the coordinates of the arc function and the use of increments to make the arcs rotate, i used the help of the reference sheet on the p5js website to figure out the rotation element and angles. That was difficult, sometimes they would just not work, i kept trying over and over again until everything worked cohesively.

This function is activated every time the button is clicked, it checks whether the mouse is on the play/stop button or on restart button  , also variable p decides if the music played or not :

 

// Function to respond to mouse clicks
function mouseClicked() {
  // Check if the mouse click is within the boundaries of the Play/Stop button
  if (
    mouseX > btn.x - btn.w / 2 &&
    mouseX < btn.x + btn.w / 2 &&
    mouseY > btn.y - btn.h / 2 &&
    mouseY < btn.y + btn.h / 2
  ) {
    // Toggle the value of p to start or stop the rotation animation
    if (p == 1) {
      mySound.pause(); // Pause the music
      p = 0; // Stop the animation
    } else {
      mySound.pause(); // Pause the music
      mySound.play(); // Start playing the music
      p = 1; // Start the animation
    }
  }

  // Check if the mouse click is within the boundaries of the Restart button
  if (
    mouseX > btnReplay.x - btnReplay.w / 2 &&
    mouseX < btnReplay.x + btnReplay.w / 2 &&
    mouseY > btnReplay.y - btnReplay.h / 2 &&
    mouseY < btnReplay.y + btnReplay.h / 2
  ) {
    mySound.stop(); // Stop the music
    mySound.play(); // Start playing the music
    p = 1; // Start the animation
  }

 

In this part variable p decides if the angle has to increase :

 

// Function to draw a rotating shape
function record(x, y) {
  push();
  translate(x, y); // Translate the origin to the specified position

  // If p is set to 1, increment the angle for rotation
  if (p == 1) {
    angle += 0.1;
  }
  rotate(angle); // Rotate the subsequent shapes based on the angle

  fill(0); // Fill color for the central ellipse
  ellipse(0, 0, 200, 200); // Draw a central ellipse

  noFill();
  stroke(100); // Set stroke color
  strokeWeight(5); // Set stroke weight

  // Draw four arcs to create a pattern
  arc(0, 0, 150, 150, 0, PI / 4);
  arc(0, 0, 120, 120, PI / 4, PI / 2);
  arc(0, 0, 100, 100, PI, (3 * PI) / 2);
  arc(0, 0, 150, 150, PI / 2, PI);

  pop(); // Restore the previous drawing settings
}

Finally, in this part of the code variable p decides if the animation(sprite sheet character) is good to start/run:

 

let f = 0; // Frame counter

function draw() {
  record(250, 250); // Call the record function to draw a rotating shape
  btn.show(); // Display the Play/Stop button
  btnReplay.show(); // Display the Restart button

  // Check if the animation is playing, and update the frame counter
  if (p == 1) {
    if (frameCount % 10 == 0) {
      f = (f + 1) % 40;
    }
  }

  image(imgs[f], 225, 60); // Display the current image frame

  // Check if the music is playing, and update the animation playback flag
  if (mySound.isPlaying()) {
    p = 1;
  } else {
    p = 0;
  }
}

 

Areas of improvement / future work:

I would like to in the future projects to create something more complex and a bit more creative, also bettering my skills in coding, thank you for viewing my project.

Link  to my code :

https://editor.p5js.org/mka413/sketches/zrBYeGRWy

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Midterm Project – ArtfulMotion: A Digital Canvas of Creativity

Link to edit

Images from Sketch

 

Concept

ArtfulMotion is an innovative fusion of interactive art creation and musical immersion, designed as a captivating digital canvas for users to unleash their creativity. Grounded in the p5.js framework, the program offers a dynamic platform where art and music coalesce seamlessly. A richly textured backdrop, comprising the fifth print from Casey Reas’s Tissue prints, sets the visual stage, creating an aesthetic foundation for users to craft their masterpieces. The harmonious integration of various audio tracks and intuitive music controls allows users to select a musical score that perfectly complements their artistic journey, cultivating a multi-sensory and immersive experience.

The project pushes the boundaries of interaction with the implementation of machine learning through ml5.js. Leveraging the handpose model, users can shape their art through real-time hand gestures, offering a tangible link between the digital canvas and the physical world. A diverse array of artistic modes empowers users to explore varied styles and tools, encouraging experimentation and artistic expression. The user-friendly interface facilitates smooth navigation through different sections, while responsive design ensures the project adapts flawlessly to different screen sizes and resolutions. This program aspires to inspire creativity, fostering an environment where art and music converge to create a captivating and enjoyable artistic experience.

 

Implementation

In developing this project, I adopted a systematic approach that involved several key steps. First, I conducted an initial assessment to distinguish between frames containing a hand and those without. Subsequently, I delved into verifying the accuracy of the model’s key points. To ensure that these points corresponded correctly to the hand’s landmarks, I employed green ellipses as visual indicators. During this process, I identified a mirroring issue, which arose from my attempt to mirror the webcam feed. To address this, I placed the drawing function for the points within the push() and pop() functions, effectively correcting the mirroring problem.

A pivotal element of my approach was the creation of a dedicated Point class, designed to render the model’s points onto the screen with precision. I seamlessly integrated this class into the existing sketch responsible for drawing the hand’s landmarks. I also fine-tuned the drawKeyPoint() function to generate points that were stored in an array, allowing for streamlined rendering on the canvas.

For the project’s second mode, I took a different artistic approach by implementing curveVertex() in the draw function of the Point class. This choice lent a unique aesthetic to this mode, differentiating it from the first. Furthermore, I embarked on the design of the program’s landing page and other sub-interfaces. These elements were connected through functions I defined in separate JavaScript files. The collective result of these steps was a visually engaging project, which not only translated logic into code but also integrated modularity, object-oriented programming, event-driven programming, and image handling.

[Sketch of planning phase]

Highlight of Code

 The draw() function plays a pivotal role in the code, as it manages the application’s state and navigation. It renders different pages, such as the menu, instructions, color selection, mode selection, and the art creation canvas, by utilizing a switch statement to determine the current state. It also incorporates a back button for easy navigation between pages, excluding the menu and art creation canvas. Additionally, the function is responsible for rendering music control buttons, allowing users to adjust the soundtrack as they create art. The code’s modularity and clear separation of rendering logic for distinct states contribute to improved code organization and maintenance.

function draw() {
  
  // determines which page to display
  switch (state) {
    case "menu":
      drawMenu();
      break;

    case "instructions":
      drawInstructions();
      break;
      
    case "select_colors":
      drawSelectColors();
      break;

    case "select_mode":
      drawSelectMode();
      break;
      
    case "create_art":
      drawArt();
      break;      
  }
  
  // adds back button if on any other page except menu and main sketch
  if (state != "menu" && state != "create_art") {
    drawBackButton();
  }
  
  // draws music control buttons
  drawMusicControls();
}

One of the primary technical challenges encountered in the project was related to resizing the video feed within the drawArt() function while preserving its original aspect ratio and ensuring it was correctly positioned. The challenge involved intricate mathematical calculations to determine the new dimensions and position for the scaled video feed. Additionally, it required addressing the mirroring of the feed to ensure that user interactions remained intuitive and natural. The process demanded rigorous testing and iterative adjustments to strike the right balance and achieve the desired outcome, ensuring that the video feed displayed in the intended location on the canvas while preserving its correct proportions.

function drawArt() {
  
  // scaling video to avoid distortion
  let aspectRatio = video_feed.height/video_feed.width;
  
  // mirroring feed from the webcam
  // -- beginning of transformation
  push();
  translate(width, 0);
  scale(-1, 1);
  if (drawing_flag) {
    loadKeyPoints();
    drawKeyPoints();
  }
  image(video_feed, width - ( width / videoScale ), 0,  
        width / videoScale , (width /videoScale) * aspectRatio);
  pop();
  // -- ending of transformation
  
  // print button
  updatePrintButton();
  
  // end button
  createEndButton();

}

 

Areas for Improvement

In future iterations of ArtfulMotion, key considerations include implementing real-time collaboration, providing an intuitive and secure environment for multiple users to collectively create art; incorporating interactive art elements, enabling users to seamlessly add animations, dynamic effects, or physics simulations, with a focus on user-friendliness and real-time previewing; and achieving music and art synchronization, allowing users to link music parameters to visual elements for a multimedia experience. Furthermore, the project could offer customizable brushes and visual effects, giving users the tools to add unique artistic touches to their creations through an accessible interface that balances customization and usability. These enhancements have the potential to expand the project’s creative horizons and provide users with a more versatile and engaging platform for artistic expression.

 

Mid-Term Project 3: What A Waste

 

https://editor.p5js.org/Minjae0216/sketches/hPYFgGfht

Concept of The Game:

“What A Waste” operates as an engaging educational game with a clear mission: to educate students about the crucial importance of proper waste segregation. It addresses a pressing issue in the United Arab Emirates (UAE) where recycling rates have fallen below 10%, primarily due to a lack of awareness and insufficient segregation infrastructure. The government’s sustainability goals for 2030 aim to divert 75% of waste from landfills, making proper waste segregation imperative. The game simulates real-life scenarios, such as students mistakenly placing non-recyclable items in recycling bins. Players must correctly sort recyclable items to prevent contamination in the recycling stream. By doing so, they learn the adverse consequences of unsorted waste, which not only hinder recycling but also increase the workload for recycling centers and waste management companies. “What A Waste” fosters a sense of responsibility and equips students with the knowledge and habits needed to contribute to recycling efforts, supporting the UAE’s sustainability goals and promoting a cleaner environment.

How the game works:

The game’s design incorporates a simple yet effective concept. Players click the start button, and trash items begin to fall from the screen. The challenge lies in catching and correctly placing plastic waste into the plastic recycling bin, earning 2 points for each correct placement. Catching the wrong trash, like dirty plastic plates or paper boxes, leads to a loss of life. This format tests players’ knowledge of proper recycling while making waste sorting and segregation engaging and interactive. The game’s mechanics align with its educational purpose, reinforcing the importance of correct waste management practices. It’s a game where entertainment meets education, allowing players to win by accumulating 15 points and, in turn, contributing to a more sustainable future.

Codes I am proud of:

class Basket {
  constructor() {
    this.x = width / 2; // Initialize the basket's x-position at the center of the canvas.
    this.y = height - 100; // Initialize the basket's y-position near the bottom of the canvas.
    this.width = 110; // Set the width of the basket.
    this.height = 110; // Set the height of the basket.
  }

  // Renders the basket on the canvas.
  display() {
    // Use the image() function to display the basket image at the specified position and dimensions.
    image(basketImage, this.x - this.width / 2, this.y - this.height / 2, this.width, this.height);
  }

  //control the horizontal movement of the basket using arrow keys.
  move() {
    if (keyIsDown(LEFT_ARROW) && this.x > this.width / 2) {
      this.x -= basketSpeed;
    }
    if (keyIsDown(RIGHT_ARROW) && this.x < width - this.width / 2) {
      this.x += basketSpeed;
    }
  }
}

/// objects that fall from the top of the screen in the game.
class FallingObject {
  constructor() {
    this.x = random(width); // Initialize a random horizontal position for the falling object.
    this.y = 0; // Set the initial vertical position at the top of the canvas.
    this.radius = random(50, 70); // Set the size (radius) of the falling object.
    this.speed = random(objectSpeedMin, objectSpeedMax); // Set the falling speed.
    this.image = random(trashImages); // Randomly select an image for the falling object
    
    // Check if the selected trash image is recyclable (true) or not (false).
    this.isRecyclable = this.image === trashImages[0] || this.image === trashImages[1] || this.image === trashImages[2]; // Check if the trash is recyclable
  }


  display() {
    // Use the image() function to display the object's image at its current position and size.
    image(this.image, this.x - this.radius / 5, this.y - this.radius / 5, this.radius, this.radius);
  }

  
 // updates the vertical position, causing the object to fall down the screen.
  fall() {
    this.y += this.speed;
  }

“FallingObject” is my favorite part of the code because it is the heart of the game’s dynamic and unpredictable nature. The FallingObject class is responsible for creating the diverse objects that rain down on the player. Its uncertainty lies in the use of randomization, ensuring that no two objects are alike in terms of position, size, and speed. This randomness adds an element of excitement and surprise to the game, making it more engaging for players.

What’s truly remarkable is how this part of my code logically manages the recyclability aspect. By checking and categorizing the objects as recyclable or not, it directly ties into the game’s core mechanics. Thus, this coding structure effectively integrates both fun and educational elements. Furthermore, the smooth movement of these falling objects enhances the gameplay’s fluidity, which is another reason I take pride in this code section. In essence, the FallingObject class is one of the standout features in my project.

Areas for Improvement:

During the development process, some challenges were encountered, such as refining the game’s difficulty curve and maintaining a balance between fun and education. I can implement adaptive difficulty levels that adjust based on the player’s performance for the next project. If a player consistently performs well, increase the challenge. If they struggle, offer easier levels or hints. Developing adaptive difficulty will make the game remain engaging for players of different skill levels. Moreover, the accessibility of the game, especially for younger players, was one of the considerations. Ensuring that the game is both fun and easy to understand for its target audience presented a significant design challenge. Despite these challenges, I believe my project successfully aligns entertainment with educational objectives, creating a promising tool for waste segregation awareness and fostering eco-conscious habits among students.

Midterm progress #3

At this point after completing my template and look of my code, it may be simple but i translated what i shared in my last progress report. I am very proud of my code as it was quite challenging for me since i had some difficulties. i added an animation of a circle with 4 arches rotating to give an illusion that the record is spinning. I inserted a button that would make the record spin when pressed on and also pause the record when clicked on again. In the final sketch there will be a sprite sheet dancing character which will be dancing to a sample of music i created using the software “Logic”.

Initial sketch:

i sketched out my design on adobe illustrator to see how i would like my sketch to look like, and luckily it turned out exactly how i wanted it to be.

My final design:

My code:

// Declare a variable to store the button object
let btn;

// Variables to control rotation animation
let r = 0;
let angle = 0;

function setup() {
  createCanvas(500, 500); // Create a 500x500 pixel canvas
  background("#408080"); // Set the background color to a shade of blue-green
  btn = new Button(250, 400, 120, 50); // Create a button object at the specified position and dimensions
}

function draw() {
  record(250, 250); // Call the record function to draw a rotating shape
  btn.show(); // Call the show method of the button object to display it
}

// Function to draw a rotating shape
function record(x, y) {
  push();
  translate(x, y); // Translate the origin to the specified position

  // If r is set to 1, increment the angle for rotation
  if (r == 1) {
    angle += 0.1;
  }
  rotate(angle); // Rotate the subsequent shapes based on the angle

  fill(0); // Fill color for the central ellipse
  ellipse(0, 0, 200, 200); // Draw a central ellipse

  noFill();
  stroke(100); // Set stroke color
  strokeWeight(5); // Set stroke weight

  // Draw four arcs to create a pattern
  arc(0, 0, 150, 150, 0, PI/4);
  arc(0, 0, 120, 120, PI/4, PI/2);
  arc(0, 0, 100, 100, PI, 3 * PI/2);
  arc(0, 0, 150, 150, PI/2, PI);

  pop(); // Restore the previous drawing settings
}

// Function to respond to mouse clicks
function mouseClicked() {
  // Check if the mouse click is within the boundaries of the button
  if (mouseX > btn.x - btn.w / 2 && mouseX < btn.x + btn.w / 2 && mouseY > btn.y - btn.h / 2 && mouseY < btn.y + btn.h / 2) {
    // Toggle the value of r to start or stop the rotation animation
    if (r == 1) {
      r = 0;
    } else {
      r = 1;
    }
  }
}

Button code:

// Define a class called Button
class Button {
    // Constructor that initializes button position (x, y) and dimensions (w, h)
    constructor(x, y, w, h) {
        this.x = x; // X-coordinate of the button
        this.y = y; // Y-coordinate of the button
        this.w = w; // Width of the button
        this.h = h; // Height of the button
    }

    // Method to display the button
    show() {
        // Save the current drawing style
        push();

        // Set the rectangle drawing mode to center
        rectMode(CENTER);

        // Set the fill color to yellow
        fill(255, 255, 0);

        // Check if the mouse is within the button's boundaries
        if (mouseX > this.x - this.w / 2 && mouseX < this.x + this.w / 2 && mouseY > this.y - this.h / 2 && mouseY < this.y + this.h / 2) {
            // If the mouse is inside, change the fill color to a darker shade of yellow
            fill(200, 200, 0);
        }

        // Draw a rectangle with rounded corners at the specified position and dimensions
        rect(this.x, this.y, this.w, this.h, 10);

        // Restore the previous drawing style
        pop();
    }
}

 

Rotation of the arcs/ also a part of the code that made me proud:

I used the push and pop method we took in class to achieve this motion, also to achieve the arc “animation” i used the reference “arc()” on p5js website

arc() :

arc(50, 55, 50, 50, 0, HALF_PI);
noFill();
arc(50, 55, 60, 60, HALF_PI, PI);
arc(50, 55, 70, 70, PI, PI + QUARTER_PI);
arc(50, 55, 80, 80, PI + QUARTER_PI, TWO_PI);
describe(
  'A shattered outline of an ellipse with a quarter of a white circle at the bottom-right.'
);
// Function to draw a rotating shape
function record(x, y) {
  push();
  translate(x, y); // Translate the origin to the specified position

  // If r is set to 1, increment the angle for rotation
  if (r == 1) {
    angle += 0.1;
  }
  rotate(angle); // Rotate the subsequent shapes based on the angle

  fill(0); // Fill color for the central ellipse
  ellipse(0, 0, 200, 200); // Draw a central ellipse

  noFill();
  stroke(100); // Set stroke color
  strokeWeight(5); // Set stroke weight

  // Draw four arcs to create a pattern
  arc(0, 0, 150, 150, 0, PI/4);
  arc(0, 0, 120, 120, PI/4, PI/2);
  arc(0, 0, 100, 100, PI, 3 * PI/2);
  arc(0, 0, 150, 150, PI/2, PI);

  pop(); // Restore the previous drawing settings
}

 

I also used the function for the button to start and pause the record mouseClicked() :

From p5js website:

let cnv, d, g;
function setup() {
  cnv = createCanvas(100, 100);
  cnv.mouseClicked(changeGray); // attach listener for
  // activity on canvas only
  d = 10;
  g = 100;
}

function draw() {
  background(g);
  ellipse(width / 2, height / 2, d, d);
}

// this function fires after the mouse has been
// clicked anywhere
function mouseClicked() {
  d = d + 10;
}

// this function fires after the mouse has been
// clicked on canvas
function changeGray() {
  g = random(0, 255);
}
// Function to respond to mouse clicks
function mouseClicked() {
  // Check if the mouse click is within the boundaries of the button
  if (mouseX > btn.x - btn.w / 2 && mouseX < btn.x + btn.w / 2 && mouseY > btn.y - btn.h / 2 && mouseY < btn.y + btn.h / 2) {
    // Toggle the value of r to start or stop the rotation animation
    if (r == 1) {
      r = 0;
    } else {
      r = 1;
    }

Button function:

I created a class called button then set the x,y,w,h coordinates, in addition to the shape of the rectangle, and the color changes for when mouse is clicked

// Define a class called Button
class Button {
    // Constructor that initializes button position (x, y) and dimensions (w, h)
    constructor(x, y, w, h) {
        this.x = x; // X-coordinate of the button
        this.y = y; // Y-coordinate of the button
        this.w = w; // Width of the button
        this.h = h; // Height of the button
    }

    // Method to display the button
    show() {
        // Save the current drawing style
        push();

        // Set the rectangle drawing mode to center
        rectMode(CENTER);

        // Set the fill color to yellow
        fill(255, 255, 0);

        // Check if the mouse is within the button's boundaries
        if (mouseX > this.x - this.w / 2 && mouseX < this.x + this.w / 2 && mouseY > this.y - this.h / 2 && mouseY < this.y + this.h / 2) {
            // If the mouse is inside, change the fill color to a darker shade of yellow
            fill(200, 200, 0);
        }

        // Draw a rectangle with rounded corners at the specified position and dimensions
        rect(this.x, this.y, this.w, this.h, 10);

        // Restore the previous drawing style
        pop();
    }
}

 

Any difficulties? :

Fidgeting with the coordinates of the arc() function was tricky for me, its the first time for me to try and use it as it was not quite working for me, also figuring out the push and pop method was confusing at first. In future projects i would want to do something more complex and better my skills coding wise. I will be posting my final sketch soon.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Midterm Project- Pop Frenzy

Concept:

I have developed a game using p5.js, in which random balls of varying speeds and diameters emerge across the screen. Our objective is to swiftly pop each ball before it diminishes and fades away. As each ball is lost, a ‘balllost’ counter increments, and after a certain count, the player loses. Many elements have been incorporated into the game to enhance the experience, including sound effects, the gradual reddening of the background as the ‘balllost’ count increases, and, of course, the shout button at the end of the game. While the game initially appears straightforward, it cultivates and refines various skills and abilities within the player. The foremost and pivotal skill that improves is the player’s tracking ability, accompanied by heightened reaction speed. This game effectively primes the player’s instincts and reflexes. Such games hold paramount importance and enjoy popularity in sports and activities demanding rapid reflexes, like F1 racing or high-speed shooting games. Ultimately, the game fosters cognitive development.

Moreover, in a study published by Mathew and his colleagues titled “Increasing Speed of Processing With Action Video Games,” it was indicated that action-packed games, similar to this one, exert a significant impact on cognitive functions and reaction time. The intense gameplay demands split-second decision-making, thereby enhancing problem-solving abilities. Additionally, the fast-paced nature of these games has been associated with improved visual processing and heightened attention, ultimately resulting in an augmentation of overall cognitive abilities. The rapid stimuli and dynamic environments present in such games lead to notable improvements in reaction speed. Players are required to process visual information at an accelerated rate, a skill that transfers well into scenarios requiring quick decisions(Dye, Matthew W G et al.). In essence, Pop Frenzy not only provides an engaging and entertaining experience but also serves as a tool for cognitive development and honing crucial skills vital in high-demanding activities.

In the gaming world, popular warm-up games like AimLab are played, which incorporates a series of games similar to Pop Frency, here’s an example of one game: Same goal as Pop Frency, but this game depends on time. Whereas, Pop Frenzy depends on balls lost.

Sketch:

Link to the game: https://editor.p5js.org/Nasar/sketches/FlE0f_9MH

Mid-Game Screen:

Game Lost Screen:

Coding Logic:

I started by creating the ball class and putting it into the sketch. Then, I adjusted the speed and size of each ball to make the game challenging but not too hard. After that, I added screens for the menu and when you lose. Instead of using complex loops, I used if-else statements to keep the code organized. Once I had the basic structure in place, I made the game more interactive. I added buttons and sounds and even made it so you hear a sound when you hover over a ball. As I kept working on the code, things started to make more sense in terms of what I should add in order to make it better.

I made some changes along the way to make sure the game was fun and easy to play. For example, I decided to have only one ball on the screen at a time. It might be cool to have more, but it would make the game too complicated. I also chose a screen size of 400 x 400. This way, the balls are close together, and players can easily swipe to them. If the screen was bigger, it would be harder to play. I used everything we learned in class – like making classes, using functions, adding sounds and pictures, and controlling their volume and size. I also put in things like text and buttons. As an extra touch, I added a particle class to make the game look cooler and more fun.

Here’s an initial sketch of my game:

Initially, I  envisioned a game where the black ball shouldn’t be popped or else the player loses. Later I didn’t include it though because of the increased difficulty.

Challenges I overcame:

Throughout the process, I encountered several challenges. In some cases, I had to shift my perspective on how I approached the code. In others, I found it necessary to completely rework certain elements. One particularly intricate part of the code, in which I faced multiple hurdles but ultimately achieved a satisfying outcome, was the implementation of the escape screen. This screen allows the player to pause the game using the escape button. The challenge arose from the interplay between the ‘loop’ and ‘noLoop’ functions. The ‘noLoop’ function halts the continuous execution of the ‘draw’ function. However, there were instances where the code would stop without displaying the escape screen. After conducting research online and studying examples from other coders, I discovered that by encapsulating the ‘loop’ and ‘noLoop’ functions within another function and placing it at the end of the entire code, I could ensure that the pause screen would be displayed before the code ceased to loop. Here’s the snippet to it:

//Built-in function
function keyPressed() {
  //check if escape is pressed, if game is continuing, it would pause, if balllost is 8 then we cant go pause screen
  if (keyCode === ESCAPE)
  {
    if(balllost==8)
      {
        gamePaused=false;
      }
    else
    {
    gamePaused = !gamePaused; // Toggle gamePaused variable
    }
    if (gamePaused) {
      noLoop(); // Pause the game by stopping the entire loop through draw
    } else {
      loop(); // Resume the game by enabling draw function to continue
    }
  }
}

Another issue I encountered involved the sound that should play only once when the cursor hovers over a button. However, I found that the sound was persistently repeating. I resolved this by introducing an additional flag variable. This flag becomes ‘true’ when the cursor is hovered over the button, allowing the sound to be executed only once before reverting to ‘false.’ This adjustment guarantees that the sound is not played endlessly.

if(mouseX>150 && mouseX<269 && mouseY> 260 && mouseY<298)
  {
  if (!menuButtonHovered) {
    buttonHover.play();
    menuButtonHovered = true;
  }
  fill('rgb(176,174,174)');
} else {
  fill('grey');
  menuButtonHovered = false;
}

Future Improvements:

While I put in my best effort to enhance the gaming experience by incorporating extra elements like hovering sounds, there are certainly opportunities for refinement in the code. The same outcome could be achieved with simpler and more streamlined coding techniques. As for the game itself, I could introduce a time element where, as a ball is popped, the time increases. The objective could be to prevent the timer from reaching zero.

I also envision the possibility of incorporating various difficulty levels such as easy, medium, and hard. With increasing difficulty, the speed at which the balls diminish could escalate. Additionally, multiple ball objects could potentially be in play simultaneously.

Lastly, I’ve noticed a slight delay when the balls are popped. Despite my efforts to minimize it and have the sound play immediately, there remains a small delay. This aspect is certainly something that could be refined in future iterations.

Citation:

Dye, Matthew W G et al. “Increasing Speed of Processing With Action Video Games.” Current directions in psychological science vol. 18,6 (2009): 321-326. doi:10.1111/j.1467-8721.2009.01660.x

reading response:Computer Vision for Artists and Designers: Pedagogic Tools and Techniques for Novice Programmers

This is one of my favorite readings so far and I have divided my reflections into bullet points as it was how I noted them down while reading the text :).

In the passage we read, we explored computer vision, a technology that allows machines to comprehend and engage with the visual world. This topic is intriguing due to its practical applications.

  1. Object Detection and Tracking:
    • An interesting aspect is how computer vision can identify people or objects in videos. It does this by comparing what it observes with an image of the background. When something stands out significantly from the background, it’s recognized as important. This capability is valuable, although it can be sensitive to variations in lighting.
    • Another fascinating aspect is the use of brightness to locate objects. Think about it like this: if something is significantly darker or lighter than its surroundings, computer vision can easily spot it.
    • Furthermore, there’s a straightforward method for monitoring an object in a video. It’s akin to pinpointing the brightest or darkest spot and keeping it in focus. This can serve various purposes.
  2. Basic Interactions and Their Function:
    • Computer vision isn’t solely about object recognition; it can also facilitate interactivity. For instance, there are interesting ways to interact with video games using body movements. These are like games where you see yourself in the virtual world, like a mirror.
  3. Computer Vision in Creative Tools:
    • Individuals are incorporating computer vision into tools for generating art, games, and more. This is captivating because it extends beyond web applications and is utilized in various imaginative ways.
  4. A Case Study: LimboTime:
    • We examined LimboTime, a game where computer vision tracks your actions. You can engage in a limbo contest with it. This demonstrates that anyone, even those who are new to the field, can craft enjoyable and interactive experiences using computer vision.

Midterm Project Progress 2: I’m Not/Too Bored

Progress update:

I have been trying to make the player move and engage with the NPC and show the engaging dioloage allowing them to choose certain option that gets saved to show a final result at the end.

 

Next step:

Add BGM and sound affect

As well as display the questions and the final results.

https://editor.p5js.org/mariamalkhoori/full/L-i2O01PV

Midterm Progress Report #2 Drum Machine

The progress on the midterm so far has been quite significant. I have realized that understanding and utilizing the p5.sound library is more challenging than I initially thought. The language of audio, with terms related to sample rate and frequency, took me some time to grasp, and I’m still unsure if I fully understand it. At this point, I have created the layout for the drum machine, which is interactive and responds to user clicks. I have included three sections for hi-hat, clap, and bass samples in the “drums” p5.part using the addPhrase method. I tried adding more samples, but for some reason, the audio keeps getting distorted on my browser. I looked it up online, and it seems to be a common issue with p5.js on the Chrome browser, so I am attributing it to that for now. I might test it with a different browser later but for now I am happy with having three rows of drum beats.

Currently, I have two versions of my project to display. One version has a background canvas, while the other version uses individual PNG files of the drum parts instead of circles to give visual cue as to which specific drum phrase is triggered. I made 2 functions: drawMatrix() and canvasPressed() for updating the grid on the canvas for when users deselect and add a 16th note phrase to the drum loop.

Press space to hear the beat.(open the sketch link)

https://editor.p5js.org/Saiki/full/m6MkI9vMD

Drum Icon Version (you can de-select/add beats in this version)

https://editor.p5js.org/Saiki/sketches/Mtr3z9iJ8

I have encountered some difficulties when implementing OOP (Object-Oriented Programming) into my code. I attempted to use a class called “Pattern” to create different drum phrases. However, when working with p5.part and p5.phrase, it did not function properly.

Additionally, I still need to add a start screen to my drum machine. I have implemented a BPM (Beats Per Minute) control slider, which I will provide captions for to make its purpose more obvious. For now, I am content that my project is functional, and I will now focus on refining the details to create a cohesive experience.