Log In  


I'm a newbie and I'd like to learn procedural generation to add things like dynamic grass and vegetation to my game. I really like how Zep created the swaying trees in the fireflies gif for the 0.2.4 release, so I thought I'd examine his code. But I'm having some trouble parsing it because the function seems to call itself. I'm assuming this is what's called a recursive function.

How does the function know to stop calling itself? I'm guessing the if statement regarding the l variable terminates it but how? I'm confused because, to my mind, logically, there should be an "else" following the if/then to call the function again. What is the point of the return command?

Here is his function for drawing the trees:

function tree(x,y,a,l)
 if (l<3) then

  for ii=0,3 do
   circfill(
	   x+rnd(8)-rnd(8),
	   y+ii,
    1,lcol[4-ii])
  end

  return

 end

 local x1=x+cos(a)*l
 local y1=y+sin(a)*l

 local q=l/8
 local col=l>8 and 13 or 0
 for xx=-q,q do
  line(x+xx,y,x1+xx,y1,col)
  col=0
 end

 local d=
 (
  cos(t()/3+x1/50)+
  cos(t()/4+x1/70)
 )/500

 tree(x1,y1,d+a-.04-rnd(0.04),l*(.9-rnd(0.2)))
 tree(x1,y1,d+a+.04+rnd(0.04),l*(.9-rnd(0.2)))

end

Thanks!



1

The return statement is what stops the recursion. It does this by preventing the code from reaching the part with the function calls.

The way the cycle works is that each call makes a branch (or the truck in the initial call), then makes two more calls, each with a shorter length for the branch. Once a branch is short enough, it no longer makes any more calls. The cycle ends when all the new branches are too short.

Note that actual order the calls go will be all the first branches, then second branch of the second to last call, an so on. This is because the function calls do have to finish before the caller can move on.

Regarding recursion in general, one way to think of it is the interpreter is writing notes on index cards about where it is right now in the code and what values things have, then sticking those cards onto a stack. The interpreter then goes back through the stack starting at the top and resolving 1 card at a time, but with the frustration that the cards are still potentially allowed to add more cards (at least until the interpreter runs out of memory).


Thanks for the detailed explanation @kimiyoribaka



[Please log in to post a comment]