diff --git a/asteroids/AsteroidsEnums.h b/asteroids/AsteroidsEnums.h index e8107c8..281f8a1 100644 --- a/asteroids/AsteroidsEnums.h +++ b/asteroids/AsteroidsEnums.h @@ -27,6 +27,7 @@ BEGIN_ENUM(GameState) DECL_ENUM_ELEMENT(GameStatePlayerDied), DECL_ENUM_ELEMENT(GameStateLevelComplete), DECL_ENUM_ELEMENT(GameStateShowHighscore), + DECL_ENUM_ELEMENT(GameStateEnterPlayername), DECL_ENUM_ELEMENT(GameStateGameOver) } END_ENUM(GameState) diff --git a/asteroids/Model.cc b/asteroids/Model.cc index a6500a5..d37e314 100644 --- a/asteroids/Model.cc +++ b/asteroids/Model.cc @@ -80,7 +80,8 @@ void Model::Process () { // some action. Engine::LogDebug ("Switching from %s->%s", GetStringGameState(mLastGameState), GetStringGameState(mGameState)); - if (mLastGameState == GameStateMainMenu && mGameState == GameStateRunning) { + if ( (mLastGameState == GameStateMainMenu && mGameState == GameStateRunning) + || (mLastGameState == GameStateEnterPlayername && mGameState == GameStateRunning)){ OnNewGame(); } else if (mLastGameState == GameStateRunning && mGameState == GameStatePlayerDied) { @@ -92,13 +93,14 @@ void Model::Process () { Engine::EventBasePtr gameover_event (new Engine::EventBase()); gameover_event->mEventType = EventGameOver; QueueEvent (gameover_event); - //mGameState = GameStateGameOver; } } else if (mLastGameState == GameStateLevelComplete && mGameState == GameStateRunning) { mCurrentLevelIndex++; if (mCurrentLevelIndex == mLevelList.size()) { - SetGameState(GameStateGameOver); + Engine::EventBasePtr gameover_event (new Engine::EventBase()); + gameover_event->mEventType = EventGameOver; + QueueEvent (gameover_event); } else { DoLoadLevel(mLevelList[mCurrentLevelIndex].c_str()); } @@ -345,8 +347,10 @@ int Model::DoSaveLevel (const char* filename) { bool Model::OnLevelComplete() { Engine::LogMessage ("Level complete!"); - if (mCurrentLevelIndex + 1== mLevelList.size()) { - SetGameState(GameStateGameOver); + if (mCurrentLevelIndex + 1 == mLevelList.size()) { + Engine::EventBasePtr gameover_event (new Engine::EventBase()); + gameover_event->mEventType = EventGameOver; + QueueEvent (gameover_event); } else { SetGameState (GameStateLevelComplete); } @@ -355,7 +359,7 @@ bool Model::OnLevelComplete() { } bool Model::OnGameOver() { - Engine::LogMessage ("Points = %d lowest = %d", mPoints,mHighscoreList.back().points ); + Engine::LogMessage ("Points = %d lowest = %d", mPoints, mHighscoreList.back().points ); if (mPoints > mHighscoreList.back().points) { Engine::LogMessage ("New Highscore!"); AddHighscoreEntry (mPlayerName, mPoints); diff --git a/asteroids/UserInterface.cc b/asteroids/UserInterface.cc index 191a067..7960e69 100644 --- a/asteroids/UserInterface.cc +++ b/asteroids/UserInterface.cc @@ -9,6 +9,7 @@ #include "UserInterface.h" #include "Model.h" #include "View.h" +#include "Controller.h" #include "Sprite.h" #include "ShipEntity.h" @@ -35,7 +36,7 @@ bool MainMenuOverlay::OnKeyDown (const SDL_keysym &keysym) { Engine::RunCommand ("quit"); return true; case SDLK_RETURN: - GetModel()->SetGameState(GameStateRunning); + GetModel()->SetGameState(GameStateEnterPlayername); return true; case SDLK_h: GetModel()->SetGameState(GameStateShowHighscore); @@ -73,7 +74,8 @@ void MainMenuOverlay::Draw () { Engine::DrawGLString ( right * 0.5 - 100, bottom * 0.5 - 8 - 64, "A s t e r o i d s"); Engine::DrawGLString ( right * 0.5 - 100, bottom * 0.5 - 8 - 32, "Main Menu"); Engine::DrawGLString ( right * 0.5 - 80, bottom * 0.5 - 8 - 16, "[Return] - Start Game"); - Engine::DrawGLString ( right * 0.5 - 80, bottom * 0.5 - 8, "[Escape] - Quit"); + Engine::DrawGLString ( right * 0.5 - 80, bottom * 0.5 - 8, "[h] - Show Highscore"); + Engine::DrawGLString ( right * 0.5 - 80, bottom * 0.5 + 8, "[Escape] - Quit"); glPopMatrix (); @@ -174,10 +176,10 @@ void GameOverOverlay::Init () { bool GameOverOverlay::OnKeyDown (const SDL_keysym &keysym) { switch (keysym.sym) { case SDLK_ESCAPE: - GetModel()->SetGameState(GameStateMainMenu); + GetModel()->SetGameState(GameStateShowHighscore); break; case SDLK_RETURN: - GetModel()->SetGameState(GameStateMainMenu); + GetModel()->SetGameState(GameStateShowHighscore); break; default: break; @@ -424,15 +426,6 @@ bool HighscoreOverlay::OnKeyDown (const SDL_keysym &keysym) { switch (keysym.sym) { case SDLK_ESCAPE: case SDLK_RETURN: - // If we just entered a new entry we simply show the highscore table, - // otherwise we switch back to the main menu - if (GetModel()->mNewestHighscoreEntryIndex < GetModel()->mHighscoreList.size()) { - GetModel()->mNewestHighscoreEntryIndex = GetModel()->mHighscoreList.size(); - SDL_EnableUNICODE(-1); - SDL_EnableKeyRepeat(0,100); - - return true; - } GetModel()->SetGameState(GameStateMainMenu); return true; @@ -443,7 +436,7 @@ bool HighscoreOverlay::OnKeyDown (const SDL_keysym &keysym) { } void HighscoreOverlay::Draw () { - glClearColor (0., 0., 0., 1.); + glClearColor (0.1, 0.1, 0.1, 1.); right = static_cast (Engine::GetWindowWidth()); bottom = static_cast (Engine::GetWindowHeight()); @@ -531,4 +524,95 @@ void HighscoreOverlay::Draw () { }; +/********************** + * + * EnterPlayername + * + **********************/ + +void EnterPlayernameOverlay::Init () { + mPlayerNameInput = "Starkiller"; +} + +bool EnterPlayernameOverlay::OnKeyDown (const SDL_keysym &keysym) { + GetController()->EnableTextinput(true); + + switch (keysym.sym) { + case SDLK_ESCAPE: + GetModel()->SetGameState(GameStateMainMenu); + return true; + case SDLK_BACKSPACE: + if (mPlayerNameInput.size() > 0) + mPlayerNameInput = mPlayerNameInput.substr (0, mPlayerNameInput.size() - 1 ); + return true; + break; + case SDLK_RETURN: + // If we just entered a new entry we simply show the highscore table, + // otherwise we switch back to the main menu + GetModel()->SetPlayerName(mPlayerNameInput); + GetController()->EnableTextinput(false); + GetModel()->SetGameState(GameStateRunning); + return true; + default: + break; + } + + if (keysym.unicode) { + if ((keysym.unicode & 0xFF80) == 0) { + mPlayerNameInput += keysym.unicode & 0x7F; + return true; + } else { + Engine::LogWarning ("Input key not supported!"); + return false; + } + } + + return true; +} + +void EnterPlayernameOverlay::Draw () { + glClearColor (0.1, 0.1, 0.1, 1.); + + right = static_cast (Engine::GetWindowWidth()); + bottom = static_cast (Engine::GetWindowHeight()); + + // we switch to orthographic projection and draw the contents of the 2d + // overlay on top of the previous drawings + glMatrixMode (GL_PROJECTION); + glPushMatrix (); + glLoadIdentity (); + + // first we have to get the size of the current viewport to set up the + // orthographic projection correctly + GLint viewport[4]; + glGetIntegerv(GL_VIEWPORT, viewport); + gluOrtho2D (viewport[0], viewport[2], viewport[3], viewport[1]); + + glMatrixMode (GL_MODELVIEW); + glPushMatrix (); + glLoadIdentity (); + + GetView()->SelectFont("console.ttf"); + float x = right * 0.5 - 100; + float y = bottom * 0.5 - 8 - 128; + + // then we do the drawings + Engine::DrawGLString ( x, y, "A s t e r o i d s"); + y += 30; + Engine::DrawGLString ( x, y, "Enter your name: "); + + std::string name_output (mPlayerNameInput); + name_output += "_"; + Engine::DrawGLString ( x + 15*8, y, name_output.c_str()); + Engine::DrawGLString ( x + 16, y + 16, "Press [Return] to continue."); + + glPopMatrix (); + + glMatrixMode (GL_PROJECTION); + glPopMatrix (); + + glMatrixMode (GL_MODELVIEW); + +}; + } diff --git a/asteroids/UserInterface.h b/asteroids/UserInterface.h index 98df575..5e7a141 100644 --- a/asteroids/UserInterface.h +++ b/asteroids/UserInterface.h @@ -7,6 +7,7 @@ class OverlayBase; #include "OverlayBase.h" #include "Sprite.h" +#include namespace asteroids { @@ -103,6 +104,21 @@ class HighscoreOverlay : public Engine::OverlayBase { virtual void Draw (); }; +class EnterPlayernameOverlay : public Engine::OverlayBase { + public: + EnterPlayernameOverlay () { + }; + virtual ~EnterPlayernameOverlay() {}; + + virtual void Init (); + + virtual bool OnKeyDown (const SDL_keysym &keysym); + virtual void Draw (); + + private: + std::string mPlayerNameInput; +}; + } #endif /* USERINTERFACE */ diff --git a/asteroids/View.cc b/asteroids/View.cc index d7f62ba..983b1e5 100644 --- a/asteroids/View.cc +++ b/asteroids/View.cc @@ -37,6 +37,7 @@ int View::OnInit (int argc, char* argv[]) { Engine::OverlayBasePtr game_paused_overlay (new GamePausedOverlay); Engine::OverlayBasePtr player_died_overlay (new PlayerDiedOverlay); Engine::OverlayBasePtr highscore_overlay (new HighscoreOverlay); + Engine::OverlayBasePtr enterplayername_overlay (new EnterPlayernameOverlay); mOverlayManager.Register (menu_overlay, GameStateMainMenu); mOverlayManager.Register (game_running_overlay, GameStateRunning); @@ -45,6 +46,7 @@ int View::OnInit (int argc, char* argv[]) { mOverlayManager.Register (player_died_overlay, GameStatePlayerDied); mOverlayManager.Register (game_paused_overlay, GameStatePaused); mOverlayManager.Register (highscore_overlay, GameStateShowHighscore); + mOverlayManager.Register (enterplayername_overlay, GameStateEnterPlayername); mOverlayManager.InitOverlays(); diff --git a/engine/ControllerBase.cc b/engine/ControllerBase.cc index e295a03..269df1c 100644 --- a/engine/ControllerBase.cc +++ b/engine/ControllerBase.cc @@ -130,6 +130,17 @@ void ControllerBase::ProcessEvents () { } } +/** \brief Activates or deactivates unicode processing and key delays of the keyboard inputs */ +void ControllerBase::EnableTextinput (bool textinput_state) { + if (textinput_state) { + SDL_EnableUNICODE(1); + SDL_EnableKeyRepeat(500, 50); + } else { + SDL_EnableUNICODE(-1); + SDL_EnableKeyRepeat(0, 100); + } +} + /** \brief Keyboard processing */ bool ControllerBase::OnKeyDown (const SDL_keysym &keysym) { if (mView->mOverlayManager.SendKeyDown (keysym)) diff --git a/engine/ControllerBase.h b/engine/ControllerBase.h index 483f031..6a5f3da 100644 --- a/engine/ControllerBase.h +++ b/engine/ControllerBase.h @@ -44,6 +44,9 @@ class ControllerBase : public Module { } bool BindKey (int key, const char *command); + /** \brief Activates or deactivates unicode processing and key delays of the keyboard inputs */ + void EnableTextinput (bool textinput_state); + protected: /** \brief Initializes the system */ virtual int OnInit (int argc, char* argv[]); diff --git a/engine/Engine.h b/engine/Engine.h index 6399d0e..a063cc5 100644 --- a/engine/Engine.h +++ b/engine/Engine.h @@ -27,7 +27,7 @@ * have to know the number of bits that are to be reserved in advance so this * is hard coded into the library for now. */ -#define ENTITY_CONTROLLER_MAX_KEY_STATES 64 +const int EntityControllerMaxKeyStates = 64; namespace Engine { diff --git a/engine/EntityBase.cc b/engine/EntityBase.cc index bb3d39a..5edd221 100644 --- a/engine/EntityBase.cc +++ b/engine/EntityBase.cc @@ -5,20 +5,20 @@ namespace Engine { bool EntityControllerState::GetKey (int state) { - assert (state < ENTITY_CONTROLLER_MAX_KEY_STATES && state >= 0); + assert (state < EntityControllerMaxKeyStates && state >= 0); return mKeyState.test (state); } void EntityControllerState::SetKey (int state) { - assert (state < ENTITY_CONTROLLER_MAX_KEY_STATES && state >= 0); + assert (state < EntityControllerMaxKeyStates && state >= 0); LogDebug ("Setting Entity Key State %d", state); mKeyState.set (state); } void EntityControllerState::UnsetKey (int state) { - assert (state < ENTITY_CONTROLLER_MAX_KEY_STATES && state >= 0); + assert (state < EntityControllerMaxKeyStates && state >= 0); LogDebug ("Unsetting Entity Key State %d", state); mKeyState.reset (state); diff --git a/engine/EntityBase.h b/engine/EntityBase.h index 0c466c8..a9ce23f 100644 --- a/engine/EntityBase.h +++ b/engine/EntityBase.h @@ -100,7 +100,7 @@ struct EntityPhysicState { * \todo [Low] The current design is very unflexible. Is there a better way? */ struct EntityControllerState { - std::bitset mKeyState; + std::bitset mKeyState; bool GetKey (int state); void SetKey (int state); diff --git a/engine/SimpleConsoleOverlay.cc b/engine/SimpleConsoleOverlay.cc index 2f40ad0..65482b9 100644 --- a/engine/SimpleConsoleOverlay.cc +++ b/engine/SimpleConsoleOverlay.cc @@ -1,6 +1,7 @@ #include "DrawingsGL.h" #include "OverlayBase.h" #include "SimpleConsoleOverlay.h" +#include "ControllerBase.h" #include "OGLFT.h" @@ -16,10 +17,10 @@ bool SimpleConsoleOverlay::OnKeyDown (const SDL_keysym &keysym) { if (mActive) { // We have to call SetActive() to actually // activate the unicode processing of SDL - SetActive (false); + EngineGetController()->EnableTextinput(false); } else { - SetActive (true); + EngineGetController()->EnableTextinput(true); } return true; @@ -31,7 +32,7 @@ bool SimpleConsoleOverlay::OnKeyDown (const SDL_keysym &keysym) { // check for input that requires actions switch (keysym.sym) { case SDLK_ESCAPE: - SetActive (false); + EngineGetController()->EnableTextinput(false); return true; break; case SDLK_BACKSPACE: