此篇接續第一篇:https://ithelp.ithome.com.tw/articles/10269980
接下來我們把造樹的步驟拆分成骨幹、畫樹枝、樹葉,而到目前為止只完成了一個很陽春的骨幹。
在這個步驟中,可以加入一些隨機元素,思考邏輯如下:
按照這個邏輯,我們依序設計以下變數並添加到昨天的建構式:
if(times > 0){
let endX = x + r * Math.cos(theta / 180 * Math.PI);
let endY = y + r * Math.sin(theta / 180 * Math.PI);
let shrink = 0.65 + random(0.1); // from 0.55 to 0.65
let diff = random(0.3) - 0.15; // +-0.15
this.son =
[new Tree(this, endX, endY, r * (shrink - diff), theta+30, times-1),
new Tree(this, endX, endY, r * (shrink + diff), theta-30, times-1)];
}
diff 越少看起來越完美,越多則越容易有枝葉營養不良
shrink 越少整個樹越小
這樣一來,就可以看到現在樹枝的分岔更加的寫實跟蜿蜒曲折了:
為了未來添加風力的效果,今天一邊研究一邊設計了兩個參數a和b,原本的分枝角度各為正負30度,
a: 若讓兩個分枝都增加角度,就能讓分枝逆時針綣曲,反之順時針
b: 若讓兩個分枝的正負角度更大,能讓分枝更加擴散,反之則是集中
並且為此製作一個函式,可以根據ab值計算座標:
let Tree = function(father, x, y, r, theta, times){
// ......
// 省略
// ......
this.Transform = function(index){
if(this.father){
this.theta = this.father.theta + 30 * ((index == 0)?(a+b+1):(a-b-1));
this.startX = this.father.endX;
this.startY = this.father.endY;
this.endX = this.startX + this.r * Math.cos(this.theta / 180 * Math.PI);
this.endY = this.startY + this.r * Math.sin(this.theta / 180 * Math.PI);
}
// 我是遞迴唷!還記得我嗎?
if(this.son) this.son.forEach((branch, index) => branch.Transform(index));
};
}
都是用上一根樹枝來一節節往下算,用this.father的末端座標當原點來計算(r, theta)極座標位置
也因此一開始造樹的時候第一枝要傳入undefined給father
canvas.addEventListener('click', Recreate);
function Recreate(e){
let Rect = canvas.getBoundingClientRect();
myTree = new Tree(undefined, WIDTH/2, HEIGHT, HEIGHT/6, -90, 10);
// 或者,讓它從滑鼠的位置長出來
// let x = (e.pageX - Rect.left) * RATIO;
// let y = (e.pageY - Rect.top) * RATIO;
// myTree = new Tree(undefined, x, y, HEIGHT/6, -90, 10);
}
每次點擊滑鼠時重新產生樹
接著再加上滑鼠的移動事件監聽,讓ab值隨著滑鼠移動改變:
canvas.addEventListener('mousemove', GetMouse);
function GetMouse(e) {
let Rect = canvas.getBoundingClientRect();
a = ((e.pageX - Rect.left) * RATIO - WIDTH/2) / (WIDTH/2);
b = ((e.pageY - Rect.top) * RATIO - HEIGHT/2) / (HEIGHT/2);
myTree.Transform(); // 呼叫改變樹形狀的方法
}
如此一來,便能看到樹的形狀豐富的改變,是很棒的研究材料呢!
(到這邊本來有一個demo,不過我加了一些有的沒得進去,就爆炸了ww,等我修好明天再一起po)
(因為沒有備份,然後又想加入第二章的緩衝函式,製作風力效果,然後就出事了阿北,拍謝拉~)
有了真實的骨幹終於能開始進一步囉!明天會講到:Y型樹枝、樹枝的顏色、樹的成長、樹葉
此時大家有沒有發現一件事:Draw和Transform這兩個函式不只一組!我們來算一下初始條件設10,總共會有2^10=1024個樹枝,那麼,按照我們這個物件的寫法,就會有1024組Draw、Transform函式,天哪!太多了吧,摁確實就是這麼多,翻開每一個樹枝的物件,都可以看到裡面紮紮實實的擁有這兩組函式,雖然跟其他人都長得不一樣。
那麼,其實有一個方式可以解決,用類別函式Classes來造樹枝!(大約就在...第四章節一邊做遊戲會一邊說明)