弹药.js三.js - 计算投篮所需的力矢量



我正在用三个.js和弹药.js来构建一个篮球游戏。(启用3d)

篮筐/篮筐和球的位置不断变化(AR),因此击球必须是动态和相对的。

我需要计算应用于球的力矢量,以获得成功的击球。在游戏中,用户将滑动射击,这将影响"完美射击"的力量。

我看过许多用于计算轨迹、弹道学等的代码和方程式示例,并且我一直在将它们从 C# 转换为 JavaScript,因为我在 Unity 论坛上找到的许多脚本都在 Unity 论坛上。

我需要一个计算初始力矢量的函数3 使用球的位置、篮筐的位置、球的质量和重力应用于球。初始角度或最大高度(终端速度y)也必须传递给这个函数,正如我在我看到的所有方程和计算器中注意到的那样。

编辑:

因此,我将在Unity论坛(下图)上找到的脚本转换为Javascript/Three.js:

function getBallVelocity( ballPos, rimPos, angleDegrees, gravity ) {

const Vector3 = {
forward: new THREE.Vector3( 0, 0, 1 ),
up: new THREE.Vector3( 0, 1, 0 )
};

// Get angle in radians, from angleDegrees argument
const angle = THREE.Math.degToRad( angleDegrees );

gravity = gravity || 9.81;
// Positions of this object and the target on the same plane
const planarRimPos  = new THREE.Vector3( rimPos.x, 0, rimPos.z ),
planarBallPos = new THREE.Vector3( ballPos.x, 0, ballPos.z );
// Planar distance between objects
const distance = planarRimPos.distanceTo( planarBallPos );

// Distance along the y axis between objects
const yOffset = rimPos.y - ballPos.y;

// Calculate velocity 
const initialVelocity = ( 1 / Math.cos( angle ) ) * Math.sqrt( ( 0.5 * gravity * Math.pow( distance, 2 ) ) / ( distance * Math.tan( angle ) + yOffset ) ),
velocity = new THREE.Quaternion( 0, initialVelocity * Math.sin( angle ), initialVelocity * Math.cos( angle ) );
// Rotate our velocity to match the direction between the two objects
const planarPosDifferenceBetweenObjects = planarRimPos.sub( planarBallPos ),
angleBetweenObjects = Vector3.forward.angleTo( planarPosDifferenceBetweenObjects ),
angleUpRotated = new THREE.Quaternion().setFromAxisAngle( Vector3.up, angleBetweenObjects ),
finalVelocity = angleUpRotated.multiply( velocity );

return finalVelocity;
}

我是这样发号施令的:

const velocity = getBallVelocity( ball.position, rim.position, 45 );
ball.body.applyForce( velocity.x, velocity.y, velocity.z )

它拍摄的方向错误,非常虚弱。我假设我在函数结束时没有正确进行旋转,弱点可能是由于没有质量倍增。球的质量是 2,所以我认为我应该将一些 Y 值乘以 2??不知道:(

以下是我尝试转换的 C# 脚本:

using UnityEngine;
using System.Collections;

public class ProjectileFire : MonoBehaviour {

[SerializeField]
Transform target;

[SerializeField]
float initialAngle;

void Start () {
var rigid = GetComponent<Rigidbody>();

Vector3 p = target.position;

float gravity = Physics.gravity.magnitude;
// Selected angle in radians
float angle = initialAngle * Mathf.Deg2Rad;

// Positions of this object and the target on the same plane
Vector3 planarTarget = new Vector3(p.x, 0, p.z);
Vector3 planarPostion = new Vector3(transform.position.x, 0, transform.position.z);

// Planar distance between objects
float distance = Vector3.Distance(planarTarget, planarPostion);
// Distance along the y axis between objects
float yOffset = transform.position.y - p.y;

float initialVelocity = (1 / Mathf.Cos(angle)) * Mathf.Sqrt((0.5f * gravity * Mathf.Pow(distance, 2)) / (distance * Mathf.Tan(angle) + yOffset));

Vector3 velocity = new Vector3(0, initialVelocity * Mathf.Sin(angle), initialVelocity * Mathf.Cos(angle));

// Rotate our velocity to match the direction between the two objects
float angleBetweenObjects = Vector3.Angle(Vector3.forward, planarTarget - planarPostion);
Vector3 finalVelocity = Quaternion.AngleAxis(angleBetweenObjects, Vector3.up) * velocity;

// Fire!
rigid.velocity = finalVelocity;

// Alternative way:
// rigid.AddForce(finalVelocity * rigid.mass, ForceMode.Impulse);
}
}

谢谢!

好的,三件事:

  1. 速度的旋转不起作用。改用了 atan2。
  2. 我需要切换减去的 Y 轴点以获得 yOffset
  3. 我需要使用 .setVelocity(x, y, z)
  4. 而不是 .applyForce(x, y, z)

这是最终脚本,希望对某人有所帮助!

static getBallVelocity( ballPos, rimPos, angleDegrees, gravity ){

// Get angle in radians, from angleDegrees argument
const angle = THREE.Math.degToRad( angleDegrees );

gravity = gravity || 9.81;

// Positions of this object and the target on the same plane
const planarRimPos  = new THREE.Vector3( rimPos.x, 0, rimPos.z ),
planarBallPos = new THREE.Vector3( ballPos.x, 0, ballPos.z );

// Planar distance between objects
const distance = planarRimPos.distanceTo( planarBallPos );

// Distance along the y axis between objects
const yOffset = ballPos.y - rimPos.y;

// Calculate velocity
const initialVelocity = ( 1 / Math.cos( angle ) ) * Math.sqrt( ( 0.5 * gravity * Math.pow( distance, 2 ) ) / ( distance * Math.tan( angle ) + yOffset ) ),
velocity = new THREE.Vector3( 0, initialVelocity * Math.sin( angle ), initialVelocity * Math.cos( angle ) );

// Rotate our velocity to match the direction between the two objects
const dy = planarRimPos.x - planarBallPos.x,
dx = planarRimPos.z - planarBallPos.z,
theta = Math.atan2( dy, dx ),
finalVelocity = velocity.applyAxisAngle( PopAShotAR.Vector3.up, theta )

return finalVelocity;
}

最新更新