我正在工作的Direct3D9空间模拟器游戏,在其中,我需要创建一个相机,以保持位置和角度的球员的宇宙飞船。目前,我限制了我的代码,只用于前后移动、上下移动以及扫射。下面是我的代码,它有一个问题。所有向量都封装在一个类中,所有向量都在构造函数中初始化为D3DXVECTOR3(0.0f,0.0f,0.0f),除了LocalUp( D3DXVECTOR3(0.0f,1.0f,0.0f)和LocalAhead( D3DXVECTOR3(0.0f,0.0f,1.0f) ),浮点设置为0.0f;
D3DXVECTOR3 Position, LookAt ,PosDelta, PosDeltaWorld, WorldAhead, WorldUp, LocalUp,
LocalAhead, Velocity;
D3DXMATRIX View, CameraRotation;
float SpeedX, SpeedY, SpeedZ;
void Update(float ElapsedTime)
{
SpeedX = 0.0f;
SpeedY = 0.0f;
if(IsKeyDown('A'))
{
SpeedX = -0.02f;
Velocity.x -= SpeedX;
}
if(IsKeyDown('D'))
{
SpeedX = 0.02f;
Velocity.x += SpeedX;
}
if(IsKeyDown('X'))
{
SpeedZ += 0.01f;
Velocity.z += SpeedZ;
}
if(IsKeyDown('Z'))
{
SpeedZ -= 0.01f;
Velocity.z -= SpeedZ;
}
if(IsKeyDown('W'))
{
SpeedY = 0.02f;
Velocity.y += SpeedY;
}
if(IsKeyDown('S'))
{
SpeedY = -0.02f;
Velocity.y -= SpeedY;
}
D3DXVec3Normalize(&Velocity, &Velocity);
PosDelta.x = Velocity.x * SpeedX;
PosDelta.y = Velocity.y * SpeedY;
PosDelta.z = Velocity.z * SpeedZ;
D3DXMatrixRotationYawPitchRoll(&CameraRotation, 0, 0, 0);
D3DXVec3TransformCoord(&WorldUp, &LocalUp, &CameraRotation);
D3DXVec3TransformCoord(&WorldAhead, &LocalAhead, &CameraRotation);
D3DXVec3TransformCoord(&PosDeltaWorld, &PosDelta, &CameraRotation);
Position += PosDeltaWorld;
LookAt = Position + WorldAhead;
D3DXMatrixLookAtLH(&View, &Position, &LookAt, &WorldUp);
}在应用程序的另一部分中调用"D3DXMatrixPerspectiveFovLH“和"IDirect3DDevice9::SetTransform”函数。由于他们工作得很好,我将不再谈论他们。
问题是,当Z轴的速度相当大,我扫射和横向移动,分别或同时,相机的Z轴速度将下降。而且,在速度接近于0之后,我按下增加速度的键,矢量的感觉就会反转,然后恢复正常。这也发生在改变矢量的意义在相当高的速度(例如按X然后立即按'Z')。有人能解释一下为什么会这样吗?我该如何解决这个问题呢?
我还会问另一个问题:如果没有按下键,我如何才能慢慢降低扫瞄和Y轴的速度?我想在游戏中实现惯性效应。
如果有人能帮助我,请回答!
编辑:新代码:
void NewFrontiers3DEntityPlayer::OnFrameUpdate(float ElapsedTime)
{
State.SpeedX = 0.0f;
State.SpeedY = 0.0f;
if(IsKeyDown(State.Keys[CAM_STRAFE_LEFT]))
State.SpeedX = -0.02f;
if(IsKeyDown(State.Keys[CAM_STRAFE_RIGHT]))
State.SpeedX = 0.02f;
if(IsKeyDown(State.Keys[CAM_MOVE_FORWARD]))
{
State.SpeedZ += 0.01f;
}
if(IsKeyDown(State.Keys[CAM_MOVE_BACKWARD]))
{
State.SpeedZ -= 0.01f;
}
if(IsKeyDown(State.Keys[CAM_MOVE_UP]))
State.SpeedY = 0.02f;
if(IsKeyDown(State.Keys[CAM_MOVE_DOWN]))
State.SpeedY = -0.02f;
State.Velocity.x = State.SpeedX;
State.Velocity.y = State.SpeedY;
State.Velocity.z = State.SpeedZ;
D3DXVec3Normalize(&State.Velocity, &State.Velocity);
State.PosDelta.x = State.Velocity.x * ElapsedTime;
State.PosDelta.y = State.Velocity.y * ElapsedTime;
State.PosDelta.z = State.Velocity.z * ElapsedTime;
D3DXMatrixRotationYawPitchRoll(&State.CameraRotation, 0, 0, 0);
D3DXVec3TransformCoord(&State.WorldUp, &State.LocalUp, &State.CameraRotation);
D3DXVec3TransformCoord(&State.WorldAhead, &State.LocalAhead, &State.CameraRotation);
D3DXVec3TransformCoord(&State.PosDeltaWorld, &State.PosDelta, &State.CameraRotation);
State.Position += State.PosDeltaWorld;
State.LookAt = State.Position + State.WorldAhead;
D3DXMatrixLookAtLH(&State.View, &State.Position, &State.LookAt, &State.WorldUp);
return;
}"State“是一种保存有关照相机的所有信息的结构。
发布于 2014-09-13 16:47:07
我想,当你同时向多个方向移动时,你的速度会发生变化,因为你的速度是正常的。
例如,在Z中移动:
Velocity = (0, 0, 0.01)
Speed = (0,0, 0.01)
Normalized Velocity = (0, 0, 1)
PosDelta = (0, 0, 0.01)并在X+Z中移动:
Velocity = (0.02, 0, 0.01)
Speed = (0.02, 0, 0.01)
Normalized Velocity = (0.897, 0, 0.435)
PosDelta = (0.018, 0, 0.0044) 关于你的方向反转,我猜这可能与你使用速度/速度的比较奇怪的方法有关(更多见下文),也可能是因为浮标的精度。关于最后一点,您认为以下代码输出(忽略潜在的编译器优化)是什么?
float test1 = 0f;
test1 += 0.1f;
test1 += 0.1f;
test1 += 0.1f;
test1 += 0.1f;
test1 += 0.1f;
test1 -= 0.1f;
test1 -= 0.1f;
test1 -= 0.1f;
test1 -= 0.1f;
test1 -= 0.1f;
printf("%g\n", test1);它(可能吗?)不会输出0的明显答案,因为0.1不能精确地用基-2表示。它在我的系统上打印1.49012e-008。可能发生的情况是,你可能接近0,但不完全是这样,这可能导致坐标反演出现。你可以通过舍入速度达到一定的精度来消除这个问题。
你处理速度/速度/位置的整体方法有点奇怪,可能是你遇到困难的原因。例如,我希望Velocity是一个表示玩家速度的向量,而不是像你一样的标准化向量。我会做这样的事情:
SpeedX = 0.0f;
SpeedY = 0.0f;
SpeedZ = 0.0f
if(IsKeyDown('A')) SpeedX += -0.02f;
if(IsKeyDown('D')) SpeedX += 0.02f;
...
Velocity.x += SpeedX;
Velocity.y += SpeedY;
Velocity.z += SpeedZ;
D3DXVECTOR3 NormVelocity;
D3DXVec3Normalize(&NormVelocity, &Velocity);
//Round velocity here if you need to
Velocity.x = floor(Velocity.x * 10000) / 10000.0f;
...
float FrameTime = 1; //Use last frame time here
PosDelta.x = Velocity.x * FrameTime;
PosDelta.y = Velocity.y * FrameTime;
PosDelta.z = Velocity.z * FrameTime;这样,当你向多个方向移动时,速度就会改变。如果您将FrameTime设置为最后一个帧的时间(或从它派生的值),它还允许您适当地补偿更改的帧率。当玩家试图同时向两个相反的方向移动时,它也正确地阻止了玩家的移动。
关于你最后一个关于Y速度衰减的问题,有几种方法可以做到。你只需做这样的事情:
Velocity.y *= 0.7f;每一帧(调整常量以适应你的需要)。一个更准确的模型是这样做:
if (Velocity.y > 0) {
Velocity.y -= 0.001f; //Pick constant to suit
if (Velocity.y < 0) Velocity.y = 0;
}一个更好的方法是使用最后一个帧时间来考虑不同的帧速率,例如:
Velocity.y -= FrameTime * 0.2f; //Pick constant to suithttps://stackoverflow.com/questions/25824968
复制相似问题