Create A Tree Generator (in less than 100 lines of V)

A fond believer in learning by doing. Loves to try out new languages in the world of computing
Want to optimize your JS-code(s)? Welp, I've got you covered! https://hasty.dev 🧑💻
Want to tweet your commits? https://gitbird.dev 🐦 It's dead I think, honestly, I haven't been keeping up with the death of the blue-bird-site 🤐
A Magical Tree Generator
In this post, I'll show you how to do what you've always wanted. Namely a magical tree generator - and of course, learn V in the making of this.
This will all be done in exactly 90 lines of code.
V
First of all, what is V? This is easy, I'll just simply refer you to my other post: https://madco.me/code-in-v
Tree Generator
Let's get started!
As V is much like Go in it's code, we need a module and some imports
module main
import gg
import gx
import math
import rand
import sokol.sapp
These are just a few things V provides for us to use, and that we'll need.
ggis our drawing tool, think of it as the plain ol' plaint buddy from MS.gxis the a plalette of colours for us to use.mathis forPI.randto gain some randomness. We do not want the same thing multiple times.sokol.sapp, to be honest, I have yet to figure this.
const (
win_width = 600
win_height = 600
)
This will be the size of our canvas.
struct App {
mut:
gg &gg.Context
}
This struct will be in charge of drawing.
struct Branch {
mut:
x f32
y f32
cx f32
cy f32
rad f32
len f32
}
This struct, however, just simply a branch of our tree.
fn main() {
mut app := &App{
gg: 0
}
app.gg = gg.new_context({
bg_color: gx.rgba(255, 155, 155, 0)
width: win_width
height: win_height
use_ortho: true
create_window: true
window_title: 'Tree Vv'
keydown_fn: frame
user_data: app
})
app.gg.run()
}
This is more fun, but to keep this simple, just know that this will create our paint brush.
fn frame(c sapp.KeyCode, m sapp.Modifier, app &App) {
b1 := &Branch{
x: f32(win_width / 2)
y: f32(win_height)
cx: f32(win_width / 2)
cy: f32(win_height)
rad: f32(math.pi / 2)
len: rand.f32n(100)
}
app.gg.begin()
app.draw_branch(b1, 1)
app.draw_branch(b1, -1)
app.gg.end()
}
The frame is where the fun happens! It's in charge of generating a new tree for every key-press.
We start with a simple branch, on X & Y positions, along with the old postions CX & CY.
We also generate the start radians, and a random length of the branch.
fn (app &App) draw_branch(b &Branch, mul f32) {
cos := f32(math.cos(b.rad))
sin := f32(math.sin(b.rad))
x_tmp := b.cx - cos * b.len
y_tmp := b.cy - sin * b.len
app.gg.draw_line(b.cx, b.cy, x_tmp, y_tmp, gx.black)
rad := rand.f32n(math.pi / 4)
b1 := &Branch{
x: b.cx
y: b.cy
cx: x_tmp
cy: y_tmp
rad: b.rad + rad * mul
len: b.len - rand.f32n(25)
}
if b1.len > 10 {
app.draw_branch(b1, 1)
app.draw_branch(b1, -1)
} else {
app.gg.draw_circle(b1.cx, b1.cy, 4, gx.white)
}
}
Here we simply calulate the branch's new X & Y positions. Re-use our old to as the new CX & CY.
We then draw a new line. Randomizes a number between 0 and PI / 4, and generaets a new rbanch from those values.
If the length of our branch is then above 10, we does the exact same thing again, becasue insanity, right?
If the branch's length is below or equals to 10 we draw a leaf.
Easy, right? The complete code is below my plug.
Shameless Plug
Before you turn to the complete code, please take a look at this beauty!
I'd recommend you to click on the image to gain access to a tree placeholder!
Our Generator
The generator we've just created will of not be as beautiful as the above out-put, but it's a start nonetheless.

Complete Code
module main
import gg
import gx
import math
import rand
import sokol.sapp
const (
win_width = 600
win_height = 600
)
struct App {
mut:
gg &gg.Context
}
struct Branch {
mut:
x f32
y f32
cx f32
cy f32
rad f32
len f32
}
fn main() {
mut app := &App{
gg: 0
}
app.gg = gg.new_context({
bg_color: gx.rgba(255, 155, 155, 0)
width: win_width
height: win_height
use_ortho: true
create_window: true
window_title: 'Tree Vv'
keydown_fn: frame
user_data: app
})
app.gg.run()
}
fn frame(c sapp.KeyCode, m sapp.Modifier, app &App) {
b1 := &Branch{
x: f32(win_width / 2)
y: f32(win_height)
cx: f32(win_width / 2)
cy: f32(win_height)
rad: f32(math.pi / 2)
len: rand.f32n(100)
}
app.gg.begin()
app.draw_branch(b1, 1)
app.draw_branch(b1, -1)
app.gg.end()
}
fn (app &App) draw_branch(b &Branch, mul f32) {
cos := f32(math.cos(b.rad))
sin := f32(math.sin(b.rad))
x_tmp := b.cx - cos * b.len
y_tmp := b.cy - sin * b.len
app.gg.draw_line(b.cx, b.cy, x_tmp, y_tmp, gx.black)
rad := rand.f32n(math.pi / 4)
b1 := &Branch{
x: b.cx
y: b.cy
cx: x_tmp
cy: y_tmp
rad: b.rad + rad * mul
len: b.len - rand.f32n(25)
}
if b1.len > 10 {
app.draw_branch(b1, 1)
app.draw_branch(b1, -1)
} else {
app.gg.draw_circle(b1.cx, b1.cy, 4, gx.white)
}
}
{ Best, Mads Bram Cordes }





