Generating random terrains in Enu 0.2
Enu is an interactive programming sandbox that helps learn programming through game creation. The author made it with children convenience in mind so it’s great for teaching kids programming.
Just days ago, a long-awaited Enu 0.2 was released. It boasts multiple improvements compared to the previous version but the biggest for me is the documentation. Finally, the great tool Enu is has the docs it deserves, beautiful and comprehensive.
To celebrate the new release, I decided to try and build a game with Enu and publish a tutorial on the process.
The Game #
The game I’m having in mind is a capture the flag kinda game. I’m seeing a bumpy terrain covered with trees, with monsters walking around, and a randomly placed flag. The player needs to capture the flag and not get caught my the monsters. I’d like to implement the game mechanics where the monster can see or otherwise sense the player and when it does, it rushes to the player. The player has to sneak around to remain unnoticed.
Terrain #
We’ll start with generating our terrain. This is the topic of this tutorial.
Let’s first list some basic ideas:
- the terrain consists of randomly placed hills
- a hill consists of layers placed one upon another
- a hill’s height is linearly proportionate to its diameter, which is random
- a layer is a solid circle
The plan is to implement layer first, than hill, and finally terrain with many random hills.
In Enu, there are two ways to implement something reusable: prototype and command. I’ve tried using prototypes first but it turns out they’re hard to keep track of, so we’ll use commands, which are basically just functions.
Place a regular block, select the Code tool, and click on the block. No we’re ready to start coding.
Layer #
The code for layer looks like this:
# command definition
- layer(diameter = 10):
for circleDiameter in 1..diameter:
# convert diameter to circle length we don't care about accuracy,
# so assume the length roughly equals 3 times the diameter
let stepCount = circleDiameter * 3
# to position the circle center at the starting point,
# move one radius to the left first
left circleDiameter / 2
stepCount.times:
# draw the actual circle bit and turn slightly
forward 1
turn 360 / stepCount
# return to the starting point
right circleDiameter / 2
Hill #
To draw a hill, we’ll draw a number of layer one upon another:
- hill(diameter = 10):
var
layerDiameter = diameter
layerNum = 1
# start underground
down 1
while layerDiameter > 0:
# move to the desired height
up 1
# draw a layer there
layer(layerDiameter)
# decrease the diameter with every layer
layerDiameter -= layerNum
# go to the next layer
inc layerNum
# return to the starting point
down(layerNum-2)
Terrain #
A terrain is a random arrangement of random hills:
- randomTerrain(hillCount = 10, minHillDiameter = 5, maxHillDiameter = 60, minDistance = 30, maxDistance = 60):
hillCount.times(hillNum):
# draw a hill
hill(minHillDiameter..maxHillDiameter)
# turn anywhere
turn(-180..180)
# get underground
down 1
# move the new position
forward(minDistance..maxDistance)
# get back to the ground
up 1
Result #
Finally, we call the randomTerrain
command and get a random terrain:
# speed things up
speed = 100
# draw
randomTerrain(hillCount = 30)