2014-07-12 31 views
1

這是我依賴這個網站多年後的第一個問題!帆布水/ blob物理與紋理的圓形路徑?

無論如何,我想完成類似這種效果:

http://www.flashmonkey.co.uk/html5/wave-physics/

不過的圓形軌道上,而不是地平線。本質上,屏幕中心會出現一個浮動的圓圈/斑點,它會對鼠標交互作出反應。我不在尋找的是重力,或者圓圈在屏幕周圍反射 - 只有表面漣漪。

如果可能,我想將靜態紋理應用於形狀,這是否有可能?我對帆布完全陌生!

我已經嘗試從以下鏈接循環的代碼從上面的例子替換一些代碼,非常有限的成功:

http://www.html5canvastutorials.com/tutorials/html5-canvas-circles/

如果只有它是那麼容易:)

有任何想法嗎?

提前致謝!

回答

2

我試圖弄清楚波模擬如何使用View Source和JavaScript控制檯工作。它工作正常,但拋出了一些JS錯誤。另外,看起來物理更新與render()方法中的渲染糾纏在一起。

這裏是我發現有關代碼:

mouseMove()方法基於鼠標位置的波產生的干擾,創造鼠標周圍的峯值。變量target是需要更新的粒子的索引,它是從鼠標pos計算出來的。

if (particle && mouseY > particle.y) { 
    var speed = mouseY - storeY; 

    particles[target - 2].vy = speed/6; 
    particles[target - 1].vy = speed/5; 
    particles[target].vy = speed/3; 
    particles[target + 1].vy = speed/5; 
    particles[target + 2].vy = speed/6; 

    storeY = mouseY; 
} 

然後,顆粒周圍target被更新。我發現的問題是,它沒有邊界檢查,即當target == 0時它可能有particles[-1]。如果發生這種情況,會拋出異常,方法調用結束,但代碼不會停止。

render()方法首先更新粒子位置,然後呈現波。

下面是其物理代碼:

for (var u = particles.length - 1; u >= 0; --u) { 
    var fExtensionY = 0; 
    var fForceY = 0; 

    if (u > 0) { 
     fExtensionY = particles[u - 1].y - particles[u].y - springs[u - 1].iLengthY; 
     fForceY += -fK * fExtensionY; 
    } 

    if (u < particles.length - 1) { 
     fExtensionY = particles[u].y - particles[u + 1].y - springs[u].iLengthY; 
     fForceY += fK * fExtensionY; 
    } 

    fExtensionY = particles[u].y - particles[u].origY; 
    fForceY += fK/15 * fExtensionY; 

    particles[u].ay = -fForceY/particles[u].mass; 
    particles[u].vy += particles[u].ay; 
    particles[u].ypos += particles[u].vy; 
    particles[u].vy /= 1.04; 
} 

基本上,它是爲Hooke's Law通過它們之間的彈簧聯粒子鏈。對於每個粒子u,它將前一個和下一個粒子的吸引力(if語句檢查它們是否可用)添加到變量fForceY。我不完全瞭解springs陣列的用途。在最後四行中,它計算加速度(力/質量),更新速度(加速度),然後定位(加速度),最後將速度降低1.04(摩擦)。

物理學更新後,代碼呈現波:

context.clearRect(0, 0, stageWidth, stageHeight); 
context.fillStyle = color; 
context.beginPath(); 

for (u = 0; u < particles.length; u++) { 
    ... 
} 

... 
context.closePath(); 
context.fill(); 

我不解釋,你需要閱讀畫布的教程,瞭解它。


這裏有一些想法上手,請注意,我沒有測試這些代碼。

要修改繪製圓形波的代碼,我們需要引入一個polar coordinate system,其中粒子的x -position是圓圈中的角度,而y-定位距離中心的距離。這裏我們應該使用thetar,但它需要大量的重構。我們稍後會談談轉型。

mouseMove():從鼠標的位置計算粒子指數在屏幕上極座標,並確保干擾迴繞:

定義函數(外mouseMove(),我們再次需要這個版本)

function wrapAround(i, a) { return (i + a.length) % a.length; } 

然後改變

particles[target - 2] --> particles[wrapAround(target - 2, particles)] 
particles[target - 1] --> particles[wrapAround(target - 1, particles)] 
... 

模運算符不這項工作,但我加了particles.length所以我不modulo一個負數。

render():確保強制計算環繞,因此我們需要再次使用wrapAround函數。我們可以剝去的兩個if語句:

fExtensionY = particles[wrapAround(u - 1, particles)].y - particles[u].y - springs[wrapAround(u - 1, springs)].iLengthY; 
    fForceY += -fK * fExtensionY; 

    fExtensionY = particles[u].y - particles[wrapAround(u + 1, particles)].y - springs[warpAround(u, springs)].iLengthY; 
    fForceY += fK * fExtensionY; 

這裏是到目前爲止的結果中的jsfiddle:注意波從另一個側面傳播。 http://jsfiddle.net/DM68M/

完成之後,最難的部分就是將它們渲染成一個圓。爲此,我們需要座標變換函數,將粒子的(x, y)視爲(angle in the circle, distance from center),並且我們還需要在mouseMove()中對鼠標交互進行逆變換。

function particleCoordsToScreenCoords(particleX, particleY) { 
    return [ radiusFactor * particleY * Math.cos(particleX/angleFactor), 
      radiusFactor * particleY * Math.sin(particleX/angleFactor) ]; 
} 

function screenCoordsToParticleCoords(screenX, screenY) { 
    // something involving Math.atan2 and Math.sqrt 
} 

其中...Factor變量需要單獨確定。 angleFactor是在粒子陣列中發現的最高x位置上的兩個pi

然後,在提供給context.lineTo, context.arc的座標中,使用particleCoordsToScreenCoords來轉換座標。