LibGDX: 如何在不修改原始向量的情况下将向量与标量相乘? (Java 游戏中的简单重力系统)
LibGDX: how do I multiply vector with scalar without modifing original vector? (simple gravity system in Java game)
我目前正在使用 LibGDX 在我的游戏中实现一个简单的重力系统。但是,我发现向量与向量相乘和向量与标量相乘的方式有点不同。
在 Unity 中,我会像这样实现重力:
public Vector3 velocity;
public Vector3 acceleration;
private void FixedUpdate()
{
transform.position += velocity*Time.fixedDeltaTime;
Vector3 force = Physics.gravity*GetComponent<Rigidbody>().mass;
acceleration = force/GetComponent<Rigidbody>().mass;
velocity = velocity + acceleration*Time.fixedDeltaTime;
}
}
向量乘法非常简单。
在 LibGDX 中,我正在尝试以下操作:
import com.badlogic.gdx.math.Vector2;
final protected Vector2 _gravity = new Vector2(0f, -9.82f);
final protected float _mass = 1f;
protected Vector2 _velocity;
protected Vector2 _acceleration;
public void Update(float deltaTime)
{
// Transform is a class containing a Vector2 called Position
Transform.Position.add(_velocity.scl(deltaTime));
Vector2 force = _gravity.scl(_mass);
_acceleration = force.scl(1f/_mass);
_velocity = _velocity.add(_acceleration.scl(deltaTime));
System.out.println(_velocity);
// _velocity gets smaller and smaller and finally hits 0.
}
这个不行,因为Vector2的scl()方法直接改变了vector本身,在[=34的Vector2class中可以看出=]:
public Vector2 scl (float scalar) {
x *= scalar;
y *= scalar;
return this;
}
我假设我希望它成为 return 一个 new Vector2,而不是直接改变向量本身。
我该怎么做?还是我完全错了? LibGDX 中是否有更简单的方法使用“*”运算符将向量与标量相乘?
您可以尝试在缩放之前复制向量,如下所示:
new Vector2(_gravity).scl(_mass);
Vector2 force = _gravity.cpy().scl(_mass);
cpy()
方法 returns 向量的副本,因此您最终将副本与 _mass
而不是原始向量相乘。
与使用 new Vector2()
创建副本相比,此解决方案的轻微优势在于它无需修改即可适用于任何矢量维度。
方法(和其他方法)不创建新向量的原因是为了避免产生垃圾。创建垃圾将导致垃圾收集器清理,这可能(并且将会)导致 hick ups。对于游戏,您通常希望避免频繁出现问题。
所以,如果是只需要一次的东西,那么使用cpy()
方法或者new
关键字是可以的。但是对于经常调用的方法(比如你的更新方法),你真的想避免这种情况。相反,您可以使用成员向量。
final Vector2 force = new Vector2();
public void update(float delta) {
...
force.set(_gravity).scl(mass);
...
}
请注意,对于 position += velocity * time
等操作,您可以使用 mulAdd
方法。
position.mulAdd(velocity, deltaTime);
我目前正在使用 LibGDX 在我的游戏中实现一个简单的重力系统。但是,我发现向量与向量相乘和向量与标量相乘的方式有点不同。
在 Unity 中,我会像这样实现重力:
public Vector3 velocity;
public Vector3 acceleration;
private void FixedUpdate()
{
transform.position += velocity*Time.fixedDeltaTime;
Vector3 force = Physics.gravity*GetComponent<Rigidbody>().mass;
acceleration = force/GetComponent<Rigidbody>().mass;
velocity = velocity + acceleration*Time.fixedDeltaTime;
}
}
向量乘法非常简单。
在 LibGDX 中,我正在尝试以下操作:
import com.badlogic.gdx.math.Vector2;
final protected Vector2 _gravity = new Vector2(0f, -9.82f);
final protected float _mass = 1f;
protected Vector2 _velocity;
protected Vector2 _acceleration;
public void Update(float deltaTime)
{
// Transform is a class containing a Vector2 called Position
Transform.Position.add(_velocity.scl(deltaTime));
Vector2 force = _gravity.scl(_mass);
_acceleration = force.scl(1f/_mass);
_velocity = _velocity.add(_acceleration.scl(deltaTime));
System.out.println(_velocity);
// _velocity gets smaller and smaller and finally hits 0.
}
这个不行,因为Vector2的scl()方法直接改变了vector本身,在[=34的Vector2class中可以看出=]:
public Vector2 scl (float scalar) {
x *= scalar;
y *= scalar;
return this;
}
我假设我希望它成为 return 一个 new Vector2,而不是直接改变向量本身。
我该怎么做?还是我完全错了? LibGDX 中是否有更简单的方法使用“*”运算符将向量与标量相乘?
您可以尝试在缩放之前复制向量,如下所示:
new Vector2(_gravity).scl(_mass);
Vector2 force = _gravity.cpy().scl(_mass);
cpy()
方法 returns 向量的副本,因此您最终将副本与 _mass
而不是原始向量相乘。
与使用 new Vector2()
创建副本相比,此解决方案的轻微优势在于它无需修改即可适用于任何矢量维度。
方法(和其他方法)不创建新向量的原因是为了避免产生垃圾。创建垃圾将导致垃圾收集器清理,这可能(并且将会)导致 hick ups。对于游戏,您通常希望避免频繁出现问题。
所以,如果是只需要一次的东西,那么使用cpy()
方法或者new
关键字是可以的。但是对于经常调用的方法(比如你的更新方法),你真的想避免这种情况。相反,您可以使用成员向量。
final Vector2 force = new Vector2();
public void update(float delta) {
...
force.set(_gravity).scl(mass);
...
}
请注意,对于 position += velocity * time
等操作,您可以使用 mulAdd
方法。
position.mulAdd(velocity, deltaTime);