Week 3 – Assignment

Concept:

I have always loved space, especially anything to do with stars and the solar system, so for this assignment I decided to build a small generative solar system in p5.js using object oriented programming. Each orbiting body is a Planet object with its own distance from the sun, speed, size and color, all stored in an array so I could build and animate the whole system with loops instead of writing out five separate planets by hand. The exact stats for each planet are randomized within set ranges, so it looks a little different every time you refresh it, which felt fitting since no two solar systems out there actually look the same either.

How this was made:

I split the code into two files: sketch.js for the main setup/draw loop and the sun, and planet.js for the Planet class, which handles one planets data (distance, speed, size, color, current angle) plus its own update() and display() methods. In setup() I loop through and create 5 planets, spacing their orbit distances out with map() so they do not end up overlapping and giving each one a random speed, size and color. In draw() I loop through the array every frame so that update() moves each planet a little further along its orbit and display() draws it along with a faint ring showing its orbit path.

Code Highlight:

update() {
    this.angle += this.speed;
  }

  display() {
    push();
    //translate() shifts where (0,0) is on the canvas.
    //normally (0,0) is the top-left corner, so every shape would need
    //width/2 and height/2 added to its position to appear centered.
    //instead I move the origin itself to the center of the canvas once,
    //so I can treat the sun as sitting at (0,0) and calculate every
    //planets position relative to the sun instead of the corner
    translate(width / 2, height / 2);

    //orbit ring just a circle showing the path this planet travels
    //drawn centered on the new (0,0) which is now the canvas center
    noFill();
    stroke(255, 60);
    strokeWeight(1);
    ellipse(0, 0, this.distance * 2, this.distance * 2); //*2 because ellipse() takes diameter

    //this is the actual orbit math.
    //this.angle is a value in radians representing how far around
    //the circle the planet currently is (a full loop = TWO_PI, about 6.28)
    //cos(angle) and sin(angle) both output a number between -1 and 1 -
    //multiplying by this.distance scales that up to the actual orbit radius
    //I want turning it into a real pixel offset from the center.
    let x = cos(this.angle) * this.distance; //horizontal offset from center
    let y = sin(this.angle) * this.distance; //vertical offset from center

    //every frame angle increases slightly (from update()) which changes
    //the result of cos/sin slightly which moves x and y slightly 
    //that is what creates the smooth circular motion over time

    noStroke();
    fill(this.col);
    ellipse(x, y, this.size, this.size); //draw the planet at its calculated position

    pop(); //restore the coordinate system back to normal (undoes the translate)
           //so the next planet in the loop does not inherit this shift
  }

This is the part of the code in Planet class I am happy about, since it is where the actual orbiting motion happens. update() just nudges the planets angle forward a tiny bit every frame, like a slowly ticking clock hand. In display(), I use translate() to shift the canvas’s origin point to the center, so I can treat the sun as sitting at (0,0) instead of constantly adding width/2 and height/2 to every position. Then cos(this.angle) and sin(this.angle) calculate where a point at that angle would land on a circle, and multiplying by this.distance stretches that out to the planets actual orbit radius. Since the angle keeps increasing frame by frame, this position keeps recalculating slightly differently each time, which is what produces the smooth circular motion. I wrap the whole thing in push() and pop() so the translate only affects this one planet and does not carry over and throw off the position of the next planet in the loop.

Problems I ran into:

The orbit math was the main thing I struggled with like I understood conceptually that I wanted planets to move in circles but I could not figure out on my own how to turn an increasing angle into an actual x/y position on screen. I ended up going back to Claude multiple times to work through the logic and the translate() part step by step until it actually clicked. I also ran into an issue with the orbit rings not lining up with the planets real path. I had unfortunately forgotten that ellipse takes a diameter and not a radius, so my rings were drawn at half the size they should have been. On top of that, I had to switch from fully random orbit distances to using map() to space them out evenly since random values kept causing planets to spawn too close together or right on top of the sun.

Embedded Sketch:

Reflection and ideas for improvement

This was honestly one of my favorite assignments so far because of the subject matter. Using classes also made a lot more sense once I actually built something with them, since having each planet manage its own data felt way cleaner than juggling separate arrays. For future improvements, I would really like to make the orbits a little more realistic by making them elliptical instead of perfect circles and maybe add small moons orbiting the planets themselves and also add fading trails behind each planet so you can actually see the path it has traced instead of just a plain guide ring!!!

References:

https://p5js.org/reference/p5/translate

https://p5js.org/reference/p5/cos

https://p5js.org/reference/p5/sin

https://p5js.org/reference/p5/push

https://p5js.org/reference/p5/pop

https://p5js.org/reference/p5/map

 

Week 3 – Reading Reflection

I really enjoyed doing this reading. What actually got me thinking was how strict he is about needing all three steps. Like it has to actually process what the user does and hold onto some kind of memory so the response can change based on more than just the current input and then respond in a way that reflects that processing instead of just playing back a fixed effect. I think I agree with his sentiment (for now atleast).

That is actually a useful way to look at my own p5 sketches because most of what I have built so far leans hard on that same idea of reacting instantly, so it feels interactive but there is no real thinking step. A way to fix that would be introducing an actual state like tracking things like how long the users cursor lingers in an area and letting the sketchs behavior shift over time instead of resetting every frame. Even something simple, like the sketch remembering the last few interactions and varying its response based on that instead of just the instantaneous mouse position would push it from Crawford’s “reaction with good production values” into something closer to his actual definition of interaction. Though I’ll be honest I do not know how to go about doing it but I am definitely excited to learn and explore it in the coming classes!!!

Week 2 – Assignment

My concept:

For this assignment, I made an interactive starfield. The idea was to have a field of stars scattered across the canvas that glow individually when the mouse touches them and I used loops to generate and animate the stars and a conditional to control the glow effect. I was inspired by just looking at the night sky at the Al Quaa Milky Way Spot.

How I made it:

I started by creating an empty array called stars to hold each star as an object. Then in setup I used a for loop to generate 125 stars, giving each one a random x position y position and size and then pushing that data into the array as an object. After that in draw I used another for loop to go through every star in the array each frame to check its distance from the mouse using distance function and used an if/else conditional to decide whether that star should glow bigger and brighter or stay as a small dim dot.

Code highlights:

for (let i = 0; i < stars.length; i++) {
    let s = stars[i]; //named it as s for convenience

    //checking distance from mouse to this star
    let d = dist(mouseX, mouseY, s.x, s.y);

    if (d < 60) {
      //close to mouse so glows bigger and brighter
      fill(255, 255, 200);
      noStroke();
      ellipse(s.x, s.y, s.size * 3, s.size * 3);
    } else {
      //normal dim star
      fill(255);
      noStroke();
      ellipse(s.x, s.y, s.size, s.size);
    }
  }

This part is what I like the most. Since the loop runs through every star every single frame, each one is constantly rechecking its own distance from the mouse which is what makes the glow follow the cursor smoothly and only affect stars that are actually close to it.

Embedded Sketch:

Reflection and Ideas:

I really liked doing this assignment but if I had to change something, I might have added more details to the stars and like a shape to it. I could have also tried to add a moving feature that causes the stars to maybe follow or repel away from the mouse. I was inspired by the video to make the stars random positions each time. I am happy with how it looks and maybe could work on it more in the future to make it even better!!

References:

https://p5js.org/reference/p5/loop/, https://p5js.org/reference/p5/for/, https://p5js.org/reference/p5/if/

 

Week 2 – Reading Reflection

Okay so last semester I took Live Coding with Professor Aaron and this whole talk kind of took me back to that. Every time I would throw in a random() somewhere in Hydra or Tidal I always told myself I was letting go of control but honestly I was not I was just picking a range of outcomes I was fine with and calling it random. Watching Reas go from Duchamp literally dropping strings on the floor to writing actual random number generators kind of made that connection that it is the same move, just with more math. He is not really doing something new but doing the same “let something outside me cause this” thing people have been doing since like 1916.

The note that stuck with me the most was the “ordered grid with deviation of pixels” thing because that is literally what I was chasing in class without knowing how to say it. If the pattern is too locked in it just looks dead and boring, but if it is too random it just looks like noise and does not feel like anything. The good zone is somewhere in between where you can tell there is a rule happening but it still surprises you sometimes. That is basically what his 15-image series is doing: same rule every time but different result.

So when I think where the balance is between total randomness and total control, I do not really think it is a 50/50 thing. I think what I actually want is like a really good system with one small deviation in it on purpose. Full control means no surprises, which gets boring fast. Full randomness means no me in it anymore, it is just noise doing its own thing. The deviation in between is where it actually feels like art to me.

Week 1 – Self Portrait

Hello!! For my first assignment in Intro to IM, I made a self portrait using p5.js. I just combined basic shapes and a few lines for smaller details like the nose and glasses.

Embedded Sketch!!

How I made it!!

I started by making the body using a simple rectangle shape and then added an ellipse on top for the face. For the eyes, I created a wider white ellipse with a smaller black ellipse on top to create the pupil. For the hair, I used the arc() function set to only draw the top half of a circle so it sits like a dome over the head. I also added a moon in the night sky background and glasses over the eyes since I always wear glasses.

The main source I used to help me code was the p5js reference site to remind myself of the parameters of each shape especially for the arc.

Code Highlights

//glasses
    stroke(0);
    strokeWeight(4);
    noFill();
    ellipse(width/2.5, height/1.9, 45, 30);
    ellipse(width/1.66, height/1.9, 45, 30);
    line(width/2.5+22, height/1.9, width/1.66-22, height/1.9);
    line(width/2.5-22, height/1.9, width/2.5-40, height/1.9-5);
    line(width/1.66+22, height/1.9, width/1.66+40, height/1.9-5);

The glasses gave me the most trouble. I had to line up two more ellipses exactly on top of the eyes without covering the pupils so I used noFill() so I would get only an outline instead of a solid shape. Then I needed a bridge line connecting the two lenses and two more lines angled slightly outward on each side to look like the arms of the glasses. Getting all of them to actually connect at the same points took a lot of trial and error.

//moon
    fill(255, 255, 220);
    noStroke();
    ellipse(340, 50, 50, 50);
    fill('#464444');
    ellipse(352, 42, 45, 45);

I found that I could fake a crescent shape by drawing a full ellipse and then covering part of it with a second ellipse painted the exact same color as the background

Reflection and Ideas:

This assignment was fun and I found myself losing track of time while doing it, for future assignments I would love to go more in depth with p5.js and add animations and more detailed drawings.. I could have added more details in the background and maybe even designed the body to make it look more detailed.