如何實現高拋平拋發射?從拋物線說起!Cocos Creator

遊戲中經常會遇到拋物線軌跡問題,為此研究如何運用數學物理知識,實現高拋平拋效果。文章底部獲取完整代碼!

效果預覽:

如何實現高拋平拋發射?從拋物線說起!Cocos Creator


先確認已知條件:

  • 起點發射速度大小 V
  • 重力加速 G
  • 起始點與經過點

需要求出:

  • 發射角度 a

對於拋物線運動,可以分兩個方向去看。水平方向,勻速直線運動。垂直方向勻加速運動。所以可以得出以下式子:

如何實現高拋平拋發射?從拋物線說起!Cocos Creator

在把 t 和 v_y 帶入最後一個式子,化簡整理後,可以得到一個關於 tan a 的一元二次方程。

如何實現高拋平拋發射?從拋物線說起!Cocos Creator

再根據一元二次方程通解公式,可以解出角度的 tan 值。

如何實現高拋平拋發射?從拋物線說起!Cocos Creator

接著使用反三角函數,求出角度的值。需要注意的是,反三角函數 arctan 的值域是 (-PI/2, PI/2) 。這個是第一、四象限的值,在二、三象限的時候要加 180 度(PI) 。也就是說,經過點在發射點左側時,角度要加180度(PI) 。

如何實現高拋平拋發射?從拋物線說起!Cocos Creator

角度大的正好是高拋效果,而角度小的是平拋效果。

接著看看代碼吧。先通過兩點的座標確定水平位移 s 和垂直位移 h 。接著根據上面化簡的一元二次方程求出 tan 值。最後求出角度。

<code>const s = location.x - START_POS.x;
const h = location.y - START_POS.y;
// a*t^2 + b*t + c = 0
const a = G * s / (2 * V * V);
const b = 1;
const c = a - h / s;
const delta = b * b - 4 * a * c;
if (delta >= 0) {
// 一元二次方程求根公式
const t1 = (-b + Math.sqrt(delta)) / (2 * a); // 平拋 tan 值
const t2 = (-b - Math.sqrt(delta)) / (2 * a); // 高拋 tan 值
// 二、四象限角度要加 180
const alpha1 = Math.atan(t1) + (s < 0 ? Math.PI : 0);
const alpha2 = Math.atan(t2) + (s < 0 ? Math.PI : 0);
}
/<code>

這裡用了物理引擎,初始速度需要兩個方向,只需要根據發射角度和總速度大小,就可以求出兩個分量速度大小。

<code>const v_x_1 = Math.cos(alpha1) * V;
const v_y_1 = Math.sin(alpha1) * V;
const v_x_2 = Math.cos(alpha2) * V;
const v_y_2 = Math.sin(alpha2) * V;
// 低拋線速度 保存起來
this._linearVelocity_1.x = v_x_1;
this._linearVelocity_1.y = v_y_1;
// 高拋線速度 保存起來
this._linearVelocity_2.x = v_x_2;
this._linearVelocity_2.y = v_y_2;
/<code>

只有線性速度還不行,還要調整各個弓箭的角度。這個角度可以根據剛體的線性速度算出。每幀修改弓箭剛體節點的角度即可。

<code>// 計算夾角 

const angle = rigidBody.linearVelocity.clone().signAngle(cc.v2(1, 0));
rigidBody.node.rotation = angle * 180 / Math.PI;
/<code>

如何控制箭不停發射?添加一個定時器就可以不停發射弓箭了。

<code>this.schedule(this.fireArrow, 0.5, cc.macro.REPEAT_FOREVER);
/<code>

根據不同的發射方式,選擇不同的發射線性速度就可以了。

<code>private _index = 0;
private fireArrow() {
const linearVelocity = this.toggle_arrow.isChecked ? this._linearVelocity_2.clone() : this._linearVelocity_1.clone()
const rigidBody_arrow = this._all_arrows[this._index++ % this._all_arrows.length];
rigidBody_arrow.node.setPosition(START_POS);
rigidBody_arrow.linearVelocity = linearVelocity;
}
/<code>

以上為白玉無冰使用 Cocos Creator 開發"平拋高拋發射"的技術分享。完整代碼在公重號白玉無冰。有想法歡迎留言!如果這篇對你有點幫助,歡迎分享給身邊的朋友。



分享到:


相關文章: