我刚刚开始在libgdx中使用3D进行游戏。我已经知道如何绘制基本的Model
,我试图用CameraController
来玩。现在我要创建FirstPersonCamera
或FirstPersonCameraController
。我考虑过延长PerspectiveCamera
并为其添加MyMovingObject target
。 MyMovingObject
会保留x, y, z position
,其中y
是一个常量值,因为此刻我无法移动up/down
。所以我的动作基本上是2D。 MyMovingObject
还会存储其left/right rotation
/ moving direction
所需的xSpeed, zSpeed
。但是Player
也应该能够向上和向下查看,MyMovingObject
并不真正需要这种向上/向下旋转,因为它只会更改视图而不会更改其他属性。所以我不确定我是否采取了正确的方式
我希望能够使用W,A,S,D
向前,向左,向右,向后,并使用鼠标向左旋转。此外,我希望通过使用鼠标来上下搜索,就像在大多数First Person
游戏中一样
我应该使用其他方式,而不是通过扩展PerspectiveCamera
创建自己的相机吗?
或者这种方法是否合适,我只需将上/下旋转存储在MyMovingObject
中,如果视图只需要它?
或者用W,A,S,D and mouse
控制相机并根据相机的位置和旋转更新MyMovingObject
的位置会更好吗?
我希望你明白我的意思。解释它似乎有点复杂(至少对我而言)。
编辑:我现在正在为我的NPC和播放器使用Vector3 direction
,Vector3 position
和Vector3 size
。我通过这样做来计算速度:xSpeed = direction.x / (direction.x + direction.z) * speed;
对于zSpeed来说是相同的。通过这样做,我“过滤”了它的y值,我只得到x和y的百分比。唯一的问题是,当我直视x
和z
时0
。我可以通过使用UpVecotr
来解决这个问题,当我进行“俯仰旋转”时,它会旋转。但我怎么旋转他?我需要在侧面矢量旋转它。感谢
编辑:现在轮换和移动工作(请参阅我的回答),但我对“俯仰旋转”的限制存在很大问题。我正在使用:if (direction.y < 0.9 && angle > 1) doPitchRotation(); else if (direction.y > -0.9 && angle < 1) doPitchRotation();
所以如果我向下旋转并且我仍然至少看低于-0.9 y它只是不执行旋转。但究竟发生了什么:我旋转到-0.9然后旋转到Y轴周围,另一边它旋转起来,即使我把我的摩斯向下移动。你能解释一下原因吗?当我向下看时,为什么Y轴会翻转?
编辑:现在可以使用了。似乎我的upVector有时会得到一些错误的值。对于陆基凸轮,您还可以使用Y轴和方向矢量的交叉产品。不需要upVector。
答案 0 :(得分:5)
嘿谢谢分享this链接。我发现它非常有用。 这是关于旋转陆基相机的代码,它似乎没有问题。
private int mouseX = 0;
private int mouseY = 0;
private float rotSpeed = 0.2f;
@Override
public boolean mouseMoved(int screenX, int screenY) {
int magX = Math.abs(mouseX - screenX);
int magY = Math.abs(mouseY - screenY);
if (mouseX > screenX) {
cam.rotate(Vector3.Y, 1 * magX * rotSpeed);
cam.update();
}
if (mouseX < screenX) {
cam.rotate(Vector3.Y, -1 * magX * rotSpeed);
cam.update();
}
if (mouseY < screenY) {
if (cam.direction.y > -0.965)
cam.rotate(cam.direction.cpy().crs(Vector3.Y), -1 * magY * rotSpeed);
cam.update();
}
if (mouseY > screenY) {
if (cam.direction.y < 0.965)
cam.rotate(cam.direction.cpy().crs(Vector3.Y), 1 * magY * rotSpeed);
cam.update();
}
mouseX = screenX;
mouseY = screenY;
return false;
}
适用于陆基相机。如果你想制作一个flightcontroll相机,你必须在cam.direction.crs(cam.up)
周围做一个音高旋转。而不是使用Vector3.cpy()
我会存储Vector3 help
,它会获取这些临时值,因为Vector3.cpy()
会创建一个新的Vector3
,并且每个渲染循环都会执行此操作。
对于flightcontroll相机,您还需要添加roll
个旋转,并在yaw
向量周围进行cam.up
旋转。
答案 1 :(得分:3)
我知道这个问题已经有了很好的答案。但是我对所选答案有些疑问。我只是想帮助那些正在寻找相同解决方案的人。 我注意到所选答案有些奇怪的行为。我没有把Y exis保持为正常状态。这对fps来说当然非常重要。所以这个并不完美,但我想把它放在这里。
// put into the create() method.
Gdx.input.setInputProcessor(new InputProcessor() {
private int dragX, dragY;
float rotateSpeed = 0.2f;
// dont' forget to override other methods.
@Override
public boolean mouseMoved(int screenX, int screenY) {
Vector3 direction = cam.direction.cpy();
// rotating on the y axis
float x = dragX -screenX;
// change this Vector3.y with cam.up if you have a dynamic up.
cam.rotate(Vector3.Y,x * rotateSpeed);
// rotating on the x and z axis is different
float y = (float) Math.sin( (double)(dragY -screenY)/180f);
if (Math.abs(cam.direction.y + y * (rotateSpeed*5.0f))< 0.9) {
cam.direction.y += y * (rotateSpeed*5.0f) ;
}
cam.update();
dragX = screenX;
dragY = screenY;
return true;
}
});
注意:不要使用任何相机控制器
注2:这可能会派上用场:Gdx.input.setCursorCatched(true);
编辑:我只想分享我用来改变相机位置的步行功能。当W
键关闭时,forward
为真。当密钥出现时forward
为假。其他方向具有相同的原则。要检测密钥是否向上和向上,请使用上面代码中的InputProcessor
这在二维空间(X-Z轴)中产生运动。我们消除Y轴时,摄像机的方向不会改变运动方向。方向。
现在必须将相机对准天空(与地面成90度角),方向矢量的长度不固定为1.0f
。因此不会有任何移动速度的损失。
为了测试这一点,我上下旋转相机(向前和向后移动鼠标),方向矢量的x和z值没有变化。因此,当方向矢量的y轴被消除时,我们有一个2d方向矢量,它不会受到摄像机Y角的影响。
private void walking(float timeElapsed) {
float speed = movementSpeed;
if ((forward | back) & (right | left)) {
speed /= Math.sqrt(2);
}
System.out.println(speed);
if (forward) {
Vector3 v = cam.direction.cpy();
v.y = 0f;
v.x *= speed * timeElapsed;
v.z *= speed * timeElapsed;
cam.translate(v);
cam.update();
}
if (back) {
Vector3 v = cam.direction.cpy();
v.y = 0f;
v.x = -v.x;
v.z = -v.z;
v.x *= speed * timeElapsed;
v.z *= speed * timeElapsed;
cam.translate(v);
cam.update();
}
if (left) {
Vector3 v = cam.direction.cpy();
v.y = 0f;
v.rotate(Vector3.Y, 90);
v.x *= speed * timeElapsed;
v.z *= speed * timeElapsed;
cam.translate(v);
cam.update();
}
if (right) {
Vector3 v = cam.direction.cpy();
v.y = 0f;
v.rotate(Vector3.Y, -90);
v.x *= speed * timeElapsed;
v.z *= speed * timeElapsed;
cam.translate(v);
cam.update();
}
}
答案 2 :(得分:2)
This article在我看来真的很有帮助。我找到了一个应该有效的解决方案,但我还没有尝试过。我的MovingObject
个人都有Vector3 position
,Vector3 direction
,Vector3 size
和Vecotr3 upVector
。 Player
课程扩展了此MovingObject
课程,并将Mouse
和Keycontroll
添加到动作中。
在MovingObject
课程中我有了moethods:
rotateYaw(float degrees)
:将Vector3 direction
围绕Y-Axis
旋转给定度数(libgdx具有Vector3
的旋转功能) - &gt;简单rotatePitch(float degrees)
:按照给定的度数旋转Vector3 direction
围绕direction.cross(Vector3.Y)
,即MovingObject
的旋转侧矢量。另外,Pitch-Rotation
必须旋转upVector
,因此您可以按照给定的度数围绕同一轴旋转upVector
。一旦你明白这一点就很简单。 move(delta)
通过以下方式移动MovingObject
x,z
方向:
if (direction.y == 1) { // You are looking straight up, no x,z direction, move in the opposite // direction of upVector xSpeed = upVector.x / (Math.abs(upVetor.x) + Math.abs(upVector.z)) * (-speed); zSpeed = upVector.z / (Math.abs(upVetor.x) + Math.abs(upVector.z)) * (-speed); position.add(xSpeed * delta, 0, ySpeed * delta); } else if (direction.y == -1) { // You are looking straight down, no x,z direction, move in the direction of // upVector xSpeed = upVector.x / (Math.abs(upVetor.x) + Math.abs(upVector.z)) * speed; zSpeed = upVector.z / (Math.abs(upVetor.x) + Math.abs(upVector.z)) * speed; position.add(xSpeed * delta, 0, ySpeed * delta); } else { // You are not looking straight up or down, so you have x,z direction. Use // that. xSpeed = direction.x / (Math.abs(direction.x) + Math.abs(direction.z)) * speed; zSpeed = direction.z / (Math.abs(direction.x) + Math.abs(direction.z)) * speed; position.add(xSpeed * delta, 0, ySpeed * delta); }
直到现在我才对此进行测试,但我认为它应该可行。请注意,在Pitch-rotation
中,您还应将其限制为直线上升/下降。通过检查x和z的符号来完成此操作。如果他们在你做Pitch-rotation
时你改变了,你旋转了90度。
我等待其他答案,如果我错了,请纠正我!
编辑:我测试了它。它的工作原理如下,但有几点需要注意:
direction.cross(upVector)
更改direction
向量。所以先将数据存储在某个地方!使用后重置方向Vector。direction
和upVector
!我认为这应该会很好。如果您有任何改进,请告诉我,我会在此更新。如果您有其他解决方案,请添加答案!感谢