實驗12 密閉球
簡介
本實驗將引入極坐標(biāo)的速度表示方式來解決物體與任意面碰撞的問題。這種方式在后面會用矢量代替。這種方式雖然可以降一個維度,二維降為一維,三維降為二維,但是這種方式無法方便地解決碰撞等物理問題,而且在使用極坐標(biāo)時描繪坐標(biāo)的位置也要相應(yīng)地改成極坐標(biāo)的形式,這樣才能體現(xiàn)其優(yōu)勢,然而Canvas的所有API都是基于X軸和Y軸的,所以后面會統(tǒng)一使用矢量計算來代替,本實驗只是拓展一下知識面。在進行實驗?zāi)M之前,先來了解幾種數(shù)學(xué)上的基本概念。
笛卡兒坐標(biāo)系
笛卡兒坐標(biāo)系是直角坐標(biāo)系和斜角坐標(biāo)系的統(tǒng)稱,如圖2-15所示。相交于原點的兩條數(shù)軸構(gòu)成了平面放射坐標(biāo)系。如兩條數(shù)軸上的度量單位相等,則稱此放射坐標(biāo)系為笛卡兒坐標(biāo)系。兩條數(shù)軸互相垂直的笛卡兒坐標(biāo)系稱為笛卡兒直角坐標(biāo)系,否則稱為笛卡兒斜角坐標(biāo)系。笛卡兒坐標(biāo)表示了點在空間中的位置,但卻和直角坐標(biāo)有區(qū)別,兩種坐標(biāo)可以相互轉(zhuǎn)換。

圖2-15 笛卡兒坐標(biāo)系
用一組數(shù)(x,y)可以表示平面上的一個點,平面上的一個點也可以用一組兩個有順序的數(shù)來表示,這就是坐標(biāo)系的雛形。
極坐標(biāo)系
在數(shù)學(xué)中,極坐標(biāo)系是一個二維坐標(biāo)系統(tǒng)。該坐標(biāo)系統(tǒng)中的點由一個夾角和一段相對于中心點——極點(相當(dāng)于較為熟知的直角坐標(biāo)系中的原點)的距離來表示,如圖2-16所示。極坐標(biāo)系的應(yīng)用領(lǐng)域十分廣泛,包括數(shù)學(xué)、物理、工程、航海及機器人領(lǐng)域。當(dāng)兩點間的關(guān)系用夾角和距離很容易表示時,極坐標(biāo)系便顯得尤為有用;而在平面直角坐標(biāo)系中,這樣的關(guān)系就只能使用三角函數(shù)來表示了。對于很多類型的曲線,極坐標(biāo)方程是最簡單的表達形式,甚至對于某些曲線來說,只有極坐標(biāo)方程能夠表示。

圖2-16 極坐標(biāo)系
極坐標(biāo)系到直角坐標(biāo)系的轉(zhuǎn)化
極坐標(biāo)系中的兩個坐標(biāo)ρ和θ可以由下面的公式轉(zhuǎn)換為直角坐標(biāo)系下的坐標(biāo)值:
x=ρcosθ
y=ρsinθ
由此,可得到從直角坐標(biāo)系中x和y兩坐標(biāo)計算出極坐標(biāo)系下的坐標(biāo):

其中,x不等于0,在x=0的情況下,若y為正數(shù),則θ=90°(π/2 rad);若y為負數(shù),則θ=270° (3π/2 rad)。
極坐標(biāo)速度
在前幾個實驗中,使用以下方法定義小球:
var ball={ x: 100, y: 100, r: 15, vx: 100, vy: 100 };
定義速度的方法是利用笛卡兒坐標(biāo)系,分別定義X軸方向的速度和Y軸方向的速度,這樣就表示了在二維坐標(biāo)系當(dāng)中的速度。利用極坐標(biāo)的方式同樣也可以定義小球的速度:
var ball={ x: 100, y: 100, r: 15, v: 100 * Math.sqrt(2), direction: Math.PI / 4 };
代碼中,定義了小球的速度v和方向direction。這兩種定義方式,達到的效果是完全一樣的,vx和vy也同樣為100。
密閉球
與任意軸碰撞的實驗最適合的場景就是密閉球。圖2-17就是該實驗場景的描繪。

圖2-17 在密閉球中與任意軸碰撞的實驗
要讓運動的小球不脫離圓形范圍,所要做的就是碰撞檢測和碰撞之后小球運動方向的改變。這里假設(shè)所有碰撞是完全彈性碰撞,沒有任何速度損失。只要求出碰撞時,大圓的圓心和小球的圓心連線與水平X軸的夾角,速度方向的變化角度就迎刃而解了。
用極坐標(biāo)的形式描述速度:
for (var i=0; i <6; i++) { var ball={ position: new Vector2(300, 250), r: 10, v: getRandomNumber(50, 200), direction: (getRandomNumber(0, 360) / 360) * 2 * Math.PI }; balls.push(ball); }
初始化一個大球:
var bigCircularity={ position: new Vector2(300, 250), r: 190 }
碰撞檢測:
if (Math.round(Math.pow(balls[i].position.x-bigCircularity.position.x, 2)+Math.pow(bigCircularity. position.y-balls[i].position.y, 2)) >=Math.round(Math.pow(bigCircularity.r-balls[i].r, 2))) { } // 大圓圓心到小球圓心的距離大于或等于(R-r)×(R-r)時,代表碰撞。
碰撞后,小球運動方向的改變:
var cD=balls[i].direction; var step=Math.acos((balls[i].position.x-bigCircularity.posit ion.x)/ distance); if (balls[i].position.y > bigCircularity.position.y) { balls[i].direction=-cD-Math.PI+2 * step; }else { balls[i].direction=-cD+Math.PI-2 * step; }
其中,step為大圓的圓心到小球的圓心這條線段與水平X軸的夾角。
運行代碼,其效果如圖2-18所示。

圖2-18 Canvas密閉球模擬
當(dāng)然,可以通過增加小球的數(shù)量,減小小球的半徑來制作很炫的粒子系統(tǒng)效果。
for (var i=0; i < 1200; i++) { var ball={ position: new Vector2(300, 250), r: 1, v: getRandomNumber(50, 200), direction: (getRandomNumber(0, 360) / 360) * 2 * Math.PI }; balls.push(ball); }
其效果如圖2-19所示。

圖2-19 粒子系統(tǒng)模擬1
或者改變所有小球(即爆炸點)的起始位置:
for (var i=0; i < 1200; i++) { var ball={ position: new Vector2(300, 150), r: 1, v: getRandomNumber(50, 200), direction: (getRandomNumber(0, 360) / 360) * 2 * Math.PI }; balls.push(ball); }
其效果如圖2-20所示。

圖2-20 粒子系統(tǒng)模擬2
- Bootstrap響應(yīng)式Web開發(fā)
- 網(wǎng)頁設(shè)計與制作:HTML+CSS+JavaScript標(biāo)準(zhǔn)教程
- Vue.js Web開發(fā)案例教程(在線實訓(xùn)版)
- Web前端開發(fā)精品課 HTML與CSS進階教程
- jQuery Web開發(fā)案例教程(在線實訓(xùn)版)
- 網(wǎng)頁設(shè)計與制作Dreamweaver CS6標(biāo)準(zhǔn)教程(第2版)
- Illustrator平面設(shè)計180例五步通
- Photoshop網(wǎng)頁設(shè)計從入門到精通
- 中文版Dreamweaver CC+Flash CC+Photoshop CC網(wǎng)頁設(shè)計實戰(zhàn)視頻教程
- 《練就職場功夫熊貓》
- 秩序之美:網(wǎng)頁中的網(wǎng)格設(shè)計
- 寬帶接入技術(shù)
- 從零開始讀懂Web3
- Dreamweaver,F(xiàn)lash,F(xiàn)ireworks網(wǎng)頁設(shè)計百練成精(CS3版)
- 新編網(wǎng)站設(shè)計與網(wǎng)頁制作(Dreamweaver CC + Photoshop CC + Flash CC版)從入門到精通