#### Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

# L-System Generator

Posts: 192

Hey all,
Today I was reading about the upcoming game No Man's Sky and its procedural generation techniques, and I basically read up on every one. I was intruiged by L-Systems, so I decided to first make my own "turtle" graphics drawing thing(which basically generates one continuous line as in the Logo programming language I believe). Then, I coded my own l-system interpreter. If you don't know what an L-System is, here is the wikipedia page: https://en.m.wikipedia.org/wiki/L-system
The code is quite neat for me, but still a bit hard to understand but its also really hard to explain. The wikipedia page should explain some of it, but not my thought process but here's the code anyway(I have it pre-loaded with the Sierpinski's Triangle Fractal but it can generate any of the ones on the wikipedia page and more with a bit of fiddling):

``````--# lSystem
lSystem = class()

function lSystem:init(var,const,axiom,rules,n,turtle,funcs)
-- you can accept and set parameters here
self.vars = var
self.consts = const
self.cur = axiom
self.finds = {}
self.replaces = {}
self.funcs = funcs
for i,ii in string.gmatch(rules, "(["..self.vars.."]+)>(["..self.vars..self.consts.."]+)") do
print(i,ii)
table.insert(self.finds,i)
table.insert(self.replaces,ii)
end
local count = 0

while count < n do
local newString = ""
for i=1,string.len(self.cur),1 do
local replaced = false
for a,b in pairs(self.finds) do
if string.sub(self.cur,i,i) == b and replaced == false then
newString = newString .. self.replaces[a]
replaced = true
break
else

end
end
if replaced == false then
newString = newString .. string.sub(self.cur,i,i)
end
end
self.cur = newString
count = count + 1
end
print(self.cur)
self:interpret(self.cur)
end

function lSystem:interpret(s)
-- Codea does not automatically call this method
for i=1,string.len(s),1 do
for a,v in pairs(self.funcs) do
if string.sub(s,i,i) == v.char then
v.func()
end
end
end
end

function lSystem:touched(touch)
-- Codea does not automatically call this method
end

--# Main
-- Turtle Graphics

-- Use this function to perform your initial setup
function setup()
print("Hello World!")
t = Turtle(0,0)
t:rotate(0)
local funcs = {
{char = "a",func = function() t:moveForward(10) end},
{char = "b",func = function() t:moveForward(10) end},
{char = "+",func = function() t:rotate(60) end},
{char = "-",func = function() t:rotate(-60) end},
}
l = lSystem("ab","+-","a","a>+b-a-b+;b>-a+b+a-",8,t,funcs)
end

-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(255, 255, 255, 255)

scale(1/3)
t:draw()
end

function replaceString(s,i,p)
return string.sub(s,1,i-1) .. p .. string.sub(s,i+1)
end

--# Turtle
Turtle = class()

function Turtle:init(x,y)
-- you can accept and set parameters here
self.pos = vec2(x,y)
self.stack = {}
self.rot = 0
self.lines = {}
end

function Turtle:draw()
-- Codea does not automatically call this method
stroke(0)
for i,v in pairs(self.lines) do
strokeWidth(5)
line(v.p1.x,v.p1.y,v.p2.x,v.p2.y)
end
end

function Turtle:move(vec)
local opos = self.pos
local newpos = self.pos + vec
self.pos = self.pos + vec
end

function Turtle:moveForward(amount)
local opos = self.pos
local newpos = self.pos + vec2(amount,0):rotate(math.rad(self.rot))
end

function Turtle:rotate(amount)
self.rot = self.rot + amount
end

function Turtle:push()
table.insert(self.stack, {pos = vec2(self.pos.x,self.pos.y),rot = self.rot})
end

function Turtle:pop()
self.pos = self.stack[#self.stack].pos
self.rot = self.stack[#self.stack].rot
table.remove(self.stack,#self.stack)
end

self.lines[#self.lines+1] = {p1 = pos1,p2 = pos2}
end

``````
Tagged:

• Mod
Posts: 10,053

@TheSolderKing Nice program. I haven't looked thru the code yet, but I was wondering what it would take to add a parameter to vary the draw speed. It might be interesting to watch it drawing the triangle.

• Mod
edited March 2016 Posts: 10,053

@TheSolderKing I didn't know what an L-System was, so I went to the link you showed. I found it very interesting. I was still determined to show the Sierpinski Triangle as it was created, but I didn't want to try and figure out your code. I wrote my own version for the triangle. I was able to show it as it was being created, but I didn't like the way it was do it. The drawing was jumping around because of the translates, so I removed that part of the code. But anyways, here's my code which draws the triangle when complete. I'm still determined to have it draw the triangle as its being created.

``````displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)

function setup()
size=4
size1=size
tab={a="+b-a-b+",b="-a+b+a-"}
str="a"
for t=1,8 do
str1=""
for z=1,#str do
v=string.sub(str,z,z)
t=tab[tostring(v)]
if t==nil then
str1=str1..v
else
str1=str1..t
end
end
str=str1
end
stroke(255)
strokeWidth(2)
end

function draw()
background(0)
translate(100,40)
scale(.8)
for z=1,#str do
v=string.sub(str,z,z)
if v=="a" or v=="b" then
size=size1
line(0,0,size,0)
else
translate(size,0)
size=0
if v=="+" then
rotate(60)
end
if v=="-" then
rotate(-60)
end
end
end
end
``````
• Mod
Posts: 10,053

Here's a version that shows the Sierpinski Triangle being created. You can display the parameter window to change the speed as it's running.

``````displayMode(FULLSCREEN)

function setup()
parameter.integer("speed",1,20,20)
size=3
size1=size
tab={a="+b-a-b+",b="-a+b+a-"}
str="a"
for t=1,8 do
str1=""
for z=1,#str do
v=string.sub(str,z,z)
t=tab[tostring(v)]
if t==nil then
str1=str1..v
else
str1=str1..t
end
end
str=str1
end
stroke(255)
strokeWidth(2)
c=0
end

function draw()
background(0)
if c<#str then
c=c+speed*2
end
translate(150,80)
for z=1,c do
v=string.sub(str,z,z)
if v=="a" or v=="b" then
size=size1
line(0,0,size,0)
else
translate(size,0)
size=0
if v=="+" then
rotate(60)
elseif v=="-" then
rotate(-60)
end
end
end
end
``````
• Posts: 84
Interesting stuff, I read the wiki article. I really like the 'butterfly effect' nature of it. This would be great in combination with CodeaCraft!
• Posts: 186

That's pretty interesting, thanks for sharing all!

@TheSolderKing
Could you link to the article about the no mans sky techniques?

• Posts: 192
• Posts: 186

Ah I should've checked wikipedia myself, many thanks!

I wrote a couple of procedural plant/tree/bush functions that I'd like to improve with this. Very cool technique!