Frog Catching Flies – Movement Assignment 2

Concept

I wanted to capture the contrast between patience and explosive action you see when a frog hunts. Frogs sit completely still, tracking flies with just their eyes, then BAM tongue shoots out in a split second. The whole personality comes from this timing difference, not from making it look realistic.

The movement is controlled purely through acceleration values. The frog’s body never moves (zero acceleration on position), but the tongue has two completely different acceleration modes: aggressive when extending (accel = 8) and gentle when retracting (accel = -0.8). The flies get constant random acceleration in small bursts, which creates that jittery, unpredictable flight pattern you see in real insects.

I found a few videos of frogs hunting online and what struck me was how much waiting happens. Most of the time nothing is moving except the eyes tracking. Then when the tongue extends, it’s over in like 200 milliseconds. I tried to capture that same rhythm lots of stillness punctuated by sudden action.

Code Highlight

The part I’m most proud of is how the tongue uses completely different acceleration values depending on its state:

if (this.state === 'striking') {
  // Explosive acceleration out
  this.tongueAccel = 8;
  this.tongueVel += this.tongueAccel;
  this.tongueLength += this.tongueVel;
  
  if (this.tongueLength >= this.maxTongue) {
    this.state = 'retracting';
    this.tongueVel = 0;
  }
}

if (this.state === 'retracting') {
  // Gentle acceleration back
  this.tongueAccel = -0.8;
  this.tongueVel += this.tongueAccel;
  this.tongueLength += this.tongueVel;
  
  if (this.tongueLength <= 0) {
    this.tongueLength = 0;
    this.tongueVel = 0;
    this.tongueAccel = 0;
    this.state = 'idle';
  }
}

 

The 10x difference in acceleration (8 vs 0.8) creates that snappy-then-slow feeling. The tongue rockets out but drifts back lazily. This tiny numerical difference gives it way more personality than any visual design could.

Embedded Sketch

 

Reflection & Future Ideas

The acceleration-only constraint actually made this more interesting than if I’d used direct position control. You get these natural easing curves without writing any easing functions. The tongue feels weighty and real.

Things I noticed while testing:

  • The flies sometimes cluster in corners and the frog gives up. Maybe add a “frustration” behavior where it shifts position after too many misses?
  • The eye tracking is subtle but really sells the “watching” behavior. Glad I added that.
  • Random acceleration on the flies works better than I thought. They feel nervous and unpredictable.

Future improvements:

  • Add multiple frogs competing for the same flies
  • Make the frog’s strike range dependent on hunger (longer tongue when hungry = more acceleration)
  • Flies could accelerate away when they sense the tongue coming
  • Different frog personalities (patient vs aggressive = different strike thresholds)
  • Tongue could miss sometimes based on fly speed

The constraint of “acceleration only” forced me to think about how motion creates personality. A patient hunter isn’t patient because of how it looks, it’s patient because of when and how it accelerates.

 

Reflection on Chapter 1 – The Computational Beauty of Nature

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?

Self-Avoiding Morphing Creature

Concept

 

For this week’s assignment, I combined a self-avoiding walk with a morphing creature shape. Basically, I wanted to create something that grows organically without ever crossing itself, like a blob that’s aware of its own body.

The creature starts as a small circle and then tries to expand outward by adding new points. Before placing each new point, it checks if that spot is already occupied using a simple grid system. If it’s clear, the point gets added and the shape grows. If not, it tries a different direction.

What makes it feel alive is the constant wiggling, each point shifts slightly every few frames, but only if it won’t cause a collision. This creates this pulsing, breathing effect that’s kinda so cool to watch.

Code Highlight

An interesting part in my code is the collision (closely distant) detection:

isBlocked(x, y, skipIdx) {
  // Check if grid cell is taken
  if (occupied[this.gridKey(x, y)]) return true;
  
  // Check if too close to other points
  for (let i = 0; i < this.points.length; i++) {
    if (i === skipIdx) continue;
    if (dist(x, y, this.points[i].x, this.points[i].y) < cellSize * 1.5) {
      return true;
    }
  }
  return false;
}

It’s doing a double-check: first looking at the grid to see if that cell is occupied, then measuring the actual distance to nearby points. The skipIdx parameter lets a point check if it can move to a new spot without counting itself as a blocker. Simple but effective.

Embedded Sketch

Future Ideas

For future improvements:

  • Add multiple creatures that avoid each other
  • Make the growth pattern follow the mouse or respond to sound
  • Different growth strategies (maybe prefer growing upward, or toward light sources)
  • Color shifts based on age or density of the creature