二維非對心彈性碰撞的算法


該算法適合常見的二維完全彈性碰撞的場合,支持對心碰撞(正碰)和非對心碰撞(斜碰),不考慮碰撞過程中的機械能損耗,不考慮物體表面摩擦以及恢復系數。


/*
* this是自身對象,sp是碰撞的對象
* this.m   質量
* this.r   半徑
* this.vx  水平速度
* this.vy  豎直速度
* 為了便於理解,代碼未經優化!
*/

collide(sp) {
    if (this.isCollideWith(sp)) {
        
        // 利用彈性碰撞公式計算水平、豎直方向上的速度分量 let vx
= this.vx let vy = this.vy this.vx = ((this.m - sp.m) * this.vx + 2 * sp.m * sp.vx) / (this.m + sp.m) this.vy = ((this.m - sp.m) * this.vy + 2 * sp.m * sp.vy) / (this.m + sp.m) sp.vx = (2 * this.m * vx + (sp.m - this.m) * sp.vx) / (this.m + sp.m) sp.vy = (2 * this.m * vy + (sp.m - this.m) * sp.vy) / (this.m + sp.m)
        // 關鍵!在速度突變的情況下(例如碰壁反彈,或者另一物體被擠壓以至於無法移動),必須防止位置重疊的情況出現
        // nextXPos和nextYPos是提前判斷二者下一幀的位置。若下一幀位置重疊,則反彈。 let ax
= this.nextXPos() let ay = this.nextYPos() let bx = sp.nextXPos() let by = sp.nextYPos() if (Math.sqrt((ax - bx) ** 2 + (ay - by) ** 2) < (this.r + sp.r)) { let agl = 0  // 反彈方向相對屏幕坐標系的角度 if (this.x != sp.x) agl = Math.atan((this.y - sp.y) / (this.x - sp.x))
          // 反彈的速度的方向需根據二者位置來確定 let v
= Math.sqrt(this.vx ** 2 + this.vy ** 2) this.vx = v * Math.cos(agl) * (this.x > sp.x ? 1 : -1) this.vy = v * Math.sin(agl) * (this.y > sp.y ? 1 : -1) v = Math.sqrt(sp.vx ** 2 + sp.vy ** 2) sp.vx = v * Math.cos(agl) * (sp.x > this.x ? 1 : -1) sp.vy = v * Math.sin(agl) * (sp.y > this.y ? 1 : -1)} }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM