Week 10: Reading Response

First Article: Physical Computing’s Greatest Hits (and misses)

After reading this article, I find myself reflecting on its crucial aspects. The author discusses various themes in physical computing and highlights recurring project ideas. One point raised is the versatility of these themes, allowing for originality despite their frequent use. I can see evidence of this in the examples provided, such as the theremin-like instruments and gloves used for musical interaction. However, I wonder if the author’s enthusiasm for these themes might overshadow potential limitations or drawbacks. While the projects are indeed versatile and popular, are there certain constraints or challenges that aren’t fully addressed? Additionally, the emphasis on creativity and variation might suggest a bias towards celebrating the potential of physical computing without thoroughly examining its limitations or pitfalls.

Reading this has not drastically changed my beliefs, but it has prompted me to consider the balance between creativity and practicality in project development. Are there instances where prioritizing creativity might hinder the functionality or effectiveness of a physical computing project Furthermore, the discussion of themes like “Remote Hugs” and “Meditation Helpers” raises questions about the effectiveness of technology in facilitating emotional experiences. Can machines truly simulate or enhance human connection and emotional well-being, or do they risk oversimplifying complex human experiences?

Overall, I think while the reading offers valuable insights into the world of physical computing, sententiously it also prompts critical thinking about the intersection of technology and human interaction.

Second Article: Making Interactive Art: Set the Stage, Then Shut Up and Listen

After reading this article, I find the author’s perspective on interactive art thought-provoking. They emphasize the importance of not interpreting one’s own work in the context of interactive art. Instead, the author suggests setting the stage for interaction and then allowing the audience to interpret and respond to the artwork in their own way. I agree with the notion that providing interpretation alongside interactive art can limit the viewer’s experience by dictating how they should perceive and engage with the piece. By allowing space for individual interpretation, the artwork becomes a platform for dialogue between the artist and the audience.

The comparison made between planning interactive artwork and directing actors resonates with me. Just as a director guides actors without imposing specific interpretations, an artist should create opportunities for interaction without prescribing meaning. This approach allows for more authentic and varied responses from the audience. However, I wonder about the balance between providing context for interaction and leaving room for interpretation. How can an artist effectively guide the audience’s engagement without imposing their own biases or intentions?

Furthermore, the idea of interactive artwork as a performance highlights the dynamic nature of the audience’s role in completing the work. How can artists create environments or stimuli that encourage meaningful interaction and exploration without overshadowing the audience’s agency?Overall, I feel the article challenges traditional notions of authorship and interpretation in art, encouraging a more open and collaborative approach to creating interactive experiences.

Week 10: Dual Hybrid Sensor Lighting System

Concept: For this project, I need to use both digital and analog sensors along with indicators like LEDs to get creative. After thinking about different ideas, I realized my inspiration is:  I’ve always wanted to upgrade my Marvel’s Moon Knight action figure. Just like in the comics, I want his face and symbol on his chest to light up red when it’s dark, giving a warning to criminals. I also want some background lighting, like thunder effects. So, I thought of using some cool LEDs and sensors to recreate this scene. To achieve this, I’ll be using a photocell as the analog sensor and a push button as the digital sensor.

Materials I used:
1. Arduino Uno Board
2. Breadboard
3. Two Leds (Red and Green)
4. Three 220 Ohm Resistors
5. Push Button
6. Photo-resistor (Light Sensor)
7. Jumper Wires

So the final circuit include all of these items, as well as my Moon Knight Action Figure.

Implemented Code with comments:

int led = 11; // LED pin connected to an analog sensor
int buttonPin = 2; // Button pin, using pin 2 for example
int buttonState = 0; // Variable for reading the push button status
int secondLed = 12; // Second LED pin, using pin 12 for example
bool blinking = false; // State to control the blinking

void setup() {
  Serial.begin(9600); // Starts the serial communication
  pinMode(led, OUTPUT); // Sets the led as an output
  pinMode(buttonPin, INPUT_PULLUP); // Initialize the push button pin as an input with an internal pull-up resistor
  pinMode(secondLed, OUTPUT); // Sets the second led as an output
}

void loop() {
  int sensorValue = analogRead(A2); // Read the value from the analog sensor
  Serial.println(sensorValue); // Print the value to the serial monitor
  analogWrite(led, map(sensorValue, 0, 1023, 255, 0)); // Write the inverted analog value to the LED
  
  int currentButtonState = digitalRead(buttonPin); // Read the current state of the push button

  // Check if button state has changed from high to low (button press)
  if (currentButtonState != buttonState && currentButtonState == LOW) {
    blinking = !blinking; // Toggle blinking state
  }
  buttonState = currentButtonState; // Update the buttonState
  
  // If the button was pressed, start blinking
  if (blinking) {
    digitalWrite(secondLed, HIGH); // Turn on second LED
    delay(250); // Wait for 250ms
    digitalWrite(secondLed, LOW); // Turn off second LED
    delay(250); // Wait for 250ms
  } else {
    // Turn off second LED when sensor value reaches 200 or more
    if (sensorValue >= 200) {
      digitalWrite(led, LOW); // Turn off LED
    } else {
      digitalWrite(led, HIGH); // Turn on LED
    }
  }
  
}

Video Demonstation:

Images:

Figure 1.1: Closer View of the Circuit during Night time

Figure 1.2: Complete View of the Circuit, Including with Action Figure. (Night Time)

Figure 1.3: Top Angle View of the circuit during the Day time.

Sketch: Circuit Schematics

How circuit works:

LEDs and Resistors: There are two LEDs, a green and a red one. Each LED is connected to a digital pin on the Arduino (green to pin 11 and red to pin 12) through a resistor. The resistors limit the current to the LEDs to prevent them from burning out due to excessive current. The longer leg (anode) of the LEDs is connected to the resistor, and the other side of the resistor is connected to the Arduino pins. The shorter leg (cathode) of the LEDs is connected to the ground (GND) on the Arduino to complete the circuit.

PushButton:
The pushbutton has one side connected to 5V and the other side to both the ground (through a resistor) and to digital pin 2 of the Arduino. The resistor is a pull-down resistor that ensures the pin is at a known low signal when the button is not pressed. When the button is pressed, it connects the pin directly to 5V, giving a high signal. The internal pull-up resistor on the Arduino pin is activated in the code (INPUT_PULLUP), which means the pin is normally high, and pressing the button brings it to low. Moreover an analog sensor is connected to the analog pin A2 on the Arduino.

  • For the Green LED:  When the Arduino runs, it reads the value from the analog sensor connected to A2. This value is a measure of voltage that changes with the sensor’s readings. The Arduino then converts this reading to a corresponding brightness level for the green LED using analogWrite(), which uses pulse-width modulation (PWM) to simulate varying levels of brightness by quickly turning the LED on and off.
  • For the Red LED: The Arduino continuously reads the state of the pushbutton. When the button is detected as pressed (the signal on pin 2 goes from high to low due to the INPUT_PULLUP mode), it changes the blinking variable’s state. When blinking is true, the program  likely causes the red LED to turn on and off at certain intervals, simulating a blinking effect.

    Schematic Diagram Explanation:  Ultimately, the LEDs are represented by the symbols labeled ‘D1 GREEN’ and ‘D2 RED’. The resistors, labeled ‘R1’ and ‘R2’, are in series with the LEDs and connected to the digital pins on the Arduino symbol ‘U1’. The Arduino is central to the schematic and is labeled ‘U1’. All components are connected to it. It is shown with connections to power (5V and GND), the digital pins, and the analog pins. Hence the current flows from the 5V pin through the pushbutton when it is closed, and through the LEDs when they are enabled by the Arduino. Lastly this manages the flow by turning the pins to HIGH (5V) or LOW (0V) states and reading the voltage level from the analog sensor to determine the sensor’s readings.

Challenges and Reflection:
1) Connections of Jumper Wires: Connecting the wires to the action figure was a challenge because plastic tape doesn’t conduct electricity well. I had to ensure the ends of the jumper wires stayed firmly connected to the anode and cathode ends of the red LED without any loose connections. After some effort, I managed to secure the ends firmly with three to four pieces of tape.

2)  Push Button: The push button I used had a tendency to bounce (it has a loose connection with the bread board), causing unintended multiple presses. To solve this, first I implemented a delay in the code and they fixed the button with the help of screwdriver.

3) Photo-resistor Sensitivity and Range: The response of the photoresistor varied depending on the ambient light conditions. If the light levels fell outside the photo-resistor’s sensitive range, the LED wouldn’t respond as expected. To address this, initially I had to dim all the lights to make the room dark and I changed the range a bit limiting the sensor value from 400 to 250 then adjusted the code to accommodate my room lighting conditions, ensuring consistent LED performance.

Future Improvements:
a) I have an improvement in mind for the blinking green light in the background. Currently, it blinks manually with a delay of 250 ms. However, I want to integrate it with the background system so that when there’s a high pitch, the green background LED lights up brighter, and otherwise, it remains constantly low.

Overall, despite the hours spent on connections and coding, I’m satisfied with the outcome of the project. It feels completely worthwhile to recreate the scene of my favorite superhero from the comics! In the future, I’d love to enhance it further with more LEDs and sensors.

 

Week 9: Laptop Charging Switch

Concept: While browsing YouTube for ideas, I noticed that my friend’s old laptop lacks an indicator light for charging. Every time she plugs it in, she’s uncertain if it’s actually charging. So, for my Week 9 project, I’ve decided to help her by using an Arduino to create a simple input/output switch. This will make it easy for her to tell whether her laptop is charging.

Fig 1: This is laptop we will be using for making a switch.


Fig 2: A closer look of connection between laptop and charging cable.

So the ultimate goal of this project is to incorporate an LED that will serve as an indicator when the charging plug is connected to the laptop.

Process: First, I built a basic circuit that uses an Arduino to power a breadboard. I included a red led in the circuit to serve as an indicator of whether the circuit is complete.  So the red wire is supplying power (+5V from the Arduino) to the longer, positive leg of the LED. The shorter, negative leg of the LED is connected to one end of a resistor. The other end of the resistor is connected back to the Arduino board via the black wire, which completes the circuit to GND (ground), allowing the current to flow. When the circuit is closed, a red led turns on. If the circuit is interrupted or there is a break between two wires, then the red led turns off.

Fig 3: An Open or Broken Circuit, The Red Led is in “Off” state.

Fig 4: A Closed Circuit, The LED is in “ON” State.

Components I used:

1) Three jumper wires
2) A Red LED
3)  Arduino
4) A Resistor
5) A USB Cable for connecting Laptop with Arduino
6) A Breadboard
7) A Tape

Video Demonstration:

Link to this video.

Challenges and Future Improvements:

1) Working on this basic circuit board isn’t very challenging for me. However, I find it a bit tricky to attach the wires with tape in such a way that they make a complete connection when the charging cable is plugged in. Getting the angle right for this connection is the challenging part.

2) So for future improvements, I’m considering to use a sensor that can automatically detect whether the cable is connected or disconnected, and do so wirelessly. This would enhance the system’s functionality and user convenience.

Reading 8A Week

Norman,“Emotion & Design: Attractive things work better”

Having read Norman’s thoughts on how emotions impact design, I’m struck by how feelings influence our thinking and actions. He suggests that feeling positive boosts creativity, while feeling negative sharpens our focus. I can relate to this from my own experiences: feeling happy often leads to creative ideas, while stress can make me intensely focused. Norman highlights the importance of designing products with people’s emotions in mind, which makes sense to me. It’s crucial to create things that not only work well but also make users feel good.

I understand Normal is majorly biased  towards attractiveness, he mentioned “…attractive things work better” (Pg 1). However, while Norman also argues that good design should balance aesthetics and functionality, I wonder if focusing too much on looks could sacrifice practicality. Sure, attractive designs can enhance the user experience, but can they make up for flaws in how something works? Norman’s ideas make me think about what really matters in design. Shouldn’t the main goal be to create products that are both visually appealing and easy to use? Norman also makes me wonder how designers can use emotions to make products more engaging. How can they tap into our feelings to make us enjoy using things more? Overall, Norman’s ideas have made me rethink how emotions, looks, and usability all play a part in making products that people love to use.

Her Code Got Humans on the Moon

Learning about Margaret Hamilton’s groundbreaking work in software engineering for the Apollo space program was incredibly inspiring. Her journey from being a young mother with a math degree to leading a team that created vital software for the Apollo missions shows her determination and talent. It’s amazing how she managed to balance being a mom and a pioneering programmer, challenging stereotypes and showing the importance of diversity in STEM fields.

One moment that really stood out to me was when Hamilton’s daughter accidentally caused an error in the MIT command module simulator. Even though Hamilton suggested adding code to prevent such mistakes, NASA dismissed her idea, thinking astronauts wouldn’t make errors. This shows the need to consider all possibilities and have safeguards, especially in important situations. It also makes me think about the consequences of ignoring suggestions based on assumptions about people never making mistakes.

Overall Hamilton’s story makes me reflect on the ongoing gender gaps in STEM fields and why it’s important to recognize women’s contributions to technology. It reminds me of the need to promote inclusivity and diversity, especially in fields where they’ve been overlooked. Moreover it also highlights the importance of rigorous testing and error prevention in complex systems, also reminding us to stay humble and prepared for anything.

Upon conclusion, as I witnessed Hamilton’s work, I’m left questioning: What more can be done to encourage women to pursue careers in STEM fields and break through gender barriers? How can we ensure that all voices are heard and respected in technological advancements and innovations?

Midterm Project – Musical Brick Breaker Game

Concept: Recreating one of my favorite childhood game – The Musical Brick Breaker Game

So I chose to have the concept for this project, is to create a musical soothing classical Brick Breaker game using the p5.js library. The game involves controlling a paddle to bounce a ball and break bricks at the top of the screen. The user interacts with the game by moving the paddle horizontally using the left and right arrow keys. The goal is to break all the bricks without letting the ball fall below the paddle. The game provides feedback through visual cues such as the ball bouncing off objects, disappearing bricks, and a scoring system. Moreover, sound effects further enhance the user experience.

Designing the Code: Elaborating important areas

1) Ball Behavior: Within the Ball class, I define the behavior of the ball. This includes its movement across the screen, detection of collisions with other objects (such as the paddle and bricks), and rendering on the canvas. This encapsulation allows for clear organization and modularization of ball-related functionality.

2) Paddle Control: The Paddle class covers the movement and display of the paddle. It handles user input from the keyboard to move the paddle horizontally across the screen, ensuring precise control for the player.

3) Brick Management: Each brick in the game is represented by the Brick class. This class manages the display of individual bricks on the canvas and provides methods for their creation, rendering, and removal during gameplay.

4) User Interaction: The mousePressed function responds to user input by triggering specific game actions, such as starting or resetting the game. This function enhances the interactivity of the game and provides a seamless user experience.

Additional functions, such as createBricks and resetGame, are responsible for initializing game elements (such as bricks) and resetting the game state, respectively. These functions streamline the codebase and improve readability by encapsulating repetitive tasks.

By breaking down the code into these specific components, I ensured a clear and organized structure, facilitating easier maintenance.

Minimizing Risk: Code I’m proud of,

display() {
    fill(255, 0, 0);
    ellipse(this.x, this.y, this.radius * 2);
  }
  
  checkCollision() {
    if (this.x > paddle.x && this.x < paddle.x + paddle.width && this.y + this.radius > paddle.y) {
      this.speedY *= -1;
      paddleHitSound.play();
    }
  }
  
  bounce() {
    this.speedY *= -1;
    ballHitSound.play();
  }
  
  hits(brick) {
    let closestX = constrain(this.x, brick.x, brick.x + brick.width);
    let closestY = constrain(this.y, brick.y, brick.y + brick.height);
    let distance = dist(this.x, this.y, closestX, closestY);
    return distance < this.radius;
  }
}

One major complex aspect of the project is implementing collision detection between the ball and other game objects (paddle, bricks, walls). Ensuring accurate collision detection is crucial for the game’s mechanics and overall user experience. To minimize the risk of errors in this area, I employed two  strategies:

1) Collision Detection Algorithm: Implementing this collision detection algorithms is essential because, for example in the Ball class, I used a method called hits(brick) to check if the ball collided with a brick. This method calculates the distance between the ball and the brick’s edges to determine if a collision occurred. Moreover, By using the dist() function in favor with appropriate ball coordinates, I ensured this accurate collision detection is perfectly executed.

2) Testing with Edge Cases: To validate the accuracy of this collision detection algorithm, I conducted repeated testing with various edge cases. This includes scenarios where the ball collides with the corners of bricks or with multiple objects simultaneously. By systematically testing these cases and analyzing the results, I came to conclusion that the collision detection behaves as expected under different conditions.

Prototypes (wire-frame notes) :

Here’s the Game:

Features & Game Mechanics:
– Game initializes with a start screen displaying “Musical Brick Breaker Game” and along with three themes to choose.
– The player controls the paddle using the left and right arrow keys.
– The ball bounces off the paddle, walls, and bricks.
– When the ball hits a brick, it disappears, and the player earns points.
– If the ball falls below the paddle, the game ends.
– Once game ends, it displays either “Game Over” or “Congrats” message along with the score and a feature for click to return Home.
– Clicking on the canvas after the game ends resets the game, allowing the player to replay.

Additional Features:
– Sound effects are played when the ball hits the paddle and when it hits a brick.
– The player earns points for each brick broken, and the score is displayed on the screen.
– Background music plays throughout the game to enhance the gaming experience, moreover different sound tracks were added to different themes selected.

Here’s a snapshot taken during the game-play of all the themes:


Complete Code Snippet (With Comments):

// Variables to hold background images for different themes
let backgroundImage;
let marvelBackgroundImage;
let dcBackgroundImage;

// Game objects
let ball;
let paddle;
let bricks = [];

// Brick layout parameters
let brickRowCount = 3;
let brickColumnCount = 5;
let brickWidth = 80;
let brickHeight = 20;
let brickPadding = 10;
let brickOffsetTop = 50;
let brickOffsetLeft = 30;

// Game score
let score = 0;

// Sound effects and background music variables
let ballHitSound;
let paddleHitSound;
let backgroundMusic;
let marvelSoundtrack;
let dcSoundtrack;

// Game state management variables
let gameState = 'home'; // Possible states: 'home', 'playing', 'gameOver'
let theme = 'default'; // Current theme: 'default', 'marvel', 'dc'
let gameStarted = false; // Flag to indicate if the game has started

// Preload function to load images and sounds before the game starts
function preload() {
  backgroundImage = loadImage('background_image.jpg');
  marvelBackgroundImage = loadImage('marvel_background.jpg');
  dcBackgroundImage = loadImage('dc_background.jpg');
  ballHitSound = loadSound('ball_hit.mp3');
  paddleHitSound = loadSound('paddle_hit.mp3');
  backgroundMusic = loadSound('background_music.mp3');
  marvelSoundtrack = loadSound('marvel_soundtrack.mp3');
  dcSoundtrack = loadSound('dc_soundtrack.mp3');
}

// Setup function to initialize game elements
function setup() {
  createCanvas(500, 400); // Set canvas size
  paddle = new Paddle(); // Initialize paddle
  ball = new Ball(); // Initialize ball
  createBricks(); // Create brick layout
}

// Main draw loop to render the game frame by frame
function draw() {
  background(255); // Clear the canvas with a white background
  // Apply background image based on the current theme with opacity
  if (theme === 'default') {
    tint(255, 127); // Half opacity
    image(backgroundImage, 0, 0, width, height);
  } else if (theme === 'marvel') {
    tint(255, 127); // Half opacity
    image(marvelBackgroundImage, 0, 0, width, height);
  } else if (theme === 'dc') {
    tint(255, 127); // Half opacity
    image(dcBackgroundImage, 0, 0, width, height);
  }
  noTint(); // Reset tint effect for drawing other elements without opacity

  // Display the appropriate screen based on the game state
  if (gameState === 'home') {
    displayHomeScreen(); // Display home screen with theme options
  } else if (gameState === 'playing') {
    playGame(); // Main game logic
  } else if (gameState === 'gameOver') {
    displayGameOver(); // Display game over screen
  }
}

// Handler for mouse press events to interact with the game
function mousePressed() {
  if (gameState === 'home') {
    checkButtonPressed(); // Check if any theme button was pressed
  } else if (gameState === 'gameOver') {
    resetGame(); // Reset game to initial state
    gameState = 'home'; // Return to home screen
  } else {
    if (!gameStarted) {
      gameStarted = true; // Start the game
    }
  }
}

// Function to check if a theme button was pressed and change the game state accordingly
function checkButtonPressed() {
  const buttonWidth = 200;
  const buttonHeight = 50;
  const startY = height / 2 - 75;
  const gap = 60;

  // Detect button press based on mouse coordinates
  if (mouseX >= width / 2 - buttonWidth / 2 && mouseX <= width / 2 + buttonWidth / 2) {
    stopAllMusic(); // Stop any currently playing music
    // Check which button was pressed and update the theme and game state
    if (mouseY >= startY && mouseY <= startY + buttonHeight) {
      theme = 'default';
      gameState = 'playing';
      backgroundMusic.loop(); // Start playing default background music
    } else if (mouseY >= startY + gap && mouseY <= startY + gap + buttonHeight) {
      theme = 'marvel';
      gameState = 'playing';
      marvelSoundtrack.loop(); // Start playing Marvel soundtrack
    } else if (mouseY >= startY + 2 * gap && mouseY <= startY + 2 * gap + buttonHeight) {
      theme = 'dc';
      gameState = 'playing';
      dcSoundtrack.loop(); // Start playing DC soundtrack
    }
  }
}

// Function to display the home screen with game title and theme selection buttons
function displayHomeScreen() {
  fill('black');
  textSize(32);
  textAlign(CENTER, CENTER);
  textFont('Georgia');
  text("Musical Brick Breaker Game", width / 2, 100); // Game title
  
  // Display theme selection buttons
  textSize(20);
  const buttonWidth = 200;
  const buttonHeight = 50;
  const startY = height / 2 - 75;
  const gap = 60;

  // Default theme button
  stroke(0);
  strokeWeight(2);
  fill(255, 0, 0, 200); // Semi-transparent red
  rect(width / 2 - buttonWidth / 2, startY, buttonWidth, buttonHeight, 20); // Rounded corners
  fill(0); // Black text
  noStroke();
  text("Default", width / 2, startY + 28);

  // Marvel theme button
  fill(0, 0, 255, 200); // Semi-transparent blue
  stroke(0);
  strokeWeight(2);
  rect(width / 2 - buttonWidth / 2, startY + gap, buttonWidth, buttonHeight, 20); // Rounded corners
  fill(255); // White text
  noStroke();
  text("Marvel Universe", width / 2, startY + gap + 25);

  // DC theme button
  fill(255, 255, 0, 200); // Semi-transparent yellow
  stroke(0);
  strokeWeight(2);
  rect(width / 2 - buttonWidth / 2, startY + 2 * gap, buttonWidth, buttonHeight, 20); // Rounded corners
  fill(0); // Black text
  noStroke();
  text("DC Universe", width / 2, startY + 2 * gap + 28);
}

// Function to handle gameplay logic
function playGame() {
  ball.update();
  ball.checkCollision();
  ball.display();
  
  paddle.display();
  paddle.update();
  
  // Loop through and display all bricks, check for collisions
  for (let i = bricks.length - 1; i >= 0; i--) {
    bricks[i].display();
    if (ball.hits(bricks[i])) {
      ball.bounce();
      bricks.splice(i, 1); // Remove hit brick from array
      score += 10; // Increase score
    }
  }
  
  // Check if game is over (no bricks left)
  if (bricks.length === 0) {
    gameState = 'gameOver';
  }
  
  // Display current score
  fill('rgb(2,46,82)');
  textSize(20);
  textAlign(LEFT);
  text("Score: " + score, 20, 30);
}

// Function to display game over screen
function displayGameOver() {
  fill('rgb(24,21,21)');
  textSize(32);
  textAlign(CENTER, CENTER);
  if (score >= 150) {
   text("Congratss! Score: " + score, width / 2, height / 2+50);
   textSize(18);
   text("You mastered this universe, click to win others", width / 2, height / 2 + 90);
  }
  else{
  text("Game Over!! Score: " + score, width / 2, height / 2+50);
  textSize(20);
  text("Click to return Home", width / 2, height / 2 + 90);
  }
}

// Function to reset the game to initial state
function resetGame() {
  gameStarted = false;
  score = 0;
  ball.reset();
  createBricks(); // Re-initialize bricks
}

// Function to stop all music tracks
function stopAllMusic() {
  backgroundMusic.stop();
  marvelSoundtrack.stop();
  dcSoundtrack.stop();
}

// Function to initialize bricks based on row and column counts
function createBricks() {
  bricks = [];
  for (let c = 0; c < brickColumnCount; c++) {
    for (let r = 0; r < brickRowCount; r++) {
      let brickX = c * (brickWidth + brickPadding) + brickOffsetLeft;
      let brickY = r * (brickHeight + brickPadding) + brickOffsetTop;
      bricks.push(new Brick(brickX, brickY));
    }
  }
}
// Class representing the ball object
class Ball {
  constructor() {
    this.radius = 10; // Radius of the ball
    this.reset(); // Reset ball position and speed
  }

  // Reset ball position and speed
  reset() {
    this.x = width / 2; // Initial x position at the center of the canvas
    this.y = paddle.y - 10; // Initial y position above the paddle
    this.speedX = 5; // Initial speed along the x-axis
    this.speedY = -5; // Initial speed along the y-axis
  }

  // Update ball position
  update() {
    this.x += this.speedX; // Update x position
    this.y += this.speedY; // Update y position
    // Bounce off the sides of the canvas
    if (this.x < this.radius || this.x > width - this.radius) {
      this.speedX *= -1; // Reverse speed along the x-axis
    }
    // Bounce off the top of the canvas
    if (this.y < this.radius) {
      this.speedY *= -1; // Reverse speed along the y-axis
    } 
    // Check if ball falls below the canvas
    else if (this.y > height - this.radius) {
      gameState = 'gameOver'; // Set game state to 'gameOver'
    }
  }

  // Check collision with the paddle
  checkCollision() {
    // Check if ball collides with paddle
    if (this.x > paddle.x && this.x < paddle.x + paddle.width && this.y + this.radius > paddle.y) {
      this.speedY *= -1; // Reverse speed along the y-axis
      paddleHitSound.play(); // Play paddle hit sound
    }
  }

  // Display the ball
  display() {
    fill(255, 0, 0); // Red fill color
    stroke(0); // Black thin outline
    strokeWeight(1); // Thin outline weight
    ellipse(this.x, this.y, this.radius * 2); // Draw ball as circle
  }

  // Bounce the ball (reverse speed along y-axis)
  bounce() {
    this.speedY *= -1; // Reverse speed along the y-axis
    ballHitSound.play(); // Play ball hit sound
  }

  // Check if ball hits a brick
  hits(brick) {
    // Calculate distance between ball center and brick center
    let distX = Math.abs(this.x - brick.x - brick.width / 2);
    let distY = Math.abs(this.y - brick.y - brick.height / 2);
    // Check if distance is less than combined radii of ball and brick
    if (distX > (brick.width / 2 + this.radius) || distY > (brick.height / 2 + this.radius)) {
      return false; // No collision
    }
    return true; // Collision detected
  }
}

// Class representing the paddle object
class Paddle {
  constructor() {
    this.width = 100; // Width of the paddle
    this.height = 20; // Height of the paddle
    this.x = (width - this.width) / 2; // Initial x position at the center of the canvas
    this.y = height - 35; // Initial y position near the bottom of the canvas
    this.speed = 10; // Speed of the paddle
  }

  // Display the paddle
  display() {
    fill(0, 0, 255); // Blue fill color
    stroke(0); // Black thin outline
    strokeWeight(1); // Thin outline weight
    rect(this.x, this.y, this.width, this.height); // Draw paddle as rectangle
  }

  // Update paddle position based on keyboard input
  update() {
    // Move paddle left
    if (keyIsDown(LEFT_ARROW) && this.x > 0) {
      this.x -= this.speed;
    } 
    // Move paddle right
    else if (keyIsDown(RIGHT_ARROW) && this.x < width - this.width) {
      this.x += this.speed;
    }
  }
}

// Class representing a brick object
class Brick {
  constructor(x, y) {
    this.x = x; // x position of the brick
    this.y = y; // y position of the brick
    this.width = brickWidth; // Width of the brick
    this.height = brickHeight; // Height of the brick
  }

  // Display the brick
  display() {
    fill(200, 50, 50); // Red fill color
    stroke(0); // Black thin outline
    strokeWeight(1); // Thin outline weight
    rect(this.x, this.y, this.width, this.height); // Draw brick as rectangle
  }
}


 


Reflection: Ideas added to this Final Midterm

1) User Experience: I’ve incorporated different themes so that the user won’t be limited to play in one environment. In addition, all the three themes have their separate backgrounds and soundtracks.

2) End Card Message:  I’ve implemented a conditional statement to display “Congrats” message if the user wins and “Game Over” message if the player losses along with the displaying scores on a side.

3) Immersive Audio Design: To ensure that the soundtrack and the paddle hit sound doesn’t overlap, I first reduced the volume (decibels) of the soundtrack using Audacity software before importing it into P5.js.

4) Areas I can Improve Further: Firstly, I aim to introduce difficulty levels to enhance the game’s complexity. Currently, players have three themes to choose from. By adding difficulty levels, players would face nine different variations (3 themes x 3 levels), offering a certain complex gaming experience.

Secondly, I plan to implement full-screen gameplay. However, attempting to switch to full-screen mode has caused disruptions in the game’s initial phase. It has affected the ball’s movement, needed adjustments in the number of bricks, required an increase in paddle size, and led to a decline in background quality. Additionally, P5.js has been slow in loading and executing the code, posing further challenges.

Conclusion: I’m very much satisfied with the output of my game, I never imagined I can implement complex algorithms and great features of P5.js programming: OOPS and Functions to recreate my favorite childhood game. For further learning experience, I’ll try to incorporate the changes I mentioned earlier.

Reference: Used Tools/ Software
1) Dall-E for background images : https://openai.com/dall-e-3
2) Audacity Software for sound editing. https://www.audacityteam.org
3) Coding Garder (Youtube Channel): https://www.youtube.com/watch?v=3GLirU3SkDM

Reading Response: Computer Vision for Artists and Designers, #Week5

Reflection: After reading the article on “Computer Vision for Artists and Designers,” I find myself intrigued by the democratization of computer vision technologies and their increasing integration into various artistic and interactive mediums. The examples provided, such as Myron Krueger’s Videoplace and Rafael Lozano-Hemmer’s Standards and Double Standards, showcase the diverse ways in which computer vision is being employed to create immersive and thought-provoking experiences. However, I couldn’t help but wonder: What are the potential ethical implications of surveillance-themed artworks like Suicide Box by the Bureau of Inverse Technology? While these projects aim to shed light on societal issues, do they also raise questions about privacy and consent?

Regarding the author’s bias, it’s evident that they have a deep appreciation for the potential of computer vision in the arts. The article primarily focuses on the positive impact of these technologies, emphasizing their accessibility to novice programmers and the creative possibilities they offer. However, I would have appreciated a more nuanced discussion: What are the potential drawbacks or limitations of using computer vision in art? How might artists address ethical concerns such as privacy and consent when incorporating surveillance-themed elements into their work? Additionally, I’m left wondering about the broader societal implications: What are the implications of widespread adoption of these technologies, particularly in terms of surveillance and data privacy? Overall, the reading has prompted me to critically examine the intersection of technology and art, and consider the ethical implications of incorporating advanced technologies like computer vision into creative practices.

Week 5 & 6: (Midterm Progress) Image Processing and Sounds

Concept: Recreating one of my favorite childhood game – The Brick Breaker

So I chose to have the concept for this project, is to create a musical soothing classical Brick Breaker game using the p5.js library. The game involves controlling a paddle to bounce a ball and break bricks at the top of the screen. The user interacts with the game by moving the paddle horizontally using the left and right arrow keys. The goal is to break all the bricks without letting the ball fall below the paddle. The game provides feedback through visual cues such as the ball bouncing off objects, disappearing bricks, and a scoring system. Moreover, sound effects further enhance the user experience.

Designing the Code: Elaborating important areas

1) Ball Behavior: Within the Ball class, I define the behavior of the ball. This includes its movement across the screen, detection of collisions with other objects (such as the paddle and bricks), and rendering on the canvas. This encapsulation allows for clear organization and modularization of ball-related functionality.

2) Paddle Control: The Paddle class covers the movement and display of the paddle. It handles user input from the keyboard to move the paddle horizontally across the screen, ensuring precise control for the player.

3) Brick Management: Each brick in the game is represented by the Brick class. This class manages the display of individual bricks on the canvas and provides methods for their creation, rendering, and removal during gameplay.

4) User Interaction: The mousePressed function responds to user input by triggering specific game actions, such as starting or resetting the game. This function enhances the interactivity of the game and provides a seamless user experience.

Additional functions, such as createBricks and resetGame, are responsible for initializing game elements (such as bricks) and resetting the game state, respectively. These functions streamline the codebase and improve readability by encapsulating repetitive tasks.

By breaking down the code into these specific components, I ensure a clear and organized structure, facilitating easier maintenance and future development of the game for the midterm project.

Minimizing Risk: Code I’m proud of,

display() {
    fill(255, 0, 0);
    ellipse(this.x, this.y, this.radius * 2);
  }
  
  checkCollision() {
    if (this.x > paddle.x && this.x < paddle.x + paddle.width && this.y + this.radius > paddle.y) {
      this.speedY *= -1;
      paddleHitSound.play();
    }
  }
  
  bounce() {
    this.speedY *= -1;
    ballHitSound.play();
  }
  
  hits(brick) {
    let closestX = constrain(this.x, brick.x, brick.x + brick.width);
    let closestY = constrain(this.y, brick.y, brick.y + brick.height);
    let distance = dist(this.x, this.y, closestX, closestY);
    return distance < this.radius;
  }
}

One major complex aspect of the project is implementing collision detection between the ball and other game objects (paddle, bricks, walls). Ensuring accurate collision detection is crucial for the game’s mechanics and overall user experience. To minimize the risk of errors in this area, I employed two  strategies:

1) Collision Detection Algorithm: Implementing this collision detection algorithms is essential because, for example in the Ball class, I used a method called hits(brick) to check if the ball collided with a brick. This method calculates the distance between the ball and the brick’s edges to determine if a collision occurred. Moreover, By using the dist() function in favor with appropriate ball coordinates, I ensured this accurate collision detection is perfectly executed.

2) Testing with Edge Cases: To validate the accuracy of this collision detection algorithm, I conducted repeated testing with various edge cases. This includes scenarios where the ball collides with the corners of bricks or with multiple objects simultaneously. By systematically testing these cases and analyzing the results, I came to conclusion that the collision detection behaves as expected under different conditions.

Here’s the Game:

Features & Game Mechanics:
– Game initializes with a start screen displaying “Brick Breaker” and “Click to start” message.
– The player controls the paddle using the left and right arrow keys.
– The ball bounces off the paddle, walls, and bricks.
– When the ball hits a brick, it disappears, and the player earns points.
– If the ball falls below the paddle, the game ends.
– Once game ends, it displays the “Game Over” message along with the score and “Click to replay” option.
– Clicking on the canvas after the game ends resets the game, allowing the player to replay.

Additional Features:
– Sound effects are played when the ball hits the paddle and when it hits a brick.
– The player earns points for each brick broken, and the score is displayed on the screen.
– Background music plays throughout the game to enhance the gaming experience.

Here’s a snapshot taken during the game-play:

Complete Code Snippet (With Comments):

// Define global variables
let backgroundImage;
let ball;
let paddle;
let bricks = [];
let brickRowCount = 3;
let brickColumnCount = 5;
let brickWidth = 80;
let brickHeight = 20;
let brickPadding = 10;
let brickOffsetTop = 50; // Adjusted value
let brickOffsetLeft = 30;
let score = 0;

let ballHitSound;
let paddleHitSound;
let backgroundMusic;

let gameStarted = false;
let gameOver = false;

// Preload function to load external assets
function preload() {
  backgroundImage = loadImage('background_image.jpg'); // Replace 'background_image.jpg' with the path to your image file
  ballHitSound = loadSound('ball_hit.mp3');
  paddleHitSound = loadSound('paddle_hit.mp3');
  backgroundMusic = loadSound('background_music.mp3');
}

// Setup function to initialize canvas and objects
function setup() {
  createCanvas(500, 400); // Set the canvas size to match the background image size
  paddle = new Paddle();
  ball = new Ball();
  createBricks();
  backgroundMusic.loop();
  // resetGame(); // Commented out, not needed here
}

// Draw function to render graphics
function draw() {
  background(backgroundImage); // Draw the background image
  
  // Display "Click to start" only when game hasn't started and isn't over
  if (!gameStarted && !gameOver) {
    textSize(32);
    textAlign(CENTER, CENTER);
    text("Brick Breaker", width / 2, height / 2 - 40);
    textSize(20);
    text("Click to start", width / 2, height / 2);
  } else { // Game running
    if (gameStarted && !gameOver) { // Run game logic only when game is started and not over
      ball.update();
      ball.checkCollision();
      ball.display();
      
      paddle.display();
      paddle.update();
      
      // Display and handle collisions with bricks
      for (let i = bricks.length - 1; i >= 0; i--) {
        bricks[i].display();
        if (ball.hits(bricks[i])) {
          ball.bounce();
          bricks.splice(i, 1);
          score += 10;
        }
      }
      
      // Check if all bricks are destroyed
      if (bricks.length === 0) {
        gameOver = true;
      }
      
      // Display score
      fill('rgb(216,32,71)')
      textSize(20);
      textAlign(LEFT);
      text("Turn up the volume!                               Score: " + score, 20, 30);
    }
    
    // Display game over message
    if (gameOver) {
      fill('rgb(32,213,32)')
      textSize(32);
      textAlign(CENTER, CENTER);
      text("Game Over! Score: " + score, width / 2, height / 2);
      text("Click to replay", width / 2, height / 2 + 40);
    }
  }
}

// Mouse pressed function to start/restart the game
function mousePressed() {
  if (!gameStarted || gameOver) {
    resetGame();
  }
}

// Reset game state and objects
function resetGame() {
  gameStarted = true;
  gameOver = false;
  score = 0;
  ball.reset();
  createBricks();
}

// Function to create bricks
function createBricks() {
  bricks = [];
  for (let c = 0; c < brickColumnCount; c++) {
    for (let r = 0; r < brickRowCount; r++) {
      let x = c * (brickWidth + brickPadding) + brickOffsetLeft;
      let y = r * (brickHeight + brickPadding) + brickOffsetTop;
      bricks.push(new Brick(x, y));
    }
  }
}

// Ball class
class Ball {
  constructor() {
    this.reset();
  }
  
  // Reset ball position and speed
  reset() {
    this.x = paddle.x + paddle.width / 2;
    this.y = paddle.y - this.radius;
    this.speedX = 5;
    this.speedY = -5;
    this.radius = 10;
  }
  
  // Update ball position
  update() {
    this.x += this.speedX;
    this.y += this.speedY;
    
    // Reflect ball off walls
    if (this.x < this.radius || this.x > width - this.radius) {
      this.speedX *= -1;
    }
    if (this.y < this.radius) {
      this.speedY *= -1;
    } else if (this.y > height - this.radius) {
      gameOver = true; // Game over if ball reaches bottom
    }
  }
  
  // Display ball
  display() {
    fill(255, 0, 0);
    ellipse(this.x, this.y, this.radius * 2);
  }
  
  // Check collision with paddle
  checkCollision() {
    if (this.x > paddle.x && this.x < paddle.x + paddle.width && this.y + this.radius > paddle.y) {
      this.speedY *= -1;
      paddleHitSound.play(); // Play paddle hit sound
    }
  }
  
  // Bounce ball off objects
  bounce() {
    this.speedY *= -1;
    ballHitSound.play(); // Play ball hit sound
  }
  
  // Check collision with a brick
  hits(brick) {
    let closestX = constrain(this.x, brick.x, brick.x + brick.width);
    let closestY = constrain(this.y, brick.y, brick.y + brick.height);
    let distance = dist(this.x, this.y, closestX, closestY);
    return distance < this.radius;
  }
}

// Paddle class
class Paddle {
  constructor() {
    this.width = 100;
    this.height = 20;
    this.x = width / 2 - this.width / 2;
    this.y = height - 50;
    this.speed = 10;
  }
  
  // Display paddle
  display() {
    fill(0, 0, 255);
    rect(this.x, this.y, this.width, this.height);
  }
  
  // Update paddle position based on user input
  update() {
    if (keyIsDown(LEFT_ARROW)) {
      this.x -= this.speed;
    }
    if (keyIsDown(RIGHT_ARROW)) {
      this.x += this.speed;
    }
    this.x = constrain(this.x, 0, width - this.width);
  }
}

// Brick class
class Brick {
  constructor(x, y) {
    this.x = x;
    this.y = y;
    this.width = brickWidth;
    this.height = brickHeight;
  }
  
  // Display brick
  display() {
    fill(0, 255, 0);
    rect(this.x, this.y, this.width, this.height);
  }
}

Ideas to improve this project for the midterm:

1) User Experience: I’m thinking to enhance the user experience by adding features such as visual effects, animations, difficulty levels, and more interactive elements (themes) can make the game more engaging and enjoyable for players.

2) Saving High Scores  Implement functionality to allow players to save the player’s progress (high scores) and comparing them with their present and previous scores.

3) Immersive Audio Design: Enhancing more immersion by adding immersive audio effects or soundscapes to game play events and interactions. This features could adds more engaging and immersive audiovisual experience for the user.

Reading Response: The Psychopathology of Everyday Things, #Week4

Reflecting on Norman’s insights from “The Psychopathology of Everyday Things, Chapter:1” I find myself deeply considering the complexity hidden within simple everyday objects like doors, refrigerators, and watches. Norman points out that the designs meant to simplify our lives can sometimes make them more complicated instead. This resonates with me because I’ve often found myself frustrated by appliances and gadgets (like smart watches, bluetooth coffee maker) that have too many features. These features, instead of making the device better, can make it harder to use. Norman’s argument makes me rethink the belief that having more features means better functionality. My own experiences support this idea, as I’ve struggled with devices that seem to prioritize complexity over ease of use.

Furthermore, Norman’s critique makes me wonder about the true purpose of design. Is it more important for a product to look good and have lots of features than to be easy to use? This challenges the current trend in design, where form and complexity often take precedence over simplicity and functionality. Norman seems to favor designs that are straightforward and user-friendly, which makes me question my own ideas about what makes a design “good.” Previously, I might have thought that the more technologically advanced a product is, the better it is. However, Norman’s perspective has made me see the value in designs that balance functionality, simplicity, and elegance. This shift in thinking opens up new questions about how designers can create products that are both advanced and accessible. As technology evolves, finding the right balance will be crucial for creating products that enhance our lives without adding unnecessary complexity.

Yaakulya’s Assignment 4: Loading Data & Displaying text

Concept: I always wanted to understand the graphs and math revolve behind Real Estates, so for my Data Visualization assignment, I created a data visualization using the Boston Housing dataset. (Dataset URL: https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv)
This Dataset is available to public.

The resultant visualization displays the relationship between the average number of rooms per dwelling (RM) and the median home value ($1000s) for various suburbs in Boston. Each data point on the graph represents a suburb, with the x-axis indicating the average number of rooms and the y-axis indicating the median home value. Additionally, I implemented an interactive tooltip that provides detailed information about each data point when the user hovers over it, including the suburb name, crime rate, and median home value.

To make my concept work, I found inspiration from these sources and moreover I learnt a lot about attributes and functions used for loading the required data from the datasets precisely:

Highlight of Code: One part of the code that I’m particularly proud of is the implementation of the interactive tooltip, initially I found it very difficult. This feature enhances the user experience by providing additional information about the data points in a user-friendly manner. Here’s the code snippet responsible for displaying the tooltip:

function draw() {
  // Check if mouse is over a data point
  let overPoint = false;
  for (let i = 0; i < data.getRowCount(); i++) {
    let rm = map(data.getNum(i, 5), 3, 9, 100, width - 100);
    let medv = map(data.getNum(i, 13), 5, 50, height - 100, 100);
    let d = dist(mouseX, mouseY, rm, medv);
    if (d < 5) {
      overPoint = true;
      let suburb = data.getString(i, 0);
      let crimeRate = data.getNum(i, 1);
      let medianValue = data.getNum(i, 13);
      tooltip.html(`Suburb: ${suburb}<br>Crime Rate: ${crimeRate.toFixed(2)}<br>Median Home Value: $${medianValue.toFixed(2)}k`);
      tooltip.position(rm + 20, medv - 20);
      tooltip.show();
      break;
    }
  }
  if (!overPoint) {
    tooltip.hide();
  }
}

Explanation – How this Interactive feature works?: In the draw() function, which updates the canvas continuously, the code iterates through each data point in the dataset. It calculates the distance between the mouse cursor position and the position of each data point using the dist() function. If this distance is within a threshold of 5 pixels, indicating that the mouse is hovering over a data point, the code retrieves information such as suburb name, crime rate, and median home value using functions like getString() and getNum(). These functions extract specific values from the dataset based on row and column indices. The tooltip’s content is then updated to display this information, and its position is adjusted slightly from the data point using the position() function. Finally, the tooltip is shown to the user with show(). If the mouse is not over any data point, the tooltip is hidden using hide(). This process allows for interactive display of detailed information when the user hovers over data points on the visualization.

Complete Embedded Sketch:

let data;
let tooltip;

function preload() {
  // Load the Boston Housing dataset
  data = loadTable('https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv', 'csv', 'header');
}

function setup() {
  createCanvas(800, 600);
  background(240);

  // Plot the data points with black color
  for (let i = 0; i < data.getRowCount(); i++) {
    let rm = map(data.getNum(i, 5), 3, 9, 100, width - 100);
    let medv = map(data.getNum(i, 13), 5, 50, height - 100, 100);

    fill('rgb(197,134,88)'); // Change color to black
    noStroke();
    ellipse(rm, medv, 10, 10);
  }

  // Add x and y axes
  drawAxes();

  // Add interactive tooltip
  tooltip = createDiv('');
  tooltip.style('position', 'absolute');
  tooltip.style('background-color', 'rgba(255, 255, 255, 0.8)');
  tooltip.style('padding', '8px');
  tooltip.style('border-radius', '4px');
  tooltip.hide();


}

function drawAxes() {
  // Draw x-axis
  stroke(0);
  line(100, height - 100, width - 100, height - 100);
  for (let i = 4; i <= 9; i++) {
    let x = map(i, 3, 9, 100, width - 100);
    textAlign(CENTER, CENTER);
    textSize(12);
    fill(0);
    text(i, x, height - 80);
  }
  textAlign(CENTER, CENTER);
  textSize(16);
  fill(0);
  text('Average Number of Rooms per Dwelling (RM)', width / 2, height - 40);

  // Draw y-axis
  stroke(0);
  line(100, 100, 100, height - 100);
  for (let i = 5; i <= 50; i += 5) {
    let y = map(i, 5, 50, height - 100, 100);
    textAlign(RIGHT, CENTER);
    textSize(12);
    fill(0);
    text(i, 90, y);
  }
  textAlign(CENTER, CENTER);
  textSize(19);
  fill(0)
  text('Boston Housing Dataset Visualization (Year:1970-2006)', 400, 40);
  rotate(-HALF_PI);
  textSize(16);
  text('Median Home Value ($1000s)', -height / 2, 50);
}

function draw() {
  // Check if mouse is over a data point
  let overPoint = false;
  for (let i = 0; i < data.getRowCount(); i++) {
    let rm = map(data.getNum(i, 5), 3, 9, 100, width - 100);
    let medv = map(data.getNum(i, 13), 5, 50, height - 100, 100);
    let d = dist(mouseX, mouseY, rm, medv);
    if (d < 5) {
      overPoint = true;
      let suburb = data.getString(i, 0);
      let crimeRate = data.getNum(i, 1);
      let medianValue = data.getNum(i, 13);
      tooltip.html(`Suburb: ${suburb}<br>Crime Rate: ${crimeRate.toFixed(2)}<br>Median Home Value: $${medianValue.toFixed(2)}k`);
      tooltip.position(rm + 20, medv - 20);
      tooltip.show();
      break;
    }
  }
  if (!overPoint) {
    tooltip.hide();
  }
}

Generated Output:

Reflection and Ideas for Future Work: Overall, I’m satisfied with how the assignment turned out. The visualization effectively communicates the relationship between the number of rooms in a dwelling and the median home value in different suburbs of Boston. The interactive tooltip adds an extra layer of interactivity and information, enhancing the user experience.

For future work or improvements, I could consider adding more features to the visualization, such as:

1. Implementing color encoding for an additional variable, such as crime rate or pupil-teacher ratio, to provide more insights into the data.

2. Enhancing the design of the visualization by adding axis labels, a title, and a legend to improve clarity and understanding.

3. Exploring different types of visualizations, such as scatter plots or line charts, to represent the data in alternative ways and uncover additional patterns or trends in addition working with latest datasets.

Overall, this assignment has been a valuable learning experience, and I look forward to applying these skills to future assignments ad projects.

Related P5 References:
1. https://p5js.org/reference/#/p5/map
2. https://p5js.org/reference/#/p5.Element/style
3. https://p5js.org/reference/#/p5.Table/getNum
4. https://p5js.org/reference/#/p5.Element/hide
5. https://p5js.org/reference/#/p5.Element/position
6. https://p5js.org/reference/#/p5.Table/getString

Reading Reflection – Week#3

Reflection on “The Art of Interactive Design” by Chris Crawford:

After reading Crawford’s work, I found myself thinking about how interactivity is often misunderstood. Crawford compares interactivity to a conversation, where both parties listen, think, and speak. This analogy helped me understand that for interaction to be meaningful, both parties need to actively participate. Crawford also talks about how interactivity is often misused and misunderstood. (Pg 5, 6)

However, I had some questions about Crawford’s perspective. He criticizes traditional media like books and movies for not being interactive enough. But I believe these media still have value because they make us feel and think, even though they don’t interact with us directly. Crawford also seems biased towards interactive design over human factors engineering, which focuses on making tools more efficient for workers.

Another question that came up for me was about the limits of interactivity. Are there times when traditional media offer experiences that can’t be replaced by interactive designs? Overall, reading Crawford’s work made me rethink what interactivity means and how it affects design. It made me consider the importance of both form and function in design processes.