From 6b6f5b95ec75f484df749a81c3a969b0f72ca54a Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Mon, 21 Jun 2010 23:39:59 +0200 Subject: [PATCH] Added camera movement (arrows/WASD). No mouse look yet. --- CMakeLists.txt | 4 +- game/engine.cpp | 8 ++- game/mwinput/inputmanager.hpp | 73 ++++++++++++++++++++++-- game/mwrender/playerpos.hpp | 56 ++++++++++++++++++ input/listener.hpp | 3 + input/poller.hpp | 51 +++++++++++++++++ old_d_version/ogre/cpp_framelistener.cpp | 23 -------- 7 files changed, 186 insertions(+), 32 deletions(-) create mode 100644 game/mwrender/playerpos.hpp create mode 100644 input/poller.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 54f358f77..0cbb94b2c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ set(OGRE ogre/renderer.cpp) set(OGRE_HEADER ogre/renderer.hpp) set(INPUT input/oismanager.cpp) -set(INPUT_HEADER input/oismanager.hpp input/listener.hpp input/func_binder.hpp input/dispatch_map.hpp input/dispatcher.hpp) +set(INPUT_HEADER input/oismanager.hpp input/listener.hpp input/func_binder.hpp input/dispatch_map.hpp input/dispatcher.hpp input/poller.hpp) set(GAME game/main.cpp game/engine.cpp) set(GAME_HEADER game/mwinput/inputmanager.hpp game/engine.hpp) @@ -38,7 +38,7 @@ set(ESM_STORE_HEADER esm_store/cell_store.hpp esm_store/reclists.hpp esm_store/s set(GAMEREND game/mwrender/mwscene.cpp game/mwrender/cell.cpp game/mwrender/interior.cpp) set(GAMEREND_HEADER game/mwrender/cell.hpp game/mwrender/mwscene.hpp - game/mwrender/interior.hpp) + game/mwrender/interior.hpp game/mwrender/playerpos.hpp) set(ESM_HEADER esm/defs.hpp esm/loadcell.hpp esm/loadfact.hpp esm/loadltex.hpp esm/loadskil.hpp diff --git a/game/engine.cpp b/game/engine.cpp index f7855847c..e23f8272a 100644 --- a/game/engine.cpp +++ b/game/engine.cpp @@ -11,6 +11,7 @@ #include "mwrender/interior.hpp" #include "mwinput/inputmanager.hpp" +#include "mwrender/playerpos.hpp" OMW::Engine::Engine() {} @@ -118,9 +119,12 @@ void OMW::Engine::go() std::cout << "\nSetting up cell rendering\n"; - // Sets up camera, scene manager etc + // Sets up camera, scene manager, and viewport. MWRender::MWScene scene(mOgre); + // Used to control the player camera and position + MWRender::PlayerPos player(scene.getCamera()); + // This connects the cell data with the rendering scene. MWRender::InteriorCellRender rend(cell, scene); @@ -130,7 +134,7 @@ void OMW::Engine::go() std::cout << "Setting up input system\n"; // Sets up the input system - MWInput::MWInputManager input(mOgre); + MWInput::MWInputManager input(mOgre, player); std::cout << "\nStart! Press Q/ESC or close window to exit.\n"; diff --git a/game/mwinput/inputmanager.hpp b/game/mwinput/inputmanager.hpp index eeee5cf82..763d1a487 100644 --- a/game/mwinput/inputmanager.hpp +++ b/game/mwinput/inputmanager.hpp @@ -1,9 +1,11 @@ -#ifndef _INPUT_MWINPUTMANAGER_H -#define _INPUT_MWINPUTMANAGER_H +#ifndef _MWINPUT_MWINPUTMANAGER_H +#define _MWINPUT_MWINPUTMANAGER_H #include "input/listener.hpp" #include "input/dispatcher.hpp" +#include "input/poller.hpp" #include "boost/bind.hpp" +#include "game/mwrender/playerpos.hpp" namespace MWInput { @@ -11,21 +13,35 @@ namespace MWInput { A_Quit, // Exit the program + A_MoveLeft, // Move player left / right + A_MoveRight, + A_MoveUp, // Move up / down + A_MoveDown, + A_MoveForward, // Forward / Backward + A_MoveBackward, + A_LAST // Marker for the last item }; // Class that handles all input and key bindings for OpenMW - class MWInputManager + class MWInputManager : public Ogre::FrameListener { + // Note: the order here is important. The OISManager must be + // initialized before poller and listener. Input::Dispatcher disp; Input::OISManager input; + Input::Poller poller; Input::InputListener listener; + MWRender::PlayerPos &player; public: - MWInputManager(Render::OgreRenderer &ogre) + MWInputManager(Render::OgreRenderer &ogre, + MWRender::PlayerPos &_player) : disp(A_LAST), input(ogre), - listener(ogre, input, disp) + poller(input), + listener(ogre, input, disp), + player(_player) { using namespace Input; using namespace OIS; @@ -35,9 +51,56 @@ namespace MWInput boost::bind(&InputListener::exitNow, &listener), "Quit program"); + // Add ourselves as a frame listener, to catch movement keys + ogre.getRoot()->addFrameListener(this); + // Key bindings disp.bind(KC_Q, A_Quit); disp.bind(KC_ESCAPE, A_Quit); + + // Key bindings for polled keys + + // Arrow keys + poller.bind(A_MoveLeft, KC_LEFT); + poller.bind(A_MoveRight, KC_RIGHT); + poller.bind(A_MoveForward, KC_UP); + poller.bind(A_MoveBackward, KC_DOWN); + + // WASD keys + poller.bind(A_MoveLeft, KC_A); + poller.bind(A_MoveRight, KC_D); + poller.bind(A_MoveForward, KC_W); + poller.bind(A_MoveBackward, KC_D); + + // Use shift and ctrl for up and down + poller.bind(A_MoveUp, KC_LSHIFT); + poller.bind(A_MoveDown, KC_LCONTROL); + } + + // Used to check for movement keys + bool frameStarted(const Ogre::FrameEvent &evt) + { + float speed = 300 * evt.timeSinceLastFrame; + float moveX = 0, moveY = 0, moveZ = 0; + + using namespace std; + + if(poller.isDown(A_MoveLeft)) moveX -= speed; + if(poller.isDown(A_MoveRight)) moveX += speed; + if(poller.isDown(A_MoveForward)) moveZ -= speed; + if(poller.isDown(A_MoveBackward)) moveZ += speed; + + // TODO: These should be enabled for floating modes (like + // swimming and levitation) and disabled for everything else. + if(poller.isDown(A_MoveUp)) moveY += speed; + if(poller.isDown(A_MoveDown)) moveY -= speed; + + if(moveX == 0 && moveY == 0 && moveZ == 0) + return true; + + player.moveRel(moveX, moveY, moveZ); + + return true; } }; } diff --git a/game/mwrender/playerpos.hpp b/game/mwrender/playerpos.hpp new file mode 100644 index 000000000..51906aca8 --- /dev/null +++ b/game/mwrender/playerpos.hpp @@ -0,0 +1,56 @@ +#ifndef _MWRENDER_PLAYERPOS_H +#define _MWRENDER_PLAYERPOS_H + +#include "OgreCamera.h" + +namespace MWRender +{ + // This class keeps track of the player position. It takes care of + // camera movement, sound listener updates, and collision handling + // (to be done). + class PlayerPos + { + float x, y, z; + Ogre::Camera *camera; + + public: + PlayerPos(Ogre::Camera *cam) : + camera(cam), x(0), y(0), z(0) {} + + // Set the player position. Uses Morrowind coordinates. + void setPos(float _x, float _y, float _z) + { + x = _x; + y = _y; + z = _z; + + // TODO: Update sound listener + } + + // Move the player relative to her own position and + // orientation. After the call, the new position is returned. + void moveRel(float &relX, float &relY, float &relZ) + { + using namespace Ogre; + + // Move camera relative to its own direction + camera->moveRelative(Vector3(relX,0,relZ)); + + // Up/down movement is always done relative the world axis. + camera->move(Vector3(0,relY,0)); + + // Get new camera position, converting back to MW coords. + Vector3 pos = camera->getPosition(); + relX = pos[0]; + relY = -pos[2]; + relZ = pos[1]; + + // TODO: Collision detection must be used to find the REAL new + // position. + + // Set the position + setPos(relX, relY, relZ); + } + }; +} +#endif diff --git a/input/listener.hpp b/input/listener.hpp index 38f899215..4c4b80c56 100644 --- a/input/listener.hpp +++ b/input/listener.hpp @@ -24,6 +24,9 @@ namespace Input mMouse = input.mouse; mKeyboard = input.keyboard; + assert(mKeyboard); + assert(mWindow); + // Add ourself to the managers rend.getRoot() -> addFrameListener(this); mKeyboard -> setEventCallback(this); diff --git a/input/poller.hpp b/input/poller.hpp new file mode 100644 index 000000000..e7d712b35 --- /dev/null +++ b/input/poller.hpp @@ -0,0 +1,51 @@ +#ifndef _INPUT_POLLER_H +#define _INPUT_POLLER_H + +#include "dispatch_map.hpp" +#include "oismanager.hpp" + +namespace Input { + +/** The poller is used to check (poll) for keys rather than waiting + for events. TODO: Might make this OIS-independent later. */ +struct Poller +{ + DispatchMap map; + OIS::Keyboard *keyboard; + + Poller(Input::OISManager &ois) + { + keyboard = ois.keyboard; + assert(keyboard); + } + + /** Bind or unbind a given action with a key. The action is the first + parameter, the key is the second. + */ + void bind(int in, int out) { map.bind(in, out); } + void unbind(int in, int out) { map.unbind(in, out); } + bool isBound(int in) const { return map.isBound(in); } + + /// Check whether a given action button is currently pressed. + typedef DispatchMap::OutList _O; + bool isDown(int index) const + { + assert(keyboard); + + // No bindings, no action + if(!isBound(index)) + return false; + + // Get all the keys bound to this action, and check them. + const _O &list = map.getList(index); + _O::const_iterator it; + for(it = list.begin(); it != list.end(); it++) + // If there's any match, we're good to go. + if(keyboard->isKeyDown((OIS::KeyCode)*it)) return true; + + return false; + } +}; + +} +#endif diff --git a/old_d_version/ogre/cpp_framelistener.cpp b/old_d_version/ogre/cpp_framelistener.cpp index 46427a03b..b9e09052c 100644 --- a/old_d_version/ogre/cpp_framelistener.cpp +++ b/old_d_version/ogre/cpp_framelistener.cpp @@ -130,11 +130,6 @@ InputListener mInput; // Functions called from D during event handling -extern "C" int32_t ois_isPressed(int32_t keysym) -{ - return mKeyboard->isKeyDown((OIS::KeyCode)keysym); -} - // Dump screen contents to file extern "C" void ogre_screenshot(char* filename) { @@ -160,15 +155,6 @@ extern "C" void ogre_rotateCamera(float x, float y) mCamera->setOrientation(nopitch); } -// Get current camera position -extern "C" void ogre_getCameraPos(float *x, float *y, float *z) -{ - Vector3 pos = mCamera->getPosition(); - *x = pos[0]; - *y = -pos[2]; - *z = pos[1]; -} - // Get current camera orientation, in the form of 'front' and 'up' // vectors. extern "C" void ogre_getCameraOrientation(float *fx, float *fy, float *fz, @@ -212,12 +198,3 @@ extern "C" void ogre_setCameraRotation(float r1, float r2, float r3) // Rotates first around z, then y, then x mCamera->setOrientation(xr*yr*zr); } - -// Move camera relative to its own axis set. -extern "C" void ogre_moveCameraRel(float x, float y, float z) -{ - mCamera->moveRelative(Vector3(x,0,z)); - - // up/down movement is always done relative the world axis - mCamera->move(Vector3(0,y,0)); -}