1. 程式人生 > 其它 >python之turtle使用:畫一顆美美噠的樹

python之turtle使用:畫一顆美美噠的樹

關於工具介紹這裡小生就不贅述了,這裡附上個人覺得最詳細的文件地址:https://docs.python.org/zh-cn/3/library/turtle.html?highlight=turtle#turtle.TurtleScreen
看效果圖:

以上就是小生犧牲午休時間搗鼓出來的~雖然不是辣麼好看,但是還是想跟大夥分享一下,進入正題。
程式碼主要分為兩部分:樹程式碼部分,地上花瓣部分

樹程式碼部分

其實程式碼很簡單,主要是我們得知道如何去實現那些關鍵點(我知道這是廢話,但是我總得說點什麼湊字數...):
1,樹幹應該是越往上越細 - 即畫筆越往上 size 尺寸越小

2,枝幹越往上越短 - 枝幹延伸的長度

3,枝幹會分叉 - 即遞迴事件繼續執行的入口

4,枝幹分叉的角度 - 畫筆偏移度

4,要長點什麼 - 遞迴事件的出口

滿足了以上幾點,這棵樹看起來才會正常一點(或者說符合大眾觀念)。總的來說,我們需要一個點來決定遞迴事件

的入口和出口,這裡我用分叉次數來決定,當然還可以用延伸長度等或一個變數,只要我們能找到出入條件,看程式碼:

 1 # 畫樹方法: n為枝幹延伸次數,l為枝幹延伸長度
 2 def drawTree(n, l):
 3     pendown()
 4     # 設定畫筆顏色 - 枝幹顏色
 5     pencolor('#5d3c3c')
 6     # 畫筆尺寸
 7     pensize( n / 1.5)
 8     # 延伸長度
 9     forward(l)
10     # 根據 n 判斷是否繼續遞迴延伸枝幹 或 結束本分支延伸
11     if n > 0:
12         # dr 為畫筆順時針偏移度,dl 為畫筆逆時針偏移度
13         dr = randint(30, 40)
14         dl =  randint(30, 40)
15 
16         # 本次延伸長度:每一次隨機減少延伸長度(所以也可以根據 l 來設定 pensize等)
17         move = l * (random() * 0.4 + 0.5)
18 
19         # 順時針偏移 dr
20         right(dr)
21         # 遞迴呼叫自身,剩餘延伸次數 -1
22         drawTree(n - 1, move)
23         # 因為上面順時針偏移了 dr,所以順時針的偏移度加上逆時針偏移度:dr + dl 才是分叉實際偏移度
24         left(dr + dl)
25         drawTree(n - 1, move)
26         # 順時針偏移dl,回到畫筆原指向
27         right(dl)
28     else:
29         # 本分支延伸結束,呼叫畫花朵方法
30         drawPetal(3)
31     # 提起畫筆
32     penup()
33     # 回到開始延伸的位置
34     backward(l)

花朵程式碼:

枝幹完成指定分叉次數後,為了好看一點,即需要長點什麼,如程式碼:

 1 # 花朵繪畫方法: n 為花朵半徑(其實就是圓半徑...)
 2 def drawPetal(n):
 3     # 指定顏色模式為 rgb 模式
 4     colormode(255)
 5     # 隨機生成 rgb 色值
 6     r = randint(200, 255)
 7     g = randint(8, 158)
 8     b = randint(8, 158)
 9 
10     # 畫圓並填充顏色
11     begin_fill()
12     fillcolor(r, g, b)
13     pencolor(r, g, b)
14     circle(n)
15     end_fill()

到這裡如果只是為了畫一棵樹,那我們的工作已經基本完成了,當然我們需要一個啟動方法:

def run():
    # 設定畫布比例: 相對顯示屏
    setup(1.0, 1.0)

    penup()
    # 移動到座標 (-50, -150)
    goto(-50, -150)
    # 逆時針旋轉90度,使畫筆指向正上方
    left(90)
    pendown()

    # 隱藏畫筆
    hideturtle()

    # 是否追蹤繪畫過程:即是否一步一步顯示繪畫過程
    tracer(False)

    # 呼叫樹方法
    drawTree(13, 150)

將上訴程式碼複製到編輯器裡,在呼叫 run()方法,一棵樹神奇的樹就會出現了(假設你已經安裝了python執行環境)。

讓我們再給它灑上一些花瓣,這裡花瓣的位置小生將它放在樹起始點下方,其實你完全可以隨意指定位置和範圍以及大小

來展示一張飄落的效果(我已經看過了,很好看):

 1 # 花瓣位置生成: m 為花瓣數量,x y 決定繪畫花瓣初始位置
 2 # 這裡我將花瓣初始位置設定為樹起點位置附近
 3 def petalPlace(m, x, y):
 4     penup()
 5     goto(x, y)
 6     pendown()
 7     setheading(0)
 8     tracer(False)
 9     for i in range(m):
10         # 起始點畫一朵
11         if i == 0:
12             drawPetal(5)
13         else:
14             penup()
15             goto(x, y)
16             # a 為下一朵花瓣水平方向相對起始點距離
17             a = randint(20, 400)
18             # b 為下一朵花瓣垂直方向相對起始點距離
19             b = randint(-50, 50)
20 
21             # 將畫筆移動相應距離
22             forward(a)
23             left(90)
24             forward(b)
25             right(90)
26             pendown()
27 
28             # 呼叫花瓣繪畫方法
29             drawPetal(5)

到這裡我們的所有程式碼已經完成,下面是所有程式碼(已去掉註釋):

 1 from turtle import *
 2 from random import *
 3 
 4 # 畫樹方法
 5 def drawTree(n, l):
 6     pendown()
 7     pencolor('#5d3c3c')
 8     pensize( n / 1.5)
 9     forward(l)
10     if n > 0:
11         dr = randint(30, 40)
12         dl =  randint(30, 40)
13         move = l * (random() * 0.4 + 0.5)
14         right(dr)
15         drawTree(n - 1, move)
16         left(dr + dl)
17         drawTree(n - 1, move)
18         right(dl)
19     else:
20         drawPetal(3)
21     penup()
22     backward(l)
23 
24 # 花瓣位置生成
25 def petalPlace(m, x, y):
26     penup()
27     goto(x, y)
28     pendown()
29     setheading(0)
30     tracer(False)
31     for i in range(m):
32         if i == 0:
33             drawPetal(5)
34         else:
35             penup()
36             goto(x, y)
37             a = randint(20, 400)
38             b = randint(-50, 50)
39             forward(a)
40             left(90)
41             forward(b)
42             right(90)
43             pendown()
44             drawPetal(5)
45 
46 # 花朵繪畫方法
47 def drawPetal(n):
48     colormode(255)
49     r = randint(200, 255)
50     g = randint(8, 158)
51     b = randint(8, 158)
52     begin_fill()
53     fillcolor(r, g, b)
54     pencolor(r, g, b)
55     circle(n)
56     end_fill()
57 
58 # 啟動方法
59 def run():
60     setup(1.0, 1.0)
61     penup()
62     goto(-50, -150)
63     left(90)
64     pendown()
65     hideturtle()
66     tracer(False)
67     drawTree(13, 150)
68     petalPlace(160, -100, -150)
69 
70 run()
71 done()

值得注意的是,因為我們使用了很多隨機生成的值,所以每一次生成的樹都一樣,也就是你說,我們可以造一片森林,
有了上面的程式碼,我們需要補充的已經很少了:

大致思路就是隨機生成樹的起始點,再呼叫我們上面的方法就可以了,當然為了美觀,部分數值是需要細調的,
最起碼每棵樹下面的花瓣這個方法不需要了,我們可以換成給整個區域的樹加上花瓣飄落效果,這裡給個森林例子

(沒有改花瓣):

 1 # m 對應生成樹的數量
 2 def run(m):
 3     setup(1.0, 1.0)
 4     for i in range(m):
 5         penup()
 6         x = randint(-500, 500)
 7         y = randint(-300, 300)
 8         goto(x ,y)
 9         left(90)
10         tracer(False)
11         drawTree(10, 150)
12         petalPlace(100, x, y)