Mouse Follow flight model
Posted: Sun Dec 22, 2013 7:43 pm
Hello,
i've just modified Pioneer so the vessel direction is following the mouse position on the screen (the far from center is the mouse, the fast the vessel will change direction).
This flight model is activated with the space key (i've changed the key assignment for this). This is the code changed in each file for this:
In bold, what i've changed/ or added
Keybindings.inc.h
BINDING_GROUP(Lang::MANUAL_CONTROL_MODE)
KEY_BINDING(thrustForward, "BindThrustForward", Lang::THRUSTER_MAIN, SDLK_i, 0)
KEY_BINDING(thrustBackwards, "BindThrustBackwards", Lang::THRUSTER_RETRO, SDLK_k, 0)
KEY_BINDING(thrustUp, "BindThrustUp", Lang::THRUSTER_VENTRAL, SDLK_u, 0)
KEY_BINDING(thrustDown, "BindThrustDown", Lang::THRUSTER_DORSAL, SDLK_o, 0)
KEY_BINDING(thrustLeft, "BindThrustLeft", Lang::THRUSTER_PORT, SDLK_j, 0)
KEY_BINDING(thrustRight, "BindThrustRight", Lang::THRUSTER_STARBOARD, SDLK_l, 0)
KEY_BINDING(thrustLowPower, "BindThrustLowPower", Lang::USE_LOW_THRUST, SDLK_LSHIFT, 0)
KEY_BINDING(FlightFollowMouse, "BindFlightFollowMouse", Lang::FLIGHT_FOLLOW_MOUSE, SDLK_SPACE, 0) => add this line
pi.h
static Game *game;
static struct DetailLevel detail;
static GameConfig *config;
static JobQueue *Jobs() { return jobQueue.get();}
static bool DrawGUI;
static int FlightModel; ==> add this line
Pi.cpp in the pi::init function add to the end:
Pi::FlightModel=0; ==> add this line
langstrings.inc.h add this to the end:
DECLARE_STRING(FLIGHT_FOLLOW_MOUSE) ==> add this line
Shipcontroller.cpp changing the function pollcontrols with this:
static bool stickySpeedKey = false;
CheckControlsLock();
if (m_controlsLocked) return;
// if flying
{
m_ship->ClearThrusterState();
m_ship->SetGunState(0,0);
m_ship->SetGunState(1,0);
vector3d wantAngVel(0.0);
double angThrustSoftness = 10.0;
const float linearThrustPower = (KeyBindings::thrustLowPower.IsActive() ? m_lowThrustPower : 1.0f);
// 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))
if (KeyBindings::FlightFollowMouse.IsActive())
{
if (Pi::FlightModel==0) Pi::FlightModel=1;
else
Pi::FlightModel=0;
}
if (Pi::FlightModel==1)
{
int x,y;
SDL_GetMouseState(&x,&y);
x-=Pi::renderer->GetWindow()->GetWidth()/2;
y-=Pi::renderer->GetWindow()->GetHeight()/2;
const matrix3x3d &rot = m_ship->GetOrient();
if (!m_mouseActive) {
m_mouseDir = -rot.VectorZ(); // in world space
// m_mouseX = m_mouseY = 0;
m_mouseActive = true;
}
vector3d objDir = m_mouseDir * rot;
const double radiansPerPixel = 0.00002 * m_fovY;
const int maxMotion = std::max(abs(x), abs(y));
const double accel = Clamp(maxMotion / 12.0, 0.0, 90.0 / m_fovY/20.0);
m_mouseX = x * accel * radiansPerPixel;
m_mouseX = clipmouse(objDir.x, m_mouseX);
const bool invertY = (Pi::IsMouseYInvert() ? !m_invertMouse : m_invertMouse);
m_mouseY = y * accel * radiansPerPixel * (invertY ? -1 : 1);
m_mouseY = clipmouse(objDir.y, m_mouseY);
if(!is_zero_general(m_mouseX) || !is_zero_general(m_mouseY)) {
matrix3x3d mrot = matrix3x3d::RotateY(m_mouseX) * matrix3x3d::RotateX(m_mouseY);
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(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()) m_ship->SetThrusterState(2, -linearThrustPower);
if (KeyBindings::thrustBackwards.IsActive()) m_ship->SetThrusterState(2, linearThrustPower);
if (KeyBindings::thrustUp.IsActive()) m_ship->SetThrusterState(1, linearThrustPower);
if (KeyBindings::thrustDown.IsActive()) m_ship->SetThrusterState(1, -linearThrustPower);
if (KeyBindings::thrustLeft.IsActive()) m_ship->SetThrusterState(0, -linearThrustPower);
if (KeyBindings::thrustRight.IsActive()) m_ship->SetThrusterState(0, linearThrustPower);
// if (KeyBindings::fireLaser.IsActive() || (Pi::MouseButtonState(SDL_BUTTON_LEFT) && Pi::MouseButtonState(SDL_BUTTON_RIGHT)))
if (Pi::MouseButtonState(SDL_BUTTON_RIGHT))
{
//XXX worldview? madness, ask from ship instead
m_ship->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::thrustLowPower.IsActive())
angThrustSoftness = 50.0;
vector3d changeVec;
changeVec.x = KeyBindings::pitchAxis.GetValue();
changeVec.y = KeyBindings::yawAxis.GetValue();
changeVec.z = KeyBindings::rollAxis.GetValue();
// Deadzone more accurate
for (int axis=0; axis<3; axis++) {
if (fabs(changeVec[axis]) < m_joystickDeadzone)
changeVec[axis]=0.0;
else
changeVec[axis] = changeVec[axis] * 2.0;
}
wantAngVel += changeVec;
if (wantAngVel.Length() >= 0.001 || force_rotation_damping || m_rotationDamping) {
if (Pi::game->GetTimeAccel()!=Game::TIMEACCEL_1X) {
for (int axis=0; axis<3; axis++)
wantAngVel[axis] = wantAngVel[axis] * Pi::game->GetInvTimeAccelRate();
}
m_ship->AIModelCoordsMatchAngVel(wantAngVel, angThrustSoftness);
}
if (m_mouseActive) m_ship->AIFaceDirection(m_mouseDir);
}
And now you'll have a vessel following the mouse, no need to move the mouse continuously, combats are more fun
Someone can test this ?
i've just modified Pioneer so the vessel direction is following the mouse position on the screen (the far from center is the mouse, the fast the vessel will change direction).
This flight model is activated with the space key (i've changed the key assignment for this). This is the code changed in each file for this:
In bold, what i've changed/ or added
Keybindings.inc.h
BINDING_GROUP(Lang::MANUAL_CONTROL_MODE)
KEY_BINDING(thrustForward, "BindThrustForward", Lang::THRUSTER_MAIN, SDLK_i, 0)
KEY_BINDING(thrustBackwards, "BindThrustBackwards", Lang::THRUSTER_RETRO, SDLK_k, 0)
KEY_BINDING(thrustUp, "BindThrustUp", Lang::THRUSTER_VENTRAL, SDLK_u, 0)
KEY_BINDING(thrustDown, "BindThrustDown", Lang::THRUSTER_DORSAL, SDLK_o, 0)
KEY_BINDING(thrustLeft, "BindThrustLeft", Lang::THRUSTER_PORT, SDLK_j, 0)
KEY_BINDING(thrustRight, "BindThrustRight", Lang::THRUSTER_STARBOARD, SDLK_l, 0)
KEY_BINDING(thrustLowPower, "BindThrustLowPower", Lang::USE_LOW_THRUST, SDLK_LSHIFT, 0)
KEY_BINDING(FlightFollowMouse, "BindFlightFollowMouse", Lang::FLIGHT_FOLLOW_MOUSE, SDLK_SPACE, 0) => add this line
pi.h
static Game *game;
static struct DetailLevel detail;
static GameConfig *config;
static JobQueue *Jobs() { return jobQueue.get();}
static bool DrawGUI;
static int FlightModel; ==> add this line
Pi.cpp in the pi::init function add to the end:
Pi::FlightModel=0; ==> add this line
langstrings.inc.h add this to the end:
DECLARE_STRING(FLIGHT_FOLLOW_MOUSE) ==> add this line
Shipcontroller.cpp changing the function pollcontrols with this:
static bool stickySpeedKey = false;
CheckControlsLock();
if (m_controlsLocked) return;
// if flying
{
m_ship->ClearThrusterState();
m_ship->SetGunState(0,0);
m_ship->SetGunState(1,0);
vector3d wantAngVel(0.0);
double angThrustSoftness = 10.0;
const float linearThrustPower = (KeyBindings::thrustLowPower.IsActive() ? m_lowThrustPower : 1.0f);
// 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))
if (KeyBindings::FlightFollowMouse.IsActive())
{
if (Pi::FlightModel==0) Pi::FlightModel=1;
else
Pi::FlightModel=0;
}
if (Pi::FlightModel==1)
{
int x,y;
SDL_GetMouseState(&x,&y);
x-=Pi::renderer->GetWindow()->GetWidth()/2;
y-=Pi::renderer->GetWindow()->GetHeight()/2;
const matrix3x3d &rot = m_ship->GetOrient();
if (!m_mouseActive) {
m_mouseDir = -rot.VectorZ(); // in world space
// m_mouseX = m_mouseY = 0;
m_mouseActive = true;
}
vector3d objDir = m_mouseDir * rot;
const double radiansPerPixel = 0.00002 * m_fovY;
const int maxMotion = std::max(abs(x), abs(y));
const double accel = Clamp(maxMotion / 12.0, 0.0, 90.0 / m_fovY/20.0);
m_mouseX = x * accel * radiansPerPixel;
m_mouseX = clipmouse(objDir.x, m_mouseX);
const bool invertY = (Pi::IsMouseYInvert() ? !m_invertMouse : m_invertMouse);
m_mouseY = y * accel * radiansPerPixel * (invertY ? -1 : 1);
m_mouseY = clipmouse(objDir.y, m_mouseY);
if(!is_zero_general(m_mouseX) || !is_zero_general(m_mouseY)) {
matrix3x3d mrot = matrix3x3d::RotateY(m_mouseX) * matrix3x3d::RotateX(m_mouseY);
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(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()) m_ship->SetThrusterState(2, -linearThrustPower);
if (KeyBindings::thrustBackwards.IsActive()) m_ship->SetThrusterState(2, linearThrustPower);
if (KeyBindings::thrustUp.IsActive()) m_ship->SetThrusterState(1, linearThrustPower);
if (KeyBindings::thrustDown.IsActive()) m_ship->SetThrusterState(1, -linearThrustPower);
if (KeyBindings::thrustLeft.IsActive()) m_ship->SetThrusterState(0, -linearThrustPower);
if (KeyBindings::thrustRight.IsActive()) m_ship->SetThrusterState(0, linearThrustPower);
// if (KeyBindings::fireLaser.IsActive() || (Pi::MouseButtonState(SDL_BUTTON_LEFT) && Pi::MouseButtonState(SDL_BUTTON_RIGHT)))
if (Pi::MouseButtonState(SDL_BUTTON_RIGHT))
{
//XXX worldview? madness, ask from ship instead
m_ship->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::thrustLowPower.IsActive())
angThrustSoftness = 50.0;
vector3d changeVec;
changeVec.x = KeyBindings::pitchAxis.GetValue();
changeVec.y = KeyBindings::yawAxis.GetValue();
changeVec.z = KeyBindings::rollAxis.GetValue();
// Deadzone more accurate
for (int axis=0; axis<3; axis++) {
if (fabs(changeVec[axis]) < m_joystickDeadzone)
changeVec[axis]=0.0;
else
changeVec[axis] = changeVec[axis] * 2.0;
}
wantAngVel += changeVec;
if (wantAngVel.Length() >= 0.001 || force_rotation_damping || m_rotationDamping) {
if (Pi::game->GetTimeAccel()!=Game::TIMEACCEL_1X) {
for (int axis=0; axis<3; axis++)
wantAngVel[axis] = wantAngVel[axis] * Pi::game->GetInvTimeAccelRate();
}
m_ship->AIModelCoordsMatchAngVel(wantAngVel, angThrustSoftness);
}
if (m_mouseActive) m_ship->AIFaceDirection(m_mouseDir);
}
And now you'll have a vessel following the mouse, no need to move the mouse continuously, combats are more fun
Someone can test this ?