Adding trees to random terrains in Enu 0.2

Read the first part →

In this tutorial, I’ll add some trees to the random terrain that we’ve created last time. For the impatient, here is the complete code: https://gist.github.com/moigagoo/d40a76beee5a62d2fec7679ebc033730

As before, let’s first write down the basic ideas:

Tree #

Here’s the command that draws a tree:

- tree(height = 5, width = 3):  
  let
# trees use their own colors so we need to preserve the original one
    defaultColor = color

# a tree is roughly half trunk and half crown
    trunkHeight = height div 2
    crownHeight = height - trunkHeight

# we'll build from the top down, so first we got up
  up height - 1

  height.times(stepNum):

  # if we're still within the crown height, draw green layers
    if stepNum < crownHeight:
      color = green
      layer 1..width

# if we're on the last crown level, switch to black
    if stepNum == crownHeight - 1:
      color = black

# go to the next level   
    down 1

# revert the color
  color = defaultColor

Hill #

Now we need to incorporate trees in hill generation. We’ll use a param called treeDensity to define how dense we want the resulting forest to be. When we draw a layer, we’ll try and place trees depending on the layer diameter and treeDensity.

# introduce tree-related arguments
- hill(diameter = 10, treeDensity = 3, treeMinHeight = 2, treeMaxHeight = 10, treeMinWidth = 2, treeMaxWidth = 10):
  var
    layerDiameter = diameter
    layerNum = 1

  down 1

  while layerDiameter > 0:
    up 1
    layer(layerDiameter)

# this is the new part where we plant the trees

# the number 5 was chosen subjectively through trial and error
    (layerDiameter div 5).times:

# we give each tree a `treeDensity` chance to get planted
      if treeDensity in 10:

# we want trees to be placed randomly on the layer edge

# turn to the random direction
        turn(-180..180)

# go to the edge
        forward layerDiameter / 2

# get out of the layer
        up 1

# plant the tree
        tree(treeMinHeight..treeMaxHeight, treeMinWidth..treeMaxWidth)

# return to the layer center
        back layerDiameter / 2

    layerDiameter -= layerNum
    inc layerNum

  down(layerNum-2)

Terrain #

Finally, we need to add tree-related params to our terrain generation command and pass them to the hill generating command.

# add the same arguments that we added earlier to `hill``
- randomTerrain(hillCount = 10, minHillDiameter = 5, maxHillDiameter = 60, minDistance = 30, maxDistance = 60, treeDensity = 5, treeMinHeight = 2, treeMaxHeight = 30, treeMinWidth = 5, treeMaxWidth = 10):

  hillCount.times(hillNum):
    down 1
    forward(minDistance..maxDistance)
    up 1

# pass the tree-related params to `hill`
    hill(minHillDiameter..maxHillDiameter, treeDensity, treeMinHeight, treeMaxHeight, treeMinWidth, treeMaxWidth)
    turn(-180..180)


speed = 100

randomTerrain(30)

Here’s the end result:

 
3
Kudos
 
3
Kudos

Now read this

How to Hire Your First Tech Writer

I’ve been a tech writer for several years before switching to a management job. Having been both tech writer and manager, I’ve built a strong vision of what a good tech writer should be able to do. I’m writing this vision down in the... Continue →