Simulation timestamps and input bindings

- added new simulation time calculations in CApplication
- added simulation frame updates
- rewritten old input binding code and input state tracking
dev-ui
Piotr Dziwinski 2012-09-12 23:43:04 +02:00
parent 6c21dceb35
commit 34d7dcf3be
7 changed files with 469 additions and 78 deletions

View File

@ -81,23 +81,47 @@ CApplication::CApplication()
m_robotMain = nullptr;
m_sound = nullptr;
m_keyState = 0;
m_axeKey = Math::Vector(0.0f, 0.0f, 0.0f);
m_axeJoy = Math::Vector(0.0f, 0.0f, 0.0f);
m_exitCode = 0;
m_active = false;
m_debugMode = false;
m_windowTitle = "COLOBOT";
m_simulationSuspended = false;
m_simulationSpeed = 1.0f;
m_realAbsTimeBase = 0LL;
m_realAbsTime = 0LL;
m_realRelTime = 0LL;
m_absTimeBase = 0LL;
m_exactAbsTime = 0LL;
m_exactRelTime = 0LL;
m_absTime = 0.0f;
m_relTime = 0.0f;
m_baseTimeStamp = CreateTimeStamp();
m_curTimeStamp = CreateTimeStamp();
m_lastTimeStamp = CreateTimeStamp();
m_joystickEnabled = false;
m_kmodState = 0;
m_mouseButtonsState = 0;
for (int i = 0; i < TRKEY_MAX; ++i)
m_trackedKeysState[i] = false;
m_keyMotion = Math::Vector(0.0f, 0.0f, 0.0f);
m_joyMotion = Math::Vector(0.0f, 0.0f, 0.0f);
m_dataPath = "./data";
m_language = LANG_ENGLISH;
ResetKey();
SetDefaultInputBindings();
}
CApplication::~CApplication()
@ -110,6 +134,10 @@ CApplication::~CApplication()
delete m_iMan;
m_iMan = nullptr;
DestroyTimeStamp(m_baseTimeStamp);
DestroyTimeStamp(m_curTimeStamp);
DestroyTimeStamp(m_lastTimeStamp);
}
bool CApplication::ParseArguments(int argc, char *argv[])
@ -542,6 +570,10 @@ int CApplication::Run()
{
m_active = true;
GetCurrentTimeStamp(m_baseTimeStamp);
GetCurrentTimeStamp(m_lastTimeStamp);
GetCurrentTimeStamp(m_curTimeStamp);
while (true)
{
// To be sure no old event remains
@ -618,6 +650,9 @@ int CApplication::Run()
// Update game and render a frame during idle time (no messages are waiting)
Render();
// Update simulation state
StepSimulation();
}
}
@ -737,8 +772,72 @@ bool CApplication::ProcessEvent(const Event &event)
if (event.type == EVENT_ACTIVE)
{
m_active = event.active.gain;
if (m_debugMode)
l->Info("Focus change: active = %s\n", m_active ? "true" : "false");
if (m_active)
ResumeSimulation();
else
SuspendSimulation();
}
else if (event.type == EVENT_KEY_DOWN)
{
m_kmodState = event.key.mod;
if ((m_kmodState & KEY_MOD(SHIFT)) != 0)
m_trackedKeysState[TRKEY_SHIFT] = true;
else if ((m_kmodState & KEY_MOD(CTRL)) != 0)
m_trackedKeysState[TRKEY_CONTROL] = true;
else if (event.key.key == KEY(KP8))
m_trackedKeysState[TRKEY_NUM_UP] = true;
else if (event.key.key == KEY(KP2))
m_trackedKeysState[TRKEY_NUM_DOWN] = true;
else if (event.key.key == KEY(KP4))
m_trackedKeysState[TRKEY_NUM_LEFT] = true;
else if (event.key.key == KEY(KP6))
m_trackedKeysState[TRKEY_NUM_RIGHT] = true;
else if (event.key.key == KEY(KP_PLUS))
m_trackedKeysState[TRKEY_NUM_PLUS] = true;
else if (event.key.key == KEY(KP_MINUS))
m_trackedKeysState[TRKEY_NUM_MINUS] = true;
else if (event.key.key == KEY(PAGEUP))
m_trackedKeysState[TRKEY_PAGE_UP] = true;
else if (event.key.key == KEY(PAGEDOWN))
m_trackedKeysState[TRKEY_PAGE_DOWN] = true;
}
else if (event.type == EVENT_KEY_UP)
{
m_kmodState = event.key.mod;
if ((m_kmodState & KEY_MOD(SHIFT)) != 0)
m_trackedKeysState[TRKEY_SHIFT] = false;
else if ((m_kmodState & KEY_MOD(CTRL)) != 0)
m_trackedKeysState[TRKEY_CONTROL] = false;
else if (event.key.key == KEY(KP8))
m_trackedKeysState[TRKEY_NUM_UP] = false;
else if (event.key.key == KEY(KP2))
m_trackedKeysState[TRKEY_NUM_DOWN] = false;
else if (event.key.key == KEY(KP4))
m_trackedKeysState[TRKEY_NUM_LEFT] = false;
else if (event.key.key == KEY(KP6))
m_trackedKeysState[TRKEY_NUM_RIGHT] = false;
else if (event.key.key == KEY(KP_PLUS))
m_trackedKeysState[TRKEY_NUM_PLUS] = false;
else if (event.key.key == KEY(KP_MINUS))
m_trackedKeysState[TRKEY_NUM_MINUS] = false;
else if (event.key.key == KEY(PAGEUP))
m_trackedKeysState[TRKEY_PAGE_UP] = false;
else if (event.key.key == KEY(PAGEDOWN))
m_trackedKeysState[TRKEY_PAGE_DOWN] = false;
}
else if (event.type == EVENT_MOUSE_BUTTON_DOWN)
{
m_mouseButtonsState |= 1 << event.mouseButton.button;
}
else if (event.type == EVENT_MOUSE_BUTTON_UP)
{
m_mouseButtonsState &= ~(1 << event.mouseButton.button);
}
// Print the events in debug mode to test the code
@ -800,9 +899,101 @@ void CApplication::Render()
SDL_GL_SwapBuffers();
}
void CApplication::StepSimulation(float rTime)
void CApplication::SuspendSimulation()
{
// TODO
m_simulationSuspended = true;
GetLogger()->Info("Suspend simulation\n");
}
void CApplication::ResumeSimulation()
{
m_simulationSuspended = false;
GetCurrentTimeStamp(m_baseTimeStamp);
CopyTimeStamp(m_curTimeStamp, m_baseTimeStamp);
m_realAbsTimeBase = m_realAbsTime;
m_absTimeBase = m_exactAbsTime;
GetLogger()->Info("Resume simulation\n");
}
bool CApplication::GetSimulationSuspended()
{
return m_simulationSuspended;
}
void CApplication::SetSimulationSpeed(float speed)
{
m_simulationSpeed = speed;
GetCurrentTimeStamp(m_baseTimeStamp);
m_realAbsTimeBase = m_realAbsTime;
m_absTimeBase = m_exactAbsTime;
GetLogger()->Info("Simulation speed = %.2f\n", speed);
}
void CApplication::StepSimulation()
{
if (m_simulationSuspended)
return;
CopyTimeStamp(m_lastTimeStamp, m_curTimeStamp);
GetCurrentTimeStamp(m_curTimeStamp);
long long absDiff = TimeStampExactDiff(m_baseTimeStamp, m_curTimeStamp);
m_realAbsTime = m_realAbsTimeBase + absDiff;
// m_baseTimeStamp is updated on simulation speed change, so this is OK
m_exactAbsTime = m_absTimeBase + m_simulationSpeed * absDiff;
m_absTime = (m_absTimeBase + m_simulationSpeed * absDiff) / 1e9f;
m_realRelTime = TimeStampExactDiff(m_lastTimeStamp, m_curTimeStamp);
m_exactRelTime = m_simulationSpeed * m_realRelTime;
m_relTime = (m_simulationSpeed * m_realRelTime) / 1e9f;
m_engine->FrameUpdate();
//m_sound->FrameMove(m_relTime);
Event frameEvent(EVENT_FRAME);
frameEvent.rTime = m_relTime;
m_eventQueue->AddEvent(frameEvent);
}
float CApplication::GetSimulationSpeed()
{
return m_simulationSpeed;
}
float CApplication::GetAbsTime()
{
return m_absTime;
}
long long CApplication::GetExactAbsTime()
{
return m_exactAbsTime;
}
long long CApplication::GetRealAbsTime()
{
return m_realAbsTime;
}
float CApplication::GetRelTime()
{
return m_relTime;
}
long long CApplication::GetExactRelTime()
{
return m_exactRelTime;
}
long long CApplication::GetRealRelTime()
{
return m_realRelTime;
}
Gfx::GLDeviceConfig CApplication::GetVideoConfig()
@ -863,25 +1054,79 @@ bool CApplication::GetDebugMode()
return m_debugMode;
}
void CApplication::FlushPressKey()
void CApplication::SetDefaultInputBindings()
{
// TODO
for (int i = 0; i < KEYRANK_MAX; i++)
m_inputBindings[i].Reset();
m_inputBindings[KEYRANK_LEFT ].key = KEY(LEFT);
m_inputBindings[KEYRANK_RIGHT ].key = KEY(RIGHT);
m_inputBindings[KEYRANK_UP ].key = KEY(UP);
m_inputBindings[KEYRANK_DOWN ].key = KEY(DOWN);
m_inputBindings[KEYRANK_GUP ].kmod = KEY_MOD(SHIFT);
m_inputBindings[KEYRANK_GDOWN ].kmod = KEY_MOD(CTRL);
m_inputBindings[KEYRANK_CAMERA ].key = KEY(SPACE);
m_inputBindings[KEYRANK_CAMERA ].joy = 2;
m_inputBindings[KEYRANK_DESEL ].key = KEY(KP0);
m_inputBindings[KEYRANK_DESEL ].kmod = 6;
m_inputBindings[KEYRANK_ACTION ].key = KEY(RETURN);
m_inputBindings[KEYRANK_ACTION ].joy = 1;
m_inputBindings[KEYRANK_NEAR ].key = KEY(KP_PLUS);
m_inputBindings[KEYRANK_NEAR ].joy = 5;
m_inputBindings[KEYRANK_AWAY ].key = KEY(KP_MINUS);
m_inputBindings[KEYRANK_AWAY ].joy = 4;
m_inputBindings[KEYRANK_NEXT ].key = KEY(TAB);
m_inputBindings[KEYRANK_NEXT ].joy = 3;
m_inputBindings[KEYRANK_HUMAN ].key = KEY(HOME);
m_inputBindings[KEYRANK_HUMAN ].joy = 7;
m_inputBindings[KEYRANK_QUIT ].key = KEY(ESCAPE);
m_inputBindings[KEYRANK_HELP ].key = KEY(F1);
m_inputBindings[KEYRANK_PROG ].key = KEY(F2);
m_inputBindings[KEYRANK_CBOT ].key = KEY(F3);
m_inputBindings[KEYRANK_VISIT ].key = KEY(KP_PERIOD);
m_inputBindings[KEYRANK_SPEED10].key = KEY(F4);
m_inputBindings[KEYRANK_SPEED15].key = KEY(F5);
m_inputBindings[KEYRANK_SPEED20].key = KEY(F6);
}
void CApplication::ResetKey()
int CApplication::GetKmods()
{
// TODO
return m_kmodState;
}
void CApplication::SetKey(int keyRank, int option, int key)
bool CApplication::GetKmodState(int kmod)
{
// TODO
return (m_kmodState & kmod) != 0;
}
int CApplication::GetKey(int keyRank, int option)
bool CApplication::GetTrackedKeyState(TrackedKey key)
{
// TODO
return 0;
return m_trackedKeysState[key];
}
bool CApplication::GetMouseButtonState(int index)
{
return (m_mouseButtonsState & (1<<index)) != 0;
}
void CApplication::ResetKeyStates()
{
for (int i = 0; i < TRKEY_MAX; ++i)
m_trackedKeysState[i] = false;
m_kmodState = 0;
m_keyMotion = Math::Vector(0.0f, 0.0f, 0.0f);
m_joyMotion = Math::Vector(0.0f, 0.0f, 0.0f);
}
void CApplication::SetInputBinding(InputSlot slot, const InputBinding& binding)
{
m_inputBindings[slot] = binding;
}
const InputBinding& CApplication::GetInputBinding(InputSlot slot)
{
return m_inputBindings[slot];
}
void CApplication::SetGrabInput(bool grab)

View File

@ -38,8 +38,9 @@ class CRobotMain;
class CSound;
/**
\struct JoystickDevice
\brief Information about a joystick device */
* \struct JoystickDevice
* \brief Information about a joystick device
*/
struct JoystickDevice
{
//! Device index (-1 = invalid device)
@ -56,8 +57,9 @@ struct JoystickDevice
};
/**
\enum VideoQueryResult
\brief Result of querying for available video resolutions */
* \enum VideoQueryResult
* \brief Result of querying for available video resolutions
*/
enum VideoQueryResult
{
VIDEO_QUERY_ERROR,
@ -67,6 +69,83 @@ enum VideoQueryResult
};
/**
* \enum TrackedKeys
* \brief Keys (or kmods) whose state (pressed/released) is tracked by CApplication
*/
enum TrackedKey
{
TRKEY_SHIFT,
TRKEY_CONTROL,
TRKEY_NUM_UP,
TRKEY_NUM_DOWN,
TRKEY_NUM_LEFT,
TRKEY_NUM_RIGHT,
TRKEY_NUM_PLUS,
TRKEY_NUM_MINUS,
TRKEY_PAGE_UP,
TRKEY_PAGE_DOWN,
TRKEY_MAX
};
/**
* \enum InputSlot
* \brief Available slots for input bindings
*/
enum InputSlot
{
INPUT_SLOT_LEFT = 0,
INPUT_SLOT_RIGHT = 1,
INPUT_SLOT_UP = 2,
INPUT_SLOT_DOWN = 3,
INPUT_SLOT_GUP = 4,
INPUT_SLOT_GDOWN = 5,
INPUT_SLOT_CAMERA = 6,
INPUT_SLOT_DESEL = 7,
INPUT_SLOT_ACTION = 8,
INPUT_SLOT_NEAR = 9,
INPUT_SLOT_AWAY = 10,
INPUT_SLOT_NEXT = 11,
INPUT_SLOT_HUMAN = 12,
INPUT_SLOT_QUIT = 13,
INPUT_SLOT_HELP = 14,
INPUT_SLOT_PROG = 15,
INPUT_SLOT_VISIT = 16,
INPUT_SLOT_SPEED10 = 17,
INPUT_SLOT_SPEED15 = 18,
INPUT_SLOT_SPEED20 = 19,
INPUT_SLOT_SPEED30 = 20,
INPUT_SLOT_AIMUP = 21,
INPUT_SLOT_AIMDOWN = 22,
INPUT_SLOT_CBOT = 23,
INPUT_SLOT_MAX
};
/**
* \struct InputBinding
* \brief Settable binding for user input
*/
struct InputBinding
{
//! Key
int key;
//! Key modifier (e.g. shift, control)
int kmod;
//! Joystick button
int joy;
inline InputBinding()
{
Reset();
}
inline void Reset()
{
key = kmod = joy = -1;
}
};
struct ApplicationPrivate;
/**
@ -146,8 +225,37 @@ public:
//! Change the video mode to given mode
bool ChangeVideoConfig(const Gfx::GLDeviceConfig &newConfig);
//! Suspends animation (time will not be updated)
void SuspendSimulation();
//! Resumes animation
void ResumeSimulation();
//! Returns whether simulation is suspended
bool GetSimulationSuspended();
//! Updates the simulation state
void StepSimulation(float rTime);
void StepSimulation();
//@{
//! Management of simulation speed
void SetSimulationSpeed(float speed);
float GetSimulationSpeed();
//@}
//! Returns the absolute time counter [seconds]
float GetAbsTime();
//! Returns the exact absolute time counter [nanoseconds]
long long GetExactAbsTime();
//! Returns the exact absolute time counter disregarding speed setting [nanoseconds]
long long GetRealAbsTime();
//! Returns the relative time since last update [seconds]
float GetRelTime();
//! Returns the exact realative time since last update [nanoseconds]
long long GetExactRelTime();
//! Returns the exact relative time since last update disregarding speed setting [nanoseconds]
long long GetRealRelTime();
//! Returns a list of available joystick devices
std::vector<JoystickDevice> GetJoystickList();
@ -158,10 +266,11 @@ public:
//! Change the current joystick device
bool ChangeJoystick(const JoystickDevice &newJoystick);
//! Enables/disables joystick
//! Management of joystick enable state
//@{
void SetJoystickEnabled(bool enable);
//! Returns whether joystick is enabled
bool GetJoystickEnabled();
//@}
//! Polls the state of joystick axes and buttons
void UpdateJoystick();
@ -169,30 +278,56 @@ public:
//! Updates the mouse position explicitly
void UpdateMouse();
void FlushPressKey();
void ResetKey();
void SetKey(int keyRank, int option, int key);
int GetKey(int keyRank, int option);
//! Returns the current key modifiers
int GetKmods();
//! Returns whether the given kmod is active
bool GetKmodState(int kmod);
//! Sets the grab mode for input (keyboard & mouse)
//! Returns whether the tracked key is pressed
bool GetTrackedKeyState(TrackedKey key);
//! Returns whether the mouse button is pressed
bool GetMouseButtonState(int index);
//! Resets tracked key states, modifiers and motion vectors
void ResetKeyStates();
// TODO move input binding and motion vectors to CRobotMain
//! Sets the default input bindings
void SetDefaultInputBindings();
//! Management of input bindings
//@{
void SetInputBinding(InputSlot slot, const InputBinding& binding);
const InputBinding& GetInputBinding(InputSlot slot);
//@}
//! Management of the grab mode for input (keyboard & mouse)
//@{
void SetGrabInput(bool grab);
//! Returns the grab mode
bool GetGrabInput();
//@}
//! Sets the visiblity of system mouse cursor
//! Management of the visiblity of system mouse cursor
//@{
void SetSystemMouseVisible(bool visible);
//! Returns the visiblity of system mouse cursor
bool GetSystemMouseVisibile();
//@}
//! Sets the position of system mouse cursor (in interface coords)
//! Management of the position of system mouse cursor (in interface coords)
//@{
void SetSystemMousePos(Math::Point pos);
//! Returns the position of system mouse cursor (in interface coords)
Math::Point GetSystemMousePos();
//@}
//! Enables/disables debug mode (prints more info in logger)
//! Management of debug mode (prints more info in logger)
//@{
void SetDebugMode(bool mode);
//! Returns whether debug mode is enabled
bool GetDebugMode();
//@}
//! Returns the full path to a file in data directory
std::string GetDataFilePath(const std::string &dirName, const std::string &fileName);
@ -253,13 +388,44 @@ protected:
//! Text set as window title
std::string m_windowTitle;
int m_keyState;
Math::Vector m_axeKey;
Math::Vector m_axeJoy;
Math::Point m_systemMousePos;
long m_mouseWheel;
//! Animation time stamps, etc.
//@{
SystemTimeStamp* m_baseTimeStamp;
SystemTimeStamp* m_lastTimeStamp;
SystemTimeStamp* m_curTimeStamp;
long m_key[50][2];
long long m_realAbsTimeBase;
long long m_realAbsTime;
long long m_realRelTime;
long long m_absTimeBase;
long long m_exactAbsTime;
long long m_exactRelTime;
float m_absTime;
float m_relTime;
float m_simulationSpeed;
bool m_simulationSuspended;
//@}
//! Current state of key modifiers (mask of SDLMod)
unsigned int m_kmodState;
//! Current state of some tracked keys (mask of TrackedKey)
bool m_trackedKeysState[TRKEY_MAX];
//! Current state of mouse buttons (mask of button indexes)
unsigned int m_mouseButtonsState;
//! Bindings for user inputs
InputBinding m_inputBindings[INPUT_SLOT_MAX];
//! Motion vector set by keyboard
Math::Vector m_keyMotion;
//! Motion vector set by joystick
Math::Vector m_joyMotion;
//! Current system mouse position
Math::Point m_systemMousePos;
//! Info about current joystick device
JoystickDevice m_joystick;

View File

@ -171,13 +171,19 @@ struct Event
ActiveEventData active;
};
// TODO: refactor/rewrite
// TODO: remove
long param; // parameter
// TODO: remove?
Math::Point pos; // mouse position (0 .. 1)
// TODO: ?
float axeX; // control the X axis (-1 .. 1)
float axeY; // control of the Y axis (-1 .. 1)
float axeZ; // control the Z axis (-1 .. 1)
short keyState; // state of the keyboard (KS_ *)
// TODO: remove in longer term (use CApplication's new time functions instead)
float rTime; // relative time
Event(EventType aType = EVENT_NULL)

View File

@ -84,9 +84,8 @@ enum ResearchType
/**
* \enum KeyRank
* \brief Slots for key assignment of user controls
*
* TODO: refactor
*/
// TODO: remove (use the new InputSlot enum from app/app.h)
enum KeyRank
{
KEYRANK_LEFT = 0,
@ -113,6 +112,8 @@ enum KeyRank
KEYRANK_AIMUP = 21,
KEYRANK_AIMDOWN = 22,
KEYRANK_CBOT = 23,
KEYRANK_MAX
};
// TODO: move to CRobotMain

View File

@ -22,7 +22,7 @@
#include <time.h>
// TODO: to be removed
// TODO: to be removed (replaced by TrackedKey enum and mouse states in app.h)
const int KS_PAGEUP = (1<<4);
const int KS_PAGEDOWN = (1<<5);
const int KS_SHIFT = (1<<6);

View File

@ -357,22 +357,22 @@ bool Gfx::CEngine::ProcessEvent(const Event &event)
}
}
}
else if (event.type == EVENT_FRAME)
{
m_highlightTime += event.rTime;
}
// By default, pass on all events
return true;
}
void Gfx::CEngine::FrameMove(float rTime)
void Gfx::CEngine::FrameUpdate()
{
float rTime = m_app->GetRelTime();
m_lightMan->UpdateProgression(rTime);
m_particle->FrameParticle(rTime);
ComputeDistance();
UpdateGeometry();
m_highlightTime = m_app->GetAbsTime();
if (m_groundMark.draw)
{
if (m_groundMark.phase == Gfx::ENG_GR_MARK_PHASE_INC) // growing?
@ -402,16 +402,6 @@ void Gfx::CEngine::FrameMove(float rTime)
}
}
}
if (m_sound == nullptr)
m_sound = static_cast<CSoundInterface*>( m_iMan->SearchInstance(CLASS_SOUND) );
m_sound->FrameMove(rTime);
}
void Gfx::CEngine::StepSimulation(float rTime)
{
m_app->StepSimulation(rTime);
}
bool Gfx::CEngine::WriteScreenShot(const std::string& fileName, int width, int height)
@ -2726,16 +2716,6 @@ int Gfx::CEngine::GetEditIndentValue()
return m_editIndentValue;
}
void Gfx::CEngine::SetSpeed(float speed)
{
m_speed = speed;
}
float Gfx::CEngine::GetSpeed()
{
return m_speed;
}
void Gfx::CEngine::SetTracePrecision(float factor)
{
m_tracePrecision = factor;

View File

@ -664,9 +664,7 @@ public:
bool ProcessEvent(const Event& event);
//! Called once per frame, the call is the entry point for animating the scene
void FrameMove(float rTime);
//! Evolved throughout the game
void StepSimulation(float rTime);
void FrameUpdate();
//! Writes a screenshot containing the current frame
@ -1098,11 +1096,6 @@ public:
int GetEditIndentValue();
//@}
//@{
//! Management of game speed
void SetSpeed(float speed);
float GetSpeed();
//@{
//! Management of precision of robot tracks
void SetTracePrecision(float factor);