Reputation: 25
So I'm working on this L system, and I have it set up like this:
private const string axiom = "X";
private string currentString = string.Empty;
I am calling a method called Generate.
private void Generate() { currentString = axiom; StringBuilder sb = new StringBuilder();for(int i=0; i < iterations; i++) {
//loop through current string and create a new string based on the rules
foreach (char c in currentString){
sb.Append(rules.ContainsKey(c) ? rules[c] : c.ToString());
}
//Set currentString to the new string we just generated.
currentString = sb.ToString();
sb = new StringBuilder();
}
And then I'm using a foreach loop and a switch statement to go through the string, and generate the tree:
foreach (char c in currentString) {
switch(c){
case 'F':
//Draw a straight line
Vector3 initialPosition = transform.position;
transform.Translate(Vector3.up * length);
GameObject treeSegment;
if (currentString[(c + 1) % currentString.Length] == 'X' ||
currentString[(c + 4) % currentString.Length] == 'F' && currentString[(c + 5) % currentString.Length] == 'X')
{
treeSegment = Instantiate(leaf);
Debug.Log("LEAF!");
}
else{
treeSegment = Instantiate(branch);
}
treeSegment.GetComponent<LineRenderer>().SetPosition(0, initialPosition);
treeSegment.GetComponent<LineRenderer>().SetPosition(1, transform.position);
break;
case 'X':
//does nothing, generate more Fs
break;
case '+':
//Rotates clockwise
transform.Rotate(Vector3.back * angle);
break;
case '-':
//Rotates counter-clockwise
transform.Rotate(Vector3.forward * angle);
break;
case '[':
//Save current transform info
transformStack.Push(new TransformInfo(){
position = transform.position,
rotation = transform.rotation
});
break;
case ']':
//Return to our previously saved transform info
TransformInfo ti = transformStack.Pop();
transform.position = ti.position;
transform.rotation = ti.rotation;
break;
default:
throw new InvalidOperationException("Invalid L-tree operation");
}
}
The tutorial which I'm basing this off checks for position to place branches and leaves like this:
for (int i = 0; i < currentString.Length; i++)
{
switch (currentString[i])
{
case 'F':
initialPosition = transform.position;
transform.Translate(Vector3.up * 2 * length);
GameObject fLine = currentString[(i + 1) % currentString.Length] == 'X' || currentString[(i + 3) % currentString.Length] == 'F' && currentString[(i + 4) % currentString.Length] == 'X' ? Instantiate(leaf) : Instantiate(branch);
I have no idea what's happening here. I don't get why he's adding seemingly random numbers and then using modulus.
Any help at all will be appreciated.
Upvotes: 0
Views: 36
Reputation: 90659
In the original one you are accessing next characters! Like a look ahead with wrap around
currentString[(i + 1) % currentString.Length]
basically goes to the next index but if the index reaches currentString.Length
it is wrapped around thanks to the %
and becomes 0
again.
As an example lets say your string looks like
0 1 2 3 4 5
A B C D E F
|
| current index = 3
Then (i + 4) % length
would mean 7 % 6
= 1
0 1 2 3 4 5
A B C D E F
|
| new index after shifting 4 with wrap around = 1
So the entire line
GameObject fLine = currentString[(i + 1) % currentString.Length] == 'X' || currentString[(i + 3) % currentString.Length] == 'F' && currentString[(i + 4) % currentString.Length] == 'X' ? Instantiate(leaf) : Instantiate(branch);
Basically translates to
F
) - from the switch
X
F
X
HOWEVER
In your code you are doing
currentString[(c + 1) % currentString.Length]
BUT c
is the actual value of a character like e.g. A
== 65
.
It makes absolutely no sense to use this as an index in your original string!
=> You want to stick to a for
loop in order to have the actual current index of your chracter
Upvotes: 0