void Ship::AIAccelToModelRelativeVelocity(const vector3d v) { vector3d difVel = v - GetVelocity() * GetOrient(); // required change in velocity vector3d maxThrust = GetMaxThrust(difVel); vector3d maxFrameAccel = maxThrust * (Pi::game->GetTimeStep() / GetMass()); SetThrusterState(0, difVel.x / maxFrameAccel.x); SetThrusterState(1, difVel.y / maxFrameAccel.y); SetThrusterState(2, difVel.z / maxFrameAccel.z); // use clamping }
void Ship::Blastoff() { if (m_flightState != LANDED) return; ClearThrusterState(); m_flightState = FLYING; m_testLanded = false; m_dockedWith = 0; m_launchLockTimeout = 2.0; // two second of applying thrusters vector3d up = GetPosition().Normalized(); Enable(); assert(GetFrame()->m_astroBody->IsType(Object::PLANET)); const double planetRadius = 2.0 + static_cast<Planet*>(GetFrame()->m_astroBody)->GetTerrainHeight(up); SetVelocity(vector3d(0, 0, 0)); SetAngVelocity(vector3d(0, 0, 0)); SetForce(vector3d(0, 0, 0)); SetTorque(vector3d(0, 0, 0)); Aabb aabb; GetAabb(aabb); // XXX hm. we need to be able to get sbre aabb SetPosition(up*planetRadius - aabb.min.y*up); SetThrusterState(1, 1.0); // thrust upwards Pi::luaOnShipTakeOff->Queue(this, GetFrame()->m_astroBody); }
void Ship::AIAccelToModelRelativeVelocity(const vector3d v) { // OK. For rotating frames linked to space stations we want to set // speed relative to non-rotating frame (so we apply Frame::GetStasisVelocityAtPosition. // For rotating frames linked to planets we want to set velocity relative to // surface, so we do not apply Frame::GetStasisVelocityAtPosition vector3d relVel = GetVelocity(); if (GetFrame()->IsStationRotFrame()) { relVel -= GetFrame()->GetStasisVelocityAtPosition(GetPosition()); } matrix4x4d m; GetRotMatrix(m); vector3d difVel = v - (relVel * m); // required change in velocity vector3d maxThrust = GetMaxThrust(difVel); vector3d maxFrameAccel = maxThrust * Pi::GetTimeStep() / GetMass(); SetThrusterState(0, difVel.x / maxFrameAccel.x); SetThrusterState(1, difVel.y / maxFrameAccel.y); SetThrusterState(2, difVel.z / maxFrameAccel.z); // use clamping }
// diffvel is required change in velocity in object space // returns true if this can be done in a single timestep bool Ship::AIChangeVelBy(const vector3d &diffvel) { // counter external forces vector3d extf = GetExternalForce() * (Pi::game->GetTimeStep() / GetMass()); vector3d diffvel2 = diffvel - extf * GetOrient(); vector3d maxThrust = GetMaxThrust(diffvel2); vector3d maxFrameAccel = maxThrust * (Pi::game->GetTimeStep() / GetMass()); vector3d thrust(diffvel2.x / maxFrameAccel.x, diffvel2.y / maxFrameAccel.y, diffvel2.z / maxFrameAccel.z); SetThrusterState(thrust); // use clamping if (thrust.x*thrust.x > 1.0 || thrust.y*thrust.y > 1.0 || thrust.z*thrust.z > 1.0) return false; return true; }
void Ship::Blastoff() { if (m_flightState != LANDED) return; vector3d up = GetPosition().Normalized(); assert(GetFrame()->GetBody()->IsType(Object::PLANET)); const double planetRadius = 2.0 + static_cast<Planet*>(GetFrame()->GetBody())->GetTerrainHeight(up); SetVelocity(vector3d(0, 0, 0)); SetAngVelocity(vector3d(0, 0, 0)); SetFlightState(FLYING); SetPosition(up*planetRadius - GetAabb().min.y*up); SetThrusterState(1, 1.0); // thrust upwards LuaEvent::Queue("onShipTakeOff", this, GetFrame()->GetBody()); }
// diffvel is required change in velocity in object space // returns true if this can be done in a single timestep bool Ship::AIChangeVelBy(const vector3d &diffvel) { // counter external forces unless we're in an orbital station rotating frame matrix4x4d rot; GetRotMatrix(rot); vector3d diffvel2 = GetExternalForce() * Pi::GetTimeStep() / GetMass(); if (GetFrame()->IsStationRotFrame()) diffvel2 = diffvel; else diffvel2 = diffvel - diffvel2 * rot; vector3d maxThrust = GetMaxThrust(diffvel2); vector3d maxFrameAccel = maxThrust * Pi::GetTimeStep() / GetMass(); vector3d thrust(diffvel2.x / maxFrameAccel.x, diffvel2.y / maxFrameAccel.y, diffvel2.z / maxFrameAccel.z); SetThrusterState(thrust); // use clamping if (thrust.x*thrust.x > 1.0 || thrust.y*thrust.y > 1.0 || thrust.z*thrust.z > 1.0) return false; return true; }
void Player::PollControls(const float timeStep) { static bool stickySpeedKey = false; if (Pi::game->GetTimeAccel() == Game::TIMEACCEL_PAUSED || Pi::player->IsDead() || GetFlightState() != FLYING) return; // if flying { ClearThrusterState(); SetGunState(0,0); SetGunState(1,0); vector3d wantAngVel(0.0); double angThrustSoftness = 50.0; // have to use this function. SDL mouse position event is bugged in windows int mouseMotion[2]; SDL_GetRelativeMouseState (mouseMotion+0, mouseMotion+1); // call to flush if (Pi::MouseButtonState(SDL_BUTTON_RIGHT)) { matrix4x4d rot; GetRotMatrix(rot); if (!m_mouseActive) { m_mouseDir = vector3d(-rot[8],-rot[9],-rot[10]); // in world space m_mouseX = m_mouseY = 0; m_mouseActive = true; } vector3d objDir = m_mouseDir * rot; const double radiansPerPixel = 0.002; m_mouseX += mouseMotion[0] * radiansPerPixel; double modx = clipmouse(objDir.x, m_mouseX); m_mouseX -= modx; const bool invertY = (Pi::IsMouseYInvert() ? !m_invertMouse : m_invertMouse); m_mouseY += mouseMotion[1] * radiansPerPixel * (invertY ? -1 : 1); double mody = clipmouse(objDir.y, m_mouseY); m_mouseY -= mody; if(!float_is_zero_general(modx) || !float_is_zero_general(mody)) { matrix4x4d mrot = matrix4x4d::RotateYMatrix(modx); mrot.RotateX(mody); m_mouseDir = (rot * (mrot * objDir)).Normalized(); } } else m_mouseActive = false; // disable all keyboard controls while the console is active if (!Pi::IsConsoleActive()) { if (m_flightControlState == CONTROL_FIXSPEED) { double oldSpeed = m_setSpeed; if (stickySpeedKey) { if (!(KeyBindings::increaseSpeed.IsActive() || KeyBindings::decreaseSpeed.IsActive())) { stickySpeedKey = false; } } if (!stickySpeedKey) { if (KeyBindings::increaseSpeed.IsActive()) m_setSpeed += std::max(fabs(m_setSpeed)*0.05, 1.0); if (KeyBindings::decreaseSpeed.IsActive()) m_setSpeed -= std::max(fabs(m_setSpeed)*0.05, 1.0); if ( ((oldSpeed < 0.0) && (m_setSpeed >= 0.0)) || ((oldSpeed > 0.0) && (m_setSpeed <= 0.0)) ) { // flipped from going forward to backwards. make the speed 'stick' at zero // until the player lets go of the key and presses it again stickySpeedKey = true; m_setSpeed = 0; } } } if (KeyBindings::thrustForward.IsActive()) SetThrusterState(2, -1.0); if (KeyBindings::thrustBackwards.IsActive()) SetThrusterState(2, 1.0); if (KeyBindings::thrustUp.IsActive()) SetThrusterState(1, 1.0); if (KeyBindings::thrustDown.IsActive()) SetThrusterState(1, -1.0); if (KeyBindings::thrustLeft.IsActive()) SetThrusterState(0, -1.0); if (KeyBindings::thrustRight.IsActive()) SetThrusterState(0, 1.0); if (KeyBindings::fireLaser.IsActive() || (Pi::MouseButtonState(SDL_BUTTON_LEFT) && Pi::MouseButtonState(SDL_BUTTON_RIGHT))) { SetGunState(Pi::worldView->GetActiveWeapon(), 1); } if (KeyBindings::yawLeft.IsActive()) wantAngVel.y += 1.0; if (KeyBindings::yawRight.IsActive()) wantAngVel.y += -1.0; if (KeyBindings::pitchDown.IsActive()) wantAngVel.x += -1.0; if (KeyBindings::pitchUp.IsActive()) wantAngVel.x += 1.0; if (KeyBindings::rollLeft.IsActive()) wantAngVel.z += 1.0; if (KeyBindings::rollRight.IsActive()) wantAngVel.z -= 1.0; if (KeyBindings::fastRotate.IsActive()) angThrustSoftness = 10.0; } vector3d changeVec; changeVec.x = KeyBindings::pitchAxis.GetValue(); changeVec.y = KeyBindings::yawAxis.GetValue(); changeVec.z = KeyBindings::rollAxis.GetValue(); // Deadzone if(changeVec.LengthSqr() < m_joystickDeadzone) changeVec = vector3d(0.0); changeVec *= 2.0; wantAngVel += changeVec; double invTimeAccelRate = 1.0 / Pi::game->GetTimeAccelRate(); for (int axis=0; axis<3; axis++) wantAngVel[axis] = Clamp(wantAngVel[axis], -invTimeAccelRate, invTimeAccelRate); if (m_mouseActive) AIFaceDirection(m_mouseDir); else AIModelCoordsMatchAngVel(wantAngVel, angThrustSoftness); } }
void Player::PollControls(const float timeStep) { double time_accel = Pi::GetTimeAccel(); double invTimeAccel = 1.0 / time_accel; static bool stickySpeedKey = false; if ((time_accel == 0) || GetDockedWith() || Pi::player->IsDead() || (GetFlightState() != FLYING)) { return; } // if flying { ClearThrusterState(); vector3d wantAngVel(0.0); // have to use this function. SDL mouse position event is bugged in windows int mouseMotion[2]; SDL_GetRelativeMouseState (mouseMotion+0, mouseMotion+1); // call to flush if (Pi::MouseButtonState(3)) { matrix4x4d rot; GetRotMatrix(rot); if (!m_mouseActive) { m_mouseDir = vector3d(-rot[8],-rot[9],-rot[10]); // in world space m_mouseX = m_mouseY = 0; m_mouseActive = true; } vector3d objDir = m_mouseDir * rot; m_mouseX += mouseMotion[0] * 0.002; double modx = clipmouse(objDir.x, m_mouseX); m_mouseX -= modx; m_mouseY += mouseMotion[1] * 0.002; // factor pixels => radians double mody = clipmouse(objDir.y, m_mouseY); m_mouseY -= mody; if(modx != 0.0 || mody != 0.0) { matrix4x4d mrot = matrix4x4d::RotateYMatrix(modx); mrot.RotateX(mody); m_mouseDir = (rot * (mrot * objDir)).Normalized(); } } else m_mouseActive = false; if (m_flightControlState == CONTROL_FIXSPEED) { double oldSpeed = m_setSpeed; if (stickySpeedKey) { if (!(KeyBindings::increaseSpeed.IsActive() || KeyBindings::decreaseSpeed.IsActive())) { stickySpeedKey = false; } } if (!stickySpeedKey) { if (KeyBindings::increaseSpeed.IsActive()) m_setSpeed += std::max(m_setSpeed*0.05, 1.0); if (KeyBindings::decreaseSpeed.IsActive()) m_setSpeed -= std::max(m_setSpeed*0.05, 1.0); if ( ((oldSpeed < 0.0) && (m_setSpeed >= 0.0)) || ((oldSpeed > 0.0) && (m_setSpeed <= 0.0)) ) { // flipped from going forward to backwards. make the speed 'stick' at zero // until the player lets go of the key and presses it again stickySpeedKey = true; m_setSpeed = 0; } } } if (KeyBindings::thrustForward.IsActive()) SetThrusterState(2, -1.0); if (KeyBindings::thrustBackwards.IsActive()) SetThrusterState(2, 1.0); if (KeyBindings::thrustUp.IsActive()) SetThrusterState(1, 1.0); if (KeyBindings::thrustDown.IsActive()) SetThrusterState(1, -1.0); if (KeyBindings::thrustLeft.IsActive()) SetThrusterState(0, -1.0); if (KeyBindings::thrustRight.IsActive()) SetThrusterState(0, 1.0); SetGunState(0,0); SetGunState(1,0); if (KeyBindings::fireLaser.IsActive() || (Pi::MouseButtonState(1) && Pi::MouseButtonState(3))) { SetGunState(Pi::worldView->GetActiveWeapon(), 1); } if (KeyBindings::yawLeft.IsActive()) wantAngVel.y += 1.0; if (KeyBindings::yawRight.IsActive()) wantAngVel.y += -1.0; if (KeyBindings::pitchDown.IsActive()) wantAngVel.x += -1.0; if (KeyBindings::pitchUp.IsActive()) wantAngVel.x += 1.0; if (KeyBindings::rollLeft.IsActive()) wantAngVel.z += 1.0; if (KeyBindings::rollRight.IsActive()) wantAngVel.z -= 1.0; wantAngVel.x += 2 * KeyBindings::pitchAxis.GetValue(); wantAngVel.y += 2 * KeyBindings::yawAxis.GetValue(); wantAngVel.z += 2 * KeyBindings::rollAxis.GetValue(); for (int axis=0; axis<3; axis++) wantAngVel[axis] = Clamp(wantAngVel[axis], -invTimeAccel, invTimeAccel); // matrix4x4d rot; GetRotMatrix(rot); const double angThrustSoftness = KeyBindings::fastRotate.IsActive() ? 10.0 : 50.0; if (m_mouseActive) AIFaceDirection(m_mouseDir); else AIModelCoordsMatchAngVel(wantAngVel, angThrustSoftness); } }