用原生 JS 寫一個簡易版的臺球
前言
突發(fā)奇想想用JS寫一個臺球小游戲,磕磕碰碰之后,算是實現(xiàn)了一個簡易版的。用到的知識主要是通過遞歸來調(diào)用requestAnimationFrame,以及一些簡單的三角函數(shù)角度計算。requestAnimationFrame就是一個JS動畫幀,簡單來說和定時器有點相似,但是動畫呈現(xiàn)出來的效果比定時器更流暢,性能更好。
1、繪制游戲元素
CSS
html
JS
2、球桿跟隨鼠標(biāo)旋轉(zhuǎn)
先獲取鼠標(biāo)在頁面的坐標(biāo),然后減去球心的坐標(biāo),就得到了一個相對坐標(biāo)。然后把球心當(dāng)成原點,計算出鼠標(biāo)相對球心的角度,最后把這個角度賦值給球桿的transform屬性,就可以實現(xiàn)球桿跟隨鼠標(biāo)旋轉(zhuǎn)的效果了
3、球桿的擊球動畫
球桿其實是由 3 個盒子組成的,最外面的大盒子來控制球桿的旋轉(zhuǎn),大盒子里面有兩個盒子 gan2 和 gan3, gan3 這個盒子用來放球桿的圖片。gan2 這個盒子是看不到的,它負(fù)責(zé)把球桿向外面撐開。所以球桿的動畫就很簡單了,只要增加和減少 gan2 盒子的寬,就能實現(xiàn)球桿的伸縮了。
實現(xiàn)動畫就是用尾遞歸來重復(fù)調(diào)用 requestAnimationFrame 函數(shù)。
4、球桿擊球后,母球的移動
母球的擊球動畫同樣是通過尾遞歸來重復(fù)調(diào)用 requestAnimationFrame 函數(shù),但是涉及到墻壁反彈,以及撞擊子秋,母球的移動函數(shù)的參數(shù)會復(fù)雜一點。
母球移動的速度和距離,是通過i這個變量來控制的,這個函數(shù)每調(diào)用一次,i 會遞減。x 和 y 這兩個參數(shù)會接收一個 -1 到 1 之間的值,起到一個方向系數(shù)的效果,通過參數(shù)把球桿的撞擊方向傳遞進(jìn)來。碰到邊界之后,就把對應(yīng)的系數(shù)取負(fù),然后用新系數(shù)執(zhí)行移動函數(shù),就能起到反彈的效果了。
5、母球撞擊子球移動
這是最麻煩的一步,撞擊后兩個球的運動軌跡都會發(fā)生變化。只考慮最普通的撞擊,子球的運動方向應(yīng)該是撞擊點與子球球心這條直線的方向,這個比較好計算。母球的撞擊后的方向應(yīng)該是以撞擊點的那條切線進(jìn)行反彈,三角函數(shù)幾乎忘光了,這個我也不知道怎么計算了,所以用了個簡易的算法,就和撞墻壁一樣直接反彈,這樣會導(dǎo)致某些角度下,母球撞擊之后的方向不正常。
把這個撞擊判斷加到母球移動的函數(shù)里面,然后再補充一個子球的移動函數(shù),整個代碼就寫完了
總結(jié)
這個小游戲?qū)崿F(xiàn)的并不完美,因為用到了太多的遞歸,很多細(xì)節(jié)方面不好控制,球的運動軌跡也很難計算,在某些角度下會出現(xiàn)BUG。球雖然是圓的,但是它的盒子是正方形,所以撞擊有的時候會看著很奇怪。移動的函數(shù)寫的也有缺陷,它不能復(fù)用,如果想添加多個球,函數(shù)就得改。
這個破產(chǎn)版的臺球主要就是寫著玩一玩,嘗試了一下JS動畫的實現(xiàn) , 不喜勿噴。