Midterm Project- Panda Math Stack- Elyazia Abbas

Concept: Learning Through Play with Panda Math Stack

For my midterm project, I chose to integrate a simple math operation game into my p5 sketch.  The Panda Math Stack transforms simple arithmetic into an interactive adventure where learning meets play. Designed with cheerful visuals and smooth animation, the game combines the task of a running panda collecting pancakes to make math practice fun and rewarding. Players solve addition problems by catching and stacking pancakes that match the correct answer. With every correct answer, the panda celebrates as cheerful sound effects and background music enhance the sense of accomplishment.

The game’s 30-second timer adds excitement, encouraging quick thinking while keeping learners engaged. Beyond its playful surface, Panda Math Stack promotes cognitive growth, especially for kids, through repetition and visual reinforcement, showing that learning can be both joyful and challenging in the right balance of design, music, and motion.

Explanation of The Main Components:

1. Use of Sounds
Sound plays an important emotional and feedback role in Panda Math Stack. The game includes three primary sound effects: background music (bgMusic), a stacking sound (boinkSound), and a game-over sound (gameOverSound). The looping background track establishes an upbeat rhythm that keeps players engaged throughout gameplay. The short “boink” effect provides instant positive feedback every time a pancake successfully lands on the tray, reinforcing the satisfaction of correct stacking. Finally, the game-over sound signals the end of a round, helping players transition between play sessions. Together, these sounds create a responsive and immersive auditory experience that strengthens player focus and motivation.

2. Use of Shapes
Shapes in this project are used to render most visual elements directly in p5.js without relying on external images. Circles and ellipses form pancakes, clouds, and decorative symbols, while rectangles and triangles are used for UI buttons and the grassy ground. By layering and coloring these basic shapes, the design achieves a friendly, cartoon-like appearance. The pancakes themselves use multiple overlapping ellipses in different brown tones, giving them dimension and warmth. This approach demonstrates how simple geometric forms can produce visually appealing and cohesive game elements that maintain a light, playful aesthetic.

3. Use of Images for Sprite Sheet
The panda character’s animation is handled using a sprite sheet (panda.png or panda2.png), divided into multiple frames organized in rows and columns. Each frame represents a different pose of the panda walking or idle. During gameplay, the code cycles through these frames (currentFrame) to simulate movement. This sprite-based animation technique allows smooth transitions without heavy computation, making the character appear lively and expressive as it moves and interacts with falling pancakes. The use of images here contrasts with the drawn shapes, introducing a visually rich and character-focused element that enhances personality and storytelling in the game.

 

4. On-Screen Text Evolution
Text evolves dynamically to communicate progress and emotions to the player. At the start, large pixel-style fonts announce the title and instructions, creating a retro arcade feel. During gameplay, text displays math problems, timers, and feedback messages that change in color and size depending on correctness ( for success, for errors). In the end screen and notebook view, typography shifts toward clarity and encouragement, summarizing scores or reviewing mistakes. This continuous adaptation of on-screen text keeps information readable while reinforcing the game’s educational purpose — transforming numbers and feedback into part of the visual storytelling.

5. Object-Oriented Programming in notebook.js and pancake.js
Both notebook.js and pancake.js apply object-oriented programming (OOP) principles to organize behavior and state efficiently. The Pancake class defines how each pancake behaves — from falling physics (update) to visual rendering (show) — encapsulating movement, collisions, and display logic into self-contained objects. Similarly, the Notebook class manages data storage and visualization of wrong answers, using methods like addWrong(), display(), and drawStack() to handle user progress and draw interactive visual feedback. This modular, class-based approach makes the code easier to scale, reuse, and maintain, as each object represents a distinct component of the game world with its own properties and responsibilities.

Code I am Proud of:

function checkAnswer() {
  if (!roundActive) return;

  if (stack.length === targetStack) {
    // Correct number of pancakes
    correctRounds++;
    message = `✅ Correct! (${num1} + ${num2} = ${targetStack})`;
    messageTimer = millis();
    roundActive = false;
    setTimeout(() => newMathProblem(), 1500);
    if (boinkSound) boinkSound.play();
  } else {
    // Incorrect answer
    message = "❌ Try Again!";
    messageTimer = millis();
    let question = `${num1} + ${num2}`;
    notebook.addWrong?.(question, targetStack, num1, num2);
    stack = [];
    pancakes = [];
  }
}

The checkAnswer() function is the core of the game’s math logic — it checks whether the number of pancakes the player stacked matches the correct answer to the math problem shown on screen. When the player presses “Check,” the function compares the length of the stack array (how many pancakes were caught) to targetStack (the sum of num1 + num2). If they’re equal, the player’s answer is correct — their score (correctRounds) increases, a success message and sound play, and a new math problem appears after a short delay. If the count is wrong, an error message is displayed, the pancakes reset, and the player can try again, making this function the key link between the math challenge and interactive gameplay.

Through Beta Testing:

Through beta testing, I received valuable feedback from my friends, that helped shape the final version of Panda Math Stack. They suggested transforming the concept into a math-based problem-solving game rather than just a stacking challenge, as this would make it more educational and purposeful.

 

They also recommended developing the notebook feature to track incorrect answers, allowing players to review and learn from their mistakes after each round. Incorporating these suggestions not only improved the gameplay experience but also strengthened the project’s learning component, making it both fun and pedagogically meaningful.

Embedded Sketch:

Future Improvements:

For future improvements, I plan to expand Panda Math Stack by adding more playable characters with unique animations and personalities to make the experience more engaging and customizable. I also aim to introduce multiple levels of difficulty, where each stage presents new visual themes and progressively challenging math problems. In addition to basic addition, future versions will include other arithmetic operations such as subtraction, multiplication, and division, allowing players to practice a wider range of skills. These updates will transform the game into a more dynamic and educational experience that adapts to different ages and learning levels.

Week 5 – Midterm Progress and Reading Response

Initial Concept:

The core concept of my project is to create a game where a panda chef stacks pancakes on its tray while pancakes fall from random positions in the sky . The gameplay is intentionally simple—pancakes fall from the sky, and the player moves the panda left and right to catch them before they hit the ground. I wanted the concept to be both whimsical and approachable, something that could appeal to all ages while still having the potential for engaging mechanics like timers, scoring, and fun visuals.

Design

The panda sprite sheet is animated using a frame-based system that cycles through images depending on movement, while background elements like clouds and grass are generated with simple loops and p5 shapes for efficiency. Pancakes are handled as objects using a dedicated class, which keeps the code modular and easy to expand. I also separated core functions—like drawing the welcome screen, updating the game state, and spawning pancakes—so the program remains organized and readable. This approach makes the design not only playful on-screen but also manageable under the hood.

Potential Struggles:

The most frightening part of the project was integrating sounds into the game. I know that audio is essential to making the experience immersive, but I was unsure about the technical steps required to implement it smoothly, especially since I had issues in the past when it comes to overlapping sounds and starting and stopping it accurately. Questions like when to trigger sounds, how to loop background music, or how to balance audio levels without them being distracting added to the challenge.

How I Plan to Tackle:

To reduce this risk, I turned to existing resources and examples, especially by watching tutorials and breakdowns on YouTube. Seeing other creators demonstrate how to load and trigger sounds in p5.js gave me both practical code snippets and creative inspiration. By learning step by step through videos, I am hoping to be able to gradually integrate audio without it feeling overwhelming.

Embedded Skecth:

Reading Response:

Computer vision i would say is different from how humans see. We naturally understand depth, context, and meaning, but computers just see a grid of pixels with no built-in knowledge or ability to infer and make connections like humans do. They need strict rules, so even small changes in lighting or background can throw a computer off.

To help computers “see” better, we often set up the environment in their favor, meaning that we cater to their capabilities. Simple techniques like frame differencing (spotting motion), background subtraction (comparing to an empty scene), and brightness thresholding (using contrast) go a long way. Artists and designers also use tricks like infrared light, reflective markers, or special camera lenses to make tracking more reliable.

What’s interesting in art is how this power of tracking plays out. Some projects use computer vision to make playful, interactive experiences where people’s bodies become the controller. Others use it to critique surveillance, showing how uncomfortable or invasive constant tracking can be. So, in interactive art, computer vision can both entertain and provoke — it depends on how it’s used.

Week 4- Loading Data, Displaying text Elyazia Abbas

Concept:

The goal of this sketch is to generate daily affirmations in the form of “I am …” statements. Each click on the canvas refreshed the draw function to bring a new affirmation assembled from a CSV file of positive words. The affirmations are placed on top of a sunset-inspired Perlin noise background using snippets of code from the decoding nature class.

Daily Doses of Positive are the Best Prevention for the Blues!

Code:

//here i am splitting these global variables to make each map to a spot or place in the phrase 
let SUBJECT = 0;
let QUALITY = 1;
let VERB = 2;
let ACTION = 3;
let PLACE = 4;




let strings = []; //this array holds all thre lines from the csv file 
let zoff = 0; // this is the third dimensionw e are using for the perlin noise


let sunsetPalettes = [ // this is the color pallette i use to make a sunset theme 
  ["#FF9E80", "#FF6E40", "#FF3D00", "#DD2C00"], 
  ["#FFB74D", "#FF8A65", "#F06292", "#BA68C8"], 
  ["#FFD180", "#FFAB40", "#FF7043", "#8E24AA"], 
  ["#FFE082", "#FFB74D", "#F48FB1", "#9575CD"]  
];

let currentPalette;

function preload(){ //preloading the csv file holding the words before setup
  strings = loadStrings("words.csv"); 
}

function setup() {//setting the canvas size and the font for the writing 
  createCanvas(600, 400);
  textFont("Georgia");
  textAlign(CENTER, CENTER);
  noLoop();
  pickPalette();
}

function draw() {
  background(255);
  noStroke();
  // this nested for loop will step between every 20 pixels +- horizontally and vertically
  for (let y = 0; y < height; y += 20) {
    for (let x = 0; x < width; x += 20) {
      let n = noise(x * 0.01, y * 0.01, zoff);// in that position we call the noise function and store th eresult in n 
      let c = color(random(currentPalette)); // get a  random sunset color
      c.setAlpha(90); // adding transparency using Alpha
      fill(c); // fill with the random color
      ellipse(x, y, n * 40, n * 40); //draw the ellipse here 
    }
  }
  zoff += 0.02; //editing the noise dimension after the draw

  
  
  //here we are randomly choosing a line to work with

  let line = "";
  do {
    line = strings[int(random(strings.length))]; // once we get a line that is not empty 
  } while (line.trim().length === 0); 

  let row = split(line, ','); // split the chosen line into n arrray of 5 tokens 

  let subject = row[SUBJECT];
  let quality = row[QUALITY];
  let verb = row[VERB];
  let action = row[ACTION];
  let place = row[PLACE];


  
  
  
  
  fill(30);
  textSize(32);
  text(subject + " " + quality, width / 2, height / 2 - 40); // here we put togehter the affirmation text 

  textSize(22);// here we put togehter the affirmation text 
  text(subject.replace("I am","I") + " " + verb + " to " + action + " in the " + place, width / 2, height / 2 + 20);


  textSize(14); // this si the footer that just asks sht euser to click 
  fill(60);
  text("Click anywhere on the screan for a new affirmation", width / 2, height - 30);
}

function mouseClicked() {
  pickPalette(); // picking. a new color pallette 
  redraw(); //draw again or call the drae function again 
}

function pickPalette() {
  currentPalette = random(sunsetPalettes); // pick random color to 
}

Embedded Skecth:

Conclusion: 

In the future, I’d like to refine grammar for more natural phrases. Maybe even make the array that holds the sentences longer so that we can get more complex phrases. I also want to let the Perlin noise flow continuously, and change colors for future sketches possibly.

 

Creative Reading Response:

  • What’s something (not mentioned in the reading) that drives you crazy and how could it be improved?

One thing that always drives me crazy is traditional TV remotes. There are so   many small buttons that all look the same, and most of them I never even touch. When I just want to change the volume or switch channels, I end up pressing the wrong thing and I’m stuck in some random settings menu. It feels like the design makes everything equally important, when really most people only use a few basic functions. If remotes had bigger, clearly marked buttons for the essentials and maybe hid the less-used ones, plus some simple feedback like a backlight, they’d be so much easier to use.

  • How can you apply some of the author’s principles of design to interactive media?

Norman’s design principles fit really naturally into interactive media because the whole field is about making technology feel intuitive and meaningful. Take affordances and signifiers, for example—these are really important when we design an interface. If a button actually looks like it can be clicked, or an arrow or sign shows you that you should swipe, users don’t have trouble guessing what to do next. In projects like games, apps, or interactive installations, these little cues make the experience smooth instead of frustrating. It’s basically about letting the design speak to the user so they can focus on enjoying the content rather than fighting with the controls. When people don’t have to think too hard about how to use something, they can actually connect with the creative side of the project.

 

 

Week 4 – OOP and Array

References and Inspiration

This project was inspired by sunsets, specifically their color transitions from yellow to orange and purple. These colors were used to design the gradient effect in the particle trails. The movement of the particles was influenced by the idea of natural flows and atmospheric motion. On the technical side, the code was built in p5.js using established techniques such as Perlin noise flow fields and particle systems, which were adapted to fit the chosen sunset theme.

Pink Sunset Color Scheme - Image Color Palettes - SchemeColor.com

Embedded Code

//this is our particle class responsible for each line of perlin noise
class Particle {
  constructor() {
    this.pos = createVector(random(width), random(height)); //randomly positioned
    this.vel = createVector(0, 0);
    this.acc = createVector(0, 0);
    this.maxSpeed = 2; //limit to how fast the particle moves
    this.prevPos = this.pos.copy(); //saves the previous/latest position of the trail 
  }

  update() {
    this.vel.add(this.acc); //alowing the vleocity to change based on the acceleration 
    this.vel.limit(this.maxSpeed); //limting the speed
    this.pos.add(this.vel); //change position based on the velocity 
    this.acc.mult(0); //reset accelration so it foes not increase infintely 
  }

  applyForce(force) {
    this.acc.add(force);
  }

  follow(vectors) {
    let x = floor(this.pos.x / scl); //getting the position of the particle x and y 
    let y = floor(this.pos.y / scl);
    let index = x + y * cols; //makingt he 2d grid into 1 d for indexing
    let force = vectors[index]; //access the vector at index
    this.applyForce(force); //apply the perlin noise
  }


  show() {
    // Sunset gradient colors
    let t = map(this.pos.y, 0, height, 0, 1);

    // Top → yellow, middle → orange/red, bottom → purple
    let topColor = color(255, 200, 50, 30);    // golden yellow
    let midColor = color(255, 100, 50, 30);    // deep orange/red
    let bottomColor = color(180, 60, 160, 30); // magenta/purple

    
    
    let c; // c is the chosen "sunset color"
    if (t < 0.5) { c = lerpColor(topColor, midColor, t * 2); } else { c = lerpColor(midColor, bottomColor, (t - 0.5) * 2); } stroke(c); strokeWeight(1.5); line(this.pos.x, this.pos.y, this.prevPos.x, this.prevPos.y); this.updatePrev(); } updatePrev() { //updating to make sure that the trail starts from the current positoin for the next/continued oaeticle this.prevPos.set(this.pos); } edges() { //limit particles ot stay within the frame if (this.pos.x > width) {
      this.pos.x = 0;
      this.updatePrev();
    }
    if (this.pos.x < 0) { this.pos.x = width; this.updatePrev(); } if (this.pos.y > height) {
      this.pos.y = 0;
      this.updatePrev();
    }
    if (this.pos.y < 0) {
      this.pos.y = height;
      this.updatePrev();
    }
  }
}

Concept:

In my p5.js sketch for this week, I mainly use a particle system where many small points move across the screen, each leaving a trail. Their movement is controlled by a flow field, which is simialr to an invisible grid of arrows that points the particles in the direction they should move in. The directions of these arrows are created with Perlin noise, which makes the movement look smooth and natural instead of random. Each particle updates its position based on the flow field and avoids the mouse when it gets too close, adding interactivity. To match the sunset theme, the particles are colored with a gradient that changes from yellow to orange to purple depending on their vertical position on the screen.

✨Sunset on the Beach ✨

Problems I Ran Into:

I had to review the previous Decoding Nature slides in order to refresh my memory on the concepts like flow field and perlin noise, and particles leaving a trail. So although it was not exactly a “problem” I had to readjust some parameters and play around with the values of certain parameters to remember what they were responsible for.

Embedded Skecth:

Reflection & Future Sketches:

I plan to incorporate more of the concepts taught in decoding nature to the weekly sketches.  I also want to focus on the creative elements and aspects of the sketches.Looking ahead, I want to experiment with making the particles react to more external inputs, such as sound or keyboard interaction, to create more dynamic sketches.

 

Reading Reflection:

When readings Crawfords piece I noticed that he mainly focused on three elements that make strong creativity: Listening, Thinking, and Speaking. By listening he means the system should be able to “capture” or “record”. Not only that but to accurately respond to certain triggers, whether it would be accurately through time, as in instant reaction, or accurately respond in an area specifically clicked on through the mouse.

After reading the piece, I have a few ideas for future sketches that will enhance the interactivity. For example, I want to start integrating all the Listening, Thinking, and Speaking elements cohesively so that the user does not have to be told that the piece is interactive- the piece speaks for itself. For instance, if my sketch has audio interaction or mouse interaction, I want the interactive element to shine through and to be the main focus rather than just an addition..

Creating Interactive Visuals with p5.js | Cratecode

 

Week 2 – Art with For and While Loops – Elyazia Abbas

Concept

In many houses here in the UAE and the Gulf region, the art displayed around homes often reflect culture and faith. For this weeks coding assignment I wanted to integrate the two pieces of art found in many Arab homes that I love the most. The first being bakhoor. The burning of bakhoor is a common tradition especially when welcoming guests, filling the space with oud and mysk fragrance. It involves using mabkhara, and adding a hot piece of coal in the middle. Then we add different kinds of oud sticks as well.

The second piece I wanted to depict in my sketch is the frames of Kiswah hung in many homes. The kiswah is basically the black silk cloth that covers the Kaaba in Mecca. Once its time to change the kiswah, ususally parts of it are sold.

My program depicts a mabkhara with a hoat coal in the middle, burning with smoke rising to the top of the screen. Behind the mabkhara is just an image I pasted of the Kiswah that says “بسم الله الرحمن الرحيم ” or “Bismillahir Rahmanir Raheem”

7+ Hundred Bukhoor Royalty-Free Images, Stock Photos & Pictures | ShutterstockDiscover 50 bakhoor ideas on this Pinterest board | incense, incense burner, oud perfume and more

Where does the Kaaba's Kiswa end up after its replacement on Arafat Day?

Code I am Proud of:

function updateSmoke() {
  noStroke();
  for (let i = smokeParticles.length - 1; i >= 0; i--) { 
//backward for loop where we decrememnt backwards, this is because we want to kill the oldest particles first then the newer ones 

    let p = smokeParticles[i]; 
//p is just there two know which particle we are currently working on 

    p.y -=5; //move particles up by decrementing y value 
    p.age+=1; //increase the age

    fill(200, 200, 200, p.alpha * (1 - p.age / p.life)); 
//coloring logic: the closer the age gets tot he life, this means that we want the particle to die off, so it would be a value/ over the same values , ultimately 1-1, which is zero, so the particle wont shpw anymore
   

 ellipse(p.x, p.y, p.size); 
//draw the smoke particle at the random x y position


    if (p.age > p.life) { //if age is greater than life, then splice the particle
      smokeParticles.splice(i, 1);
    }
  }
}

Sketch:

https://editor.p5js.org/ea2749/sketches/CBpMgmTff

Reflection and ideas for future work or improvements:

In the future I plan to hopefully start using more classes as it makes referencing so much easier and makes the process of editing certain parameters much simpler because everything is contained in a class. For future work I also plan to integrate sounds tot he skecth, for instance, which this sketch the sounds of burning wood would be very fitting!

 

Reading Reflection:

How are you planning to incorporate random elements into your work? Where do you feel is the optimum balance between total randomness and complete control?

I find it interesting how Casey Reas talks about order before he mentions randomness. Reas discusses how everything started with order and was associated with power in historic times. I specifically liked the part where, towards the end of the video, Reas showed art that depicted “parametrization” more than randomness, and he emphasized how much we can pay attention to detail, even when it looks underwhelming, when there is no randomness. But as Reas shows the pieces, we notice that there is randomness, though it does not overpower the overall structure of the art. This made me reflect on how we can balance structure/control and randomness. After looking at the last few pieces he showed, I found that the best balance is not when one overpowers the other, but when one complements or completes the other. With that in mind, I hope that for the next p5 sketches I work on, I focus more on how randomness can complement structure and parametrization rather than overpower it.

Random StructureRandomness & Chaos: An Overview of Why They Aren't the Same

 

 

Self Portrait- Elyazia Abbas

My Concept:

I wanted to create a self-portrait that depicted my features using colors that i like such as burgundy and pink, and also using the basic p5 shapes. I wanted to make a piece that felt warm and friendly, so I chose soft pink and peachy colors. The goal was to make something that looks like me but also shows my personality through the style and colors.

Most basic shapes were a good fit for the features of the portrait. For instance, basic ellipses of varying sizes were a good fit for the eyes when overlapped with different colours. Additionally for the cheeks, lips, chin, and face shape ellipses were suitable. Thin rectangles were good for the eyebrows as well.

As for the hair, I used a new shape that I used chatGPT to recommend which is the bezier shape. The bezier shape has 8 parameters, every two being an x and y pair. The first and last coordinate pairs control where the bezier starts and ends, and the middle two control the pull of the curve.

60 Pink Color Palette: Best Color Combinations with Codes - Eggradients.com

Code Snippet:

bezier(350, 160, 380, 150, 300, 220, 170, 280);
bezier(300, 160, 320, 180, 380, 220, 155, 310);
bezier(400, 160, 110, 170, 260, 380, 190, 480);
bezier(190, 480, 150, 520, 210, 580, 240, 650);
bezier(240, 650, 200, 690, 260, 740, 230, 810);
bezier(230, 810, 190, 850, 250, 890, 220, 950);
bezier(390, 180, 100, 160, 240, 400, 170, 500);
bezier(170, 500, 130, 540, 190, 600, 220, 670);
bezier(220, 670, 180, 710, 240, 760, 210, 830);
bezier(210, 830, 170, 870, 230, 910, 200, 970);
bezier(400, 160, 115, 170, 280, 370, 210, 470);
bezier(210, 470, 170, 510, 230, 570, 260, 640);
bezier(260, 640, 220, 680, 280, 730, 250, 800);
bezier(250, 800, 210, 840, 270, 880, 240, 940);
bezier(400, 140, 115, 150, 280, 370, 210, 470);
bezier(210, 470, 170, 510, 230, 570, 260, 640);
bezier(260, 640, 220, 680, 280, 730, 250, 800);
bezier(250, 800, 210, 840, 270, 880, 240, 940);
bezier(400, 130, 115, 140, 280, 370, 210, 470);
bezier(210, 470, 170, 510, 230, 570, 260, 640);
bezier(260, 640, 220, 680, 280, 730, 250, 800);
bezier(250, 800, 210, 840, 270, 880, 240, 940);
bezier(400, 120, 115, 130, 280, 370, 210, 470);
bezier(210, 470, 170, 510, 230, 570, 260, 640);
bezier(260, 640, 220, 680, 280, 730, 250, 800);
bezier(250, 800, 210, 840, 270, 880, 240, 940);
bezier(400, 110, 115, 120, 280, 370, 210, 470);
bezier(210, 470, 170, 510, 230, 570, 260, 640);
bezier(260, 640, 220, 680, 280, 730, 250, 800);
bezier(250, 800, 210, 840, 270, 880, 240, 940);

The bezier curve is a new shape that i worked with. It has has four points each of which has 2 coordinates, x and y. First, the Start point: Where the curve begins, End point: Where the curve ends, Two control points: These are like invisible magnets that “pull” the curve in different directions to create the bend.

So in the context of my self portrait the first point would be, the top of my head, the last point would be the tip of my hair, and the middle two points are where the curves occur due to the pulling in those spots.

Embedded Sketch:

Reflections and Future Improvements:

Through this assignment I learnt more about how shapes and colours could overlap in p5.js to make dimension and depth. I also learnt about the bezier shape and it added a very creative element to my sketch.

As for future improvements, I hope to be able to start making for-loops instead of manually repeating the same structures and editing the coordinates. This will not only save time, but it will also give me a less error prone program, and will create some kind of symmetry in my work.

For loop Syntax - GeeksforGeeks