• Unlikely Objects
  • Ludography
    • Nonoku
    • Acquisition
    • Image Mark Up
  • About
Menu

Unlikely Objects

  • Unlikely Objects
  • Ludography
  • Pint Sized Planet
    • Nonoku
    • Acquisition
    • Image Mark Up
  • About
The 9th iteration of the Sierpinski triangle.

The 9th iteration of the Sierpinski triangle.

An Evening of Code: Sierpinski Triangle

February 11, 2015

An extension of yesterday's work with L-Systems. The Sierpinski Triangle.

Firstly, I updated the implementation to draw the shape over a number of frames. This is not the end goal of this work so I'm doing it in Unity by drawing to a texture which is easy to implement but far from the most efficient ;) In this case it was best to limit the texture size to 512x512 to avoid a severe performance hit when redrawing the texture. If I needed to, I could simulate a larger texture by mapping it to multiple smaller ones but that's out of scope for the moment.

Next I updated the rules implementation to support multiple rules. Previously I used a single string and a regular expression. This no longer worked because the rules have to be applied simultaneously. Instead, I used a Dictionary to store the rules and, since the rules I need at the moment are only applied to a single character I could simply enumerate the axiom and use the character as the key to the dictionary. If there's a match I append the rule to a new string. If not I append the character.

There is one additional change that is not described in the notation - after each iteration the angle gets flipped so that it goes from 60 to -60, and back again. This is required to keep the triangle facing the same way at each iteration.

A= Step forward
B = Step forward
+ = +60 degrees
- = -60 degrees

A → B-A-B
B → A+B+A

Axiom: A

After 9 iterations the string has gone from 1 to 39,365 characters.

 

string Iterate(string axiom) {  
  string newAxiom = ""; 
  foreach (char c in axiom) {
    string ch = c.ToString();
    string replace = null;
    rules.TryGetValue(ch, out replace);
    if (replace != null) {
      newAxiom += replace;
    } else {
      newAxiom += ch;
    }
  }

  angle = -angle;
  Debug.Log ("Axiom Length: " + newAxiom.Length);
  return newAxiom;
}

void FixedUpdate() {
  int length = axiom.Length;

  for (int i = 0; i < 200; i++) {
    if (index < axiom.Length) {
      char c = axiom[index];
      if (c == 'F' || c == 'A' || c == 'B') {
        Vector2 newPoint = NewPoint(currentPoint, stepLength, angle);
        DrawLine (new Line(currentPoint, newPoint), colors[colIndex % 3]);
        colIndex++;
        currentPoint = newPoint;
      } else if (c == '-') {
        angle -= angleStep;
      } else if (c == '+') {
        angle += angleStep;
      }
      index++;
    }   
  }
  texture2D.Apply();
}


In An Evening of Code, Procedural, Unity Tags unity, indiedev, gamedev, procedural
← Refining TerrainAn Evening of Code: Koch Snowflake →

Latest

Unlikely Objects
Fractal Plant in Godot
about a year ago
Binary Tree in Godot
about a year ago
Sierpinski Triangle in Godot
about a year ago
Re-visiting some old code
about a year ago
React - Starting a New Project
about 3 years ago
Satsuma Tosser
about 4 years ago
1HGJ #002: Deeper and Deeper
about 7 years ago
1HGJ #001: Telekinetic Bomberman Rush
about 7 years ago
Migrating to NSPersistentContainer
about 7 years ago
Nonoku - SpriteKit Shader
about 7 years ago

Powered by Squarespace