Flake’s argument that nature is “frugal” and reuses the same simple rules for everything feels like a massive leap for us to make as a species. While he uses examples like the self-similarity in snowflakes and ferns to show how simple rules create complexity , I think we’re still too early in our development to claim we’ve figured out nature’s “program.” Now I’m not a hard science expert, but I find it hard to buy into his bold claim that nothing in nature stands above computational processes. We’re constantly discovering new things that break our old rules, and it feels a bit arrogant to assume that just because we’ve invented math and physics that can simulate a duck or an ant colony, we’ve actually decoded the fundamental “code” of the universe.
I also have a hard time with Flake’s “Silicon Laboratory” metaphor, mostly because it feels like it strips away the actual weight of being human. He talks about how groups like ant colonies or gazelle species find “solutions” through multiplicity , and while it’s true that human societies developed faster when we started sharing knowledge, being part of a group isn’t always a perfect “computational” win. In real life, groups can lead to things like mob violence or, on a completely different coin, the deep grief of losing someone – emotional experiences that a computer simulation could never truly capture. Flake seems biased by his computer science background, seeing the world as a series of number mappings. It makes me wonder, if we reduce everything to simple rules, do we lose the ability to understand things like yearning or heartbreak that don’t follow a logic-based script?
Reading Chapter 2 of The Nature of Code weirdly calmed me down. I think I usually approach motion by trying to make things feel dramatic or responsive, like faster equals better. This chapter made me slow down and realize that motion is not about speed at all. It is about pressure. Direction. Influence.
What really clicked for me is the idea that forces act on acceleration, not velocity. That sounds obvious when you read it, but in practice I was constantly breaking that rule. Every time I moved the mouse, I was basically telling the system to panic. Once I stopped doing that and forced the speed to stay constant, the sketch suddenly felt more confident. The rain did not need to prove anything. It just kept falling.
I also liked how the book is not obsessed with realism. It cares more about whether something feels believable. That gave me permission to simplify. My rain is not physically accurate, but it behaves consistently. Gravity always pulls down. Wind always pushes sideways. When the cursor leaves, the wind eases out instead of snapping back. That easing honestly made the biggest difference emotionally. It feels patient, not reactive.
Another thing that stuck with me is how small forces matter when they accumulate. I kept my wind values tiny because I was scared of it getting messy. But because they are applied every frame, they slowly shape the motion. That made me trust the system more instead of over-designing the interaction. I did not need big gestures. I needed persistence.
this chapter made me realize that personality in motion comes from constraints. By limiting speed and letting forces only steer, the rain feels stubborn in a quiet way. It does not rush when you touch it. It responds, but on its own terms. I think that is the first time I felt like I was designing behavior instead of just animation.
For future work, I want to play more with multiple forces at once without losing control. I am also interested in how constraints can be used intentionally to create mood, not just structure. This reading made me think less about showing off interaction and more about letting motion breathe.
For my movement-in-nature example, I focused on rain falling in wind. I like rain because it looks simple, but it is actually full of micro rules. It accelerates because of gravity, it gets pushed sideways by wind, and it never falls in a perfectly clean line. It feels alive even when nothing “exciting” happens.
My goal was to give the rain a personality through behavior only: steady, determined drops that do not freak out. Even when you move your cursor hard left or right, the rain will lean but it will not speed up. It is stubborn in a calm way.
Rules I used
Each raindrop has a velocity and an acceleration.
Acceleration acts like steering, not like speed boosting.
After applying acceleration, I force the velocity back to a constant magnitude so every drop keeps the same speed.
Cursor movement creates wind direction, but the wind eases in and out so it feels natural, not like a switch.
Mouse click adds more drops, it does not change the physics.
Code highlight I am proud of
This is the moment where the whole concept becomes real. I let acceleration steer the motion, then I “lock” the speed so nothing can accidentally accelerate out of control:
update() { // acceleration steers direction this.vel.add(this.acc);// constant speed ALWAYS (prevents mouse from “speeding it up”) this.vel.setMag(SPEED);this.pos.add(this.vel);
}
This is basically my “thesis”. The rain can have mood and direction changes, but it stays consistent. It feels grounded.
Embeded sketch
Reflection + future improvements
I love how it turned out honestly
What worked:
The constant speed constraint makes the sketch feel controlled and intentional. Even when the wind changes, it stays believable and not chaotic.
The eased wind makes interaction feel like a real force building up, not a sudden game mechanic.
The click-to-add drops changes the “weather intensity” without breaking the physics.
What I would improve next:
Depth: Add a second layer of drops that are thinner and slightly slower, so it feels like near/far rain.
Gust behavior: Instead of mapping wind directly to mouseX every frame, make occasional gusts that ramp up and decay, then let the cursor influence gust direction.
Splashes: When drops hit the bottom, spawn tiny splash particles for a few frames.
Performance polish: Use an object pool for drops so we reuse drops instead of constantly adding new ones when clicking.
What inspired this project is my fish, Abdulfattah, a Betta fish that was gifted to me from a very dear person to my heart.
This sketch mimics natural fish movement when it spots food. The user moves the mouse around and upon clicking you essentially drop a fish food pellet, and the fish mimics natural movement and acceleration towards food.
I first started t project by adding a background I found online
Blue water surface template in cartoon style illustration
then I made a rectangle that will later be a fish to start simulating it’s movement.
then I wrote very simple code with if statements just as a base for my fish movement.
then I updated my code to lerp (linear interpolation) towards the mouse.
After that I started implementing dropping fish pellets, I started with creating a simple function to spawn pellets with an array of circles.
let circles[];
//in draw
for (let circle of circles) {
fill(139, 69, 19); // brown
noStroke();
ellipse(circle.x, circle.y, 20, 20);
function mousePressed() {
circles.push({x: mouseX, y: mouseY});
}
Then I added a sinking motion for the pellets with a slight drift using the sin function to simulate natural waves pushing pellets around as they are sinking with a random angle for variation.
// draw food pellets
for (let i = circles.length - 1; i >= 0; i--) {
let circle = circles[i];
// make circle float downwards
circle.y += circle.speed;
// increment the angle for sin
circle.angle += 0.05;
// subtle drift for food pelletes
let drift = sin(circle.angle) * 20;
// draw circles
fill(139, 69, 19);
noStroke();
ellipse(circle.x + drift, circle.y, 20, 20);
then I edited the code to make the rectangle follow the pellets instead of the mouse. For error handling, the pellets are put in a stack such that the rectangle eats the pellets using a queue as a data structure following the FIFO (first in last out) principle.
A challenge I faced:
As shown in the previous gif, there was a problem where the rectangle can’t eat the food because the pellets are drifting and sinking. This is happening because the rectangle is trying to go the position of that circle but it doesn’t account for the drifting and sinking, therefore, its more like it’s tracing the pellet rather than trying to catch it.
The way I tackled this challenge is also a highlight of the code that I’m proud of.
.I fixed this by predicting where each pellet would be 10 frames ahead, accounting for sinking and horizontal drift. I calculated the direction vector and euclidean distance to this predicted target, then normalized it to apply acceleration forces. The velocity builds gradually but it’s not fully smooth yet but I’ll get to that later. I multiplied velocity by 0.92 each frame for friction, cap the maximum speed, then update position. When the fish gets within 30 pixels of a pellet, it gets removed from the queue with shift() and reduce velocity by 70%. This creates a deceleration effect before accelerating toward the next pellet.
function followCircles(){
// if there are circles, follow the first one following FIFO principle
if (circles.length > 0) {
let target = circles[0];
// predict where the pellet will be
let futureY = target.y + target.speed * 10;
let futureAngle = target.angle + 0.03 * 10;
let futureDrift = sin(futureAngle) * 1.5;
let targetX = target.x + futureDrift; // i add the predicted position here so the fish can catch the food
let targetY = futureY;
// calculate direction to predicted position
let dx = targetX - x;
let dy = targetY - y;
let distance = dist(x, y, targetX, targetY); // calculate the eucilidian distance of the fish and the pellet
// normalize direction and apply acceleration
if (distance > 0) {
vx += (dx / distance) * acceleration;
vy += (dy / distance) * acceleration;
}
// apply friction for more natural movement
vx *= friction;
vy *= friction;
// limit speed
let speed = dist(0, 0, vx, vy);
if (speed > maxSpeed) {
vx = (vx / speed) * maxSpeed;
vy = (vy / speed) * maxSpeed;
}
// update position with velocity
x += vx;
y += vy;
// check if rectangle is touching the circle
let actualDistance = dist(x, y, target.x + target.drift, target.y);
if (actualDistance < 30) {
circles.shift(); // eat the circle
// reduce velocity when eating
vx *= 0.3;
vy *= 0.3;
}
} else {
// slow down when no target
vx *= 0.9;
vy *= 0.9;
}
}
another problem I faced was the fish was getting stuck around the corners but I easily fixed that but implementing a function that lets the fish wander using perlin noise (Thanks professor Jack!!)
I want to have a simulation of the background such that it actually simulates fluids and looks like water. I also have 3 more fish in the tank that are Abdulfattah’s friends that I want to add, they always steal his food so it would be more realistic that way. Moreover I want to have a bigger canvas so I can add object you naturally find in the ocean or the one’s I have in my fish tank, and an algorithm that makes the fish occasionally hide behind those objects. Lastly, I want an algorithm where sometimes the fish just rests in the tank doing nothing, which would add more realism to the sketch.
For this assignment, I was tasked with finding an example of movement in nature and simulating it using code. I started by looking at how birds move in flocks. There is a specific fluidity to how they accelerate and glide that feels very different from mechanical movement.
I found this video of birds in flight which served as my primary visual reference:
While watching the video, I realized that we almost always observe birds from the ground looking up. I wondered: How do birds see each other?
I decided to shift the perspective. Instead of a human watching a bird, I wanted to create a First-Person Flyer (FPF) experience. The concept became a “Bird Chase Simulation,” where the user plays as a predator bird (or perhaps a playful friend bird) trying to catch up to a leading bird.
My goal was to give the movement “personality” not just through the way the bird looks, but through how the acceleration feels. High acceleration shouldn’t just mean “go faster”, it should feel energetic and slightly chaotic, changing the bird’s perspective of the world.
Process
Before I could make it look like a bird, I had to make it move like one. The prompt required controlling motion only by manipulating acceleration.
I started with a greyboxing phase. I created a relationship where the distance between the player and the target wasn’t represented by X/Y coordinates, but by the scale of the target. If you accelerate and get closer, the target gets bigger,if you stop flapping (drag), you fall back, and the target shrinks.
Here is a screen recording of that initial physics test:
The Code
The part of the code I am most proud of is the relationship between the Acceleration Input and the Camera Shake.
The prompt asked us to give the movement personality. I achieved this by making the “camera” (the viewport) physically shake when the user pushes the acceleration slider to the max. It simulates the physical exertion of flapping wings hard against the wind. It bridges the gap between the math (acceleration numbers) and the feeling (struggle/speed).
Here is the snippet that handles that logic:
// === PHYSICS SECTION ===
let accVector = createVector(0, accInput);
playerVel.add(accVector);
// === CAMERA SHAKE EFFECT ===
// Add shake when accelerating hard (makes it feel more dynamic)
let shakeX = 0;
let shakeY = 0;
// Only shake if we are putting in significant effort (> 0.05)
if (accInput > 0.05) {
// Map the shake intensity to the acceleration input
let shakeAmt = map(accInput, 0, 0.5, 0.5, 6);
shakeX = random(-shakeAmt, shakeAmt);
shakeY = random(-shakeAmt, shakeAmt);
}
// Later, in the drawing section:
translate(width/2 + shakeX, height/2 + shakeY);
The Simulation
To finalize the piece, I added a circular clipping mask to create a “binocular” or “focus” effect, simulating the bird’s vision. I also added wind lines that react to the player’s speed to create a parallax effect, enhancing the sensation of forward momentum.
Instructions:
Use the slider at the bottom to control your Acceleration (how hard you are flapping).
Try to catch up to the bird in front of you.
Notice how the view shakes and the wind rushes faster as you exert more energy.
Reflection & Future Work
This project was a great exercise in using simple variables (acceleration and scale) to create a 3D illusion. The hardest part was tuning the “drag” or air resistance. If the drag was too high, it felt like flying through soup; too low, and the bird felt like a rocket with no weight.
I’m happy with how the beak breathing animation and the camera shake added life to the static shapes.
For the future: Currently, the movement is linear (forward/backward). I would love to introduce steering, allowing the player to move left and right to chase the target bird as it weaves through the sky. I also think adding a Stamina bar would add a game-like element, forcing the player to choose when to glide and when to sprint.
The concepts explored in this reading were very central to how we view things and analyze not only nature but also human-made systems like the stock market. What left a strong impression on me is how important it is to analyze interaction in order to truly understand what something is. At the beginning of this chapter, Flake introduces the idea of reductionism, which is the process of reducing something into increments to better understand its true nature.
In my understanding, we are invited to look at this from a rather “scientific” lens in order to see how we could apply a similar concept in computing. This leaves me with the impression that it is very important for us to first understand how dissecting something in terms of meaning can then help us introduce that understanding to a computer.
The Concept
My concept is inspired by fireflies. Having never experienced them, I have always been curious about what it would feel like to interact with one, so why not simulate it?
For the sake of simulating human-to-firefly interaction, I did not want the firefly to simply float around randomly. I wanted it to follow the mouse around the sketch in order to translate a sense of curiosity between both the firefly and the user.
I implemented a Gaussian random walk (List 1) and mapped the motion to color and brightness to create a firefly glow effect (List 2).
I’m proud of this part of the code because I wanted the firefly’s glow to feel as natural as possible. Using Gaussian randomness makes the brightness fluctuate gently instead of jumping unpredictably, and constraining the values keeps the light within a realistic range.
The Sketch
Reflection
Initially, I wanted to mimic bacteria and binary fission, but that idea felt a bit too ambitious at this stage. I decided to step back and focus on exploring motion in a simpler way, which led me to this firefly concept. I was interested in creating something that felt organic and calm rather than complex.
For future work, I wanted to place the firefly over an image of a forest, but I realized that doing so would either cause the firefly’s trail to disappear or require the background to fade over time. I think finding a way to balance a real forest image with the artificial movement of the firefly could be an interesting direction to explore further.
The Computational Beauty of Nature
by Gary William Flake
Immediately during the author’s section on reductionism I began to think about determinism but specifically a concept called Laplace’s demon. Coined by Pierre-Simon Laplace a French philosopher in the 19th century, it refers to the idea that if you reduced the world to its most fundamental particles and had complete knowledge of all existing particles and the forces acting upon them and the forces that they can act upon other particles with a strong enough calculator you could predict anything. Free-will, and randomness would be illusions. It’s the most reductionist concept I know of.
However, as the author continued he did not begin to discuss free will and the purpose of life. Rather:
We have, then, three different ways of looking at how things work. We can take a purely reductionist approach and attempt to understand things through dissection. We also can take a wider view and attempt to understand whole collections at once (pg. 2)
…Or we can take an intermediate view and focus attention on the interactions of agents (pg. 2)
I appreciated the middle approach that the author wanted to take since I believe it would be more practical than Laplace’s demon for example.
As he began to discuss the examples across nature I realized that the concept’s I’m going to have to keep in mind for the rest of the course are in the three paragraphs on page 4. They are too long to paste here but to keep it as short as I can: Parallelism, Iteration, and Learning. Other words were used but I picked those because I find them the most memorable.
My Code
(Click on the sketch and click and drag your mouse)
For this assignment I picked the following from List 1 and List 2 respectively:
– Try implementing a self-avoiding walk
– Walk through RGB or HSB space (as opposed to XYZ)
What you’re looking at is a snake like shape which moves around in 3 pixel increments (step_size in the code) and it goes in whichever direction it wants to until it collides with itself at which point it stops.
At the head of the snake is a circle and there are lines for the path’s that it’s traversed previously.
In addition, the color of the lines or head of the snake changes depending on where it’s located on the canvas. I based it off of the color mode HSL which stands for Hue Saturation Lightness. Hue is an angle from 0-360 degrees (search up HSL color wheel) and the canvas is just set to be the window height and not a hard coded value. So I used the map function. I did the same for Saturation but I kept lightness at 50, if it was at 100 it would always be white, if it was at 0 it would be black. I could have used HSB and kept B at 100 and it was HSB which is why in the class Walker it’s b: 100, I forgot why I changed it to be honest.
My Personal Highlight
placement_calculation(x, y) {
let x_remainder = x % step_size
let y_remainder = y % step_size
let new_coordinate = new Coordinate(x - x_remainder, y - y_remainder)
return new_coordinate;
}
The reason I picked these few lines of code was because it was something I had come up with myself and had not done before. To ensure that all of the snakes/walkers stay on the same grid/lattice when placed I used this function. It takes the modulus of x, and y, with step_size and then for the new coordinate that’s being outputed its the x/y value given minus the remainder.
This ensures that the x,y coordinate that the snake is placed on is always a multiple of the step_size. I’m not sure if that made sense but it was the most efficient method I could think of to keep everything on the same grid.
Reflection
I’m happy with how the sketch looks and I think the code is somewhat easy to read. Going into this project I’ve been trying to make more readable code using variable names that explain what the variable is rather than an abbreviation and relying on comments. In the event that I did use an abbreviation I wrote a comment above (in the is_surrounded function).
With that being said there are some things I would like to change. Most importantly rather than relying purely on random chance I would like to implement some kind of formula or iterative design that can make the snake/walker last longer. And, a function to ensure that walkers don’t cross the paths of other walkers.
For this project, I created a random walker that moves using dynamic probabilities instead of fixed directions. At every step, the walker makes a decision: it has a 50% chance to move toward the mouse and a 50% chance to move in a random direction. This creates motion that sometimes feels intentional and sometimes unpredictable.
To connect motion to another medium, I mapped movement into color by letting the walker walk through HSB color space. As the walker moves, its hue slowly shifts, leaving a trail of changing colors. This makes the motion visible not only through position, but also through color.
Code Highlight
The part I am most proud of is the simple probability rule that controls the walker’s behavior:
// 50% chance: move toward mouse
if (random(1) < 0.5) {
let target = createVector(mouseX, mouseY);
let dir = p5.Vector.sub(target, pos);
dir.setMag(step);
pos.add(dir);
}
// 50% chance: random move
else {
let angle = random(TWO_PI);
pos.x += cos(angle) * step;
pos.y += sin(angle) * step;
}
With only one small decision, the system creates two very different behaviors: attraction and randomness. This balance makes the motion feel alive without being complicated.
Embedded Sketch
Reflection and Future Work
This project showed me how simple rules can create expressive motion. Even with only two possible choices, the walker feels responsive and unpredictable at the same time. I also liked how color helped reveal the path and rhythm of the movement.
In the future, I would like to change the probability based on the distance to the mouse so the attraction becomes stronger or weaker depending on position. I would also like to add multiple walkers with different behaviors and experiment with Gaussian step sizes to create smoother motion. Another idea is to map movement to sound, such as pitch or stereo pan, instead of color.
Overall, this project helped me understand how probability and interaction can shape motion in simple but interesting ways.
While reading the introduction of The Computational Beauty of Nature, I realized that the author is challenging the way we usually try to understand systems. We often break things into smaller parts, but Flake explains that this is not enough to explain how complex behavior appears. Even if we understand each part well, we still may not understand what happens when many parts interact together. This idea changed the way I think about learning and problem solving.
The example of ants stood out to me the most. A single ant behaves in a simple way, but together ants form organized colonies with complex behavior. I found this interesting because it shows that complexity does not need complicated rules. It can come from simple actions repeated many times. This reminded me of programming, where small pieces of code can create systems that behave in surprising ways.
I also liked the idea that nature itself “computes.” Systems react to their environment, adapt, and evolve over time. Seeing learning and evolution described in this way made me realize that computer science is connected to many other fields, not just technology.
Overall, this chapter made me more curious about how simple rules can lead to complex behavior, and it helped me see computation as a way to understand patterns and intelligence in the world, not only as something done by machines.
The whole reductionism vs. emergence thing really clicked for me this week, especially after coding that self-avoiding creature.
Flake talks about how knowing what a single ant does won’t tell you anything about what an ant colony can do. That’s exactly what I experienced with my sketch. Each point in my creature just checks “can I move here without hitting myself?” Super simple rule. When you watch it grow though, you get these weird tentacle formations and organic shapes that I definitely didn’t program. The complexity just emerges from repeating that one simple check.
What got me thinking was his point about nature using the same rules everywhere. The collision detection in my code works the same way for anything avoiding anything else. Planets avoiding black holes, people maintaining personal space in crowds, cells not overlapping during growth. One rule, infinite applications.
The part about computers blurring the line between theory and experimentation felt super relevant too. When I was debugging my creature, I was literally experimenting with artificial life. Tweaking the growth probability or cell size and watching how behavior changes feels more like running biology experiments than writing traditional code. You make a hypothesis (“smaller cells will create more detailed shapes”), run it, observe what actually happens (nope, just slower performance), adjust and repeat.
I’m curious about the “critical region” he mentions between static patterns and chaos. My creature usually grows until it gets trapped and can’t find new space. That feels like hitting some kind of critical point where the system freezes. Maybe if I added randomness to let it occasionally break its own rules, it could escape those dead ends? Then would it still count as “self-avoiding” though?