diff --git a/Bin/VC10/VC10.vcxproj b/Bin/VC10/VC10.vcxproj index 3336f69..6107e44 100644 --- a/Bin/VC10/VC10.vcxproj +++ b/Bin/VC10/VC10.vcxproj @@ -100,6 +100,7 @@ + @@ -128,6 +129,8 @@ + + @@ -145,6 +148,7 @@ + @@ -167,6 +171,8 @@ + + diff --git a/Bin/VC10/VC10.vcxproj.filters b/Bin/VC10/VC10.vcxproj.filters index 52683a1..8424bb1 100644 --- a/Bin/VC10/VC10.vcxproj.filters +++ b/Bin/VC10/VC10.vcxproj.filters @@ -46,6 +46,9 @@ {2826112d-5f07-4ee2-b4b4-2be9289c6811} + + {da9ad984-368f-4f6f-8f68-648733ae3a44} + @@ -183,6 +186,15 @@ Animation + + UI + + + Main + + + UI + @@ -296,5 +308,14 @@ Animation + + UI + + + Main + + + UI + \ No newline at end of file diff --git a/src/Font/Font.cpp b/src/Font/Font.cpp index f06b2f6..247ddd5 100644 --- a/src/Font/Font.cpp +++ b/src/Font/Font.cpp @@ -19,8 +19,8 @@ Font::~Font(void) { } } -bool Font::Load(const std::string& filename) { - TTF_Font* font = TTF_OpenFont(filename.c_str(), 16); +bool Font::Load(const std::string& filename, int size) { + TTF_Font* font = TTF_OpenFont(filename.c_str(), size); if(!font) { Debug::logger->message("Error loading %s: %s", filename.c_str(), TTF_GetError()); return false; @@ -94,7 +94,7 @@ bool Font::Load(const std::string& filename) { return true; } -void Font::DrawText(int xOffset, int yOffset, const char* text) { +void Font::RenderText(int xOffset, int yOffset, const char* text) { glEnable(GL_TEXTURE_2D); BindTexture(_texture); @@ -159,3 +159,24 @@ void Font::DrawText(int xOffset, int yOffset, const char* text) { glColor4f(1.0f, 1.0f, 1.0f, 1.0f); } + +void Font::TextSize(const char* text, int& width, int& height) { + width = 0; + height = _lineSkip; + + int textLength = strlen(text); + for(int i = 0; i < textLength; i++) { + char c = text[i]; + if(c == '\n') { + height += _lineSkip; + continue; + } else if(c == ' ') { + width += _spaceWidth; + continue; + } else if(c == '\t') { + width += _tabWidth; + continue; + } + width += _characters[(int)c].advance; + } +} diff --git a/src/Font/Font.h b/src/Font/Font.h index 28356f6..5c85738 100644 --- a/src/Font/Font.h +++ b/src/Font/Font.h @@ -16,16 +16,15 @@ struct FontChar { int advance; }; -class Font : public Resource { - template friend class ResourceManager; - +class Font { public: Font(void); ~Font(void); - bool Load(const std::string& filename); + bool Load(const std::string& filename, int size); - void DrawText(int xOffset, int yOffset, const char* text); + void RenderText(int xOffset, int yOffset, const char* text); + void TextSize(const char* text, int& width, int& height); int GetLineSkip() const { return _lineSkip; } float* GetColor() { return _color; } diff --git a/src/Main/Game.cpp b/src/Main/Game.cpp index 36a032e..80e95a5 100644 --- a/src/Main/Game.cpp +++ b/src/Main/Game.cpp @@ -12,8 +12,10 @@ #include "../System/Debug.h" #include "../Sprite/Sprite.h" #include "../Texture/Texture.h" + #include "../Level/Level.h" #include "Game.h" +#include "TitleScreen.h" Game::Game(void) { _level = new Level(); @@ -23,8 +25,13 @@ Game::Game(void) { _NPC->SetXY(30.0f, 30.0f); _testFont = new Font(); - _testFont->Load("../Data/Font/Fairydust.ttf"); + _testFont->Load("../Data/Font/Fairydust.ttf", 24); _testFont->SetColor(0.0f, 1.0f, 1.0f, 1.0f); + + _titleScreen = new TitleScreen(); + _inTitleScreen = true; + + _running = true; } Game::~Game(void) { @@ -56,7 +63,80 @@ void Game::Prepare(float dt) { void Game::Render(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + if(_inTitleScreen) { + RenderTitle(); + } else { + RenderGame(); + } +} +void Game::Shutdown(void) { + Debug::logger->message("\n ----- Cleaning Engine -----"); + delete _testFont; + delete _NPC; + delete _player; + delete _level; + delete _titleScreen; +} + +void Game::ProcessEvents(float dt) { + if(_inTitleScreen) { + UpdateTitle(dt); + } else { + UpdateGame(dt); + } +} + +void Game::OnResize(int width, int height) { + glViewport(0, 0, width, height); + + windowWidth = width; + windowHeight = height; + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0.0, (GLdouble)windowWidth, (GLdouble)windowHeight, 0.0, 0.0, 1.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + +void Game::UpdateTitle(float dt) { + _titleScreen->Update(dt); + + if(!_titleScreen->IsAlive()) { + switch(_titleScreen->GetResult()) { + case TitleScreen::QUIT: + _running = false; + break; + + case TitleScreen::NEW_GAME: + _inTitleScreen = false; + break; + } + } +} + +void Game::UpdateGame(float dt) { + _player->Update(dt); + _NPC->Update(dt); + _level->Update(dt); +} + +void Game::RenderTitle(void) { + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glDisable(GL_DEPTH_TEST); + glDisable(GL_ALPHA_TEST); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + _titleScreen->Render(); +} + +void Game::RenderGame(void) { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); @@ -80,35 +160,8 @@ void Game::Render(void) { _level->Draw(xOffset, yOffset); _player->Render(); _NPC->Render(); - _testFont->DrawText( + _testFont->RenderText( _player->GetX() - 5, _player->GetY() - _testFont->GetLineSkip() - 2, "Miss D"); } - -void Game::Shutdown(void) { - Debug::logger->message("\n ----- Cleaning Engine -----"); - delete _testFont; - delete _NPC; - delete _player; - delete _level; -} - -void Game::ProcessEvents(float dt) { - _player->Update(dt); - _NPC->Update(dt); -} - -void Game::OnResize(int width, int height) { - glViewport(0, 0, width, height); - - windowWidth = width; - windowHeight = height; - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0.0, (GLdouble)windowWidth, (GLdouble)windowHeight, 0.0, 0.0, 1.0); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); -} diff --git a/src/Main/Game.h b/src/Main/Game.h index d80066b..254b83b 100644 --- a/src/Main/Game.h +++ b/src/Main/Game.h @@ -6,6 +6,8 @@ class Sprite; class Level; +class Button; +class TitleScreen; class Game { public: @@ -21,9 +23,22 @@ public: void OnResize(int width, int height); + bool IsRunning() { return _running; } + void SetRunning(bool running) { _running = running; } + private: + void UpdateTitle(float dt); + void UpdateGame(float dt); + void RenderTitle(void); + void RenderGame(void); + Font* _testFont; Player* _player; NPC* _NPC; Level* _level; + + TitleScreen* _titleScreen; + bool _inTitleScreen; + + bool _running; }; diff --git a/src/Main/TitleScreen.cpp b/src/Main/TitleScreen.cpp new file mode 100644 index 0000000..b67108d --- /dev/null +++ b/src/Main/TitleScreen.cpp @@ -0,0 +1,61 @@ +#include "TitleScreen.h" +#include "../Font/Font.h" +#include "../UI/Button.h" +#include "../Global/Globals.h" + +TitleScreen::TitleScreen(void) { + _alive = true; + _result = TitleScreen::QUIT; + + _font = new Font(); + _font->Load("../Data/Font/fairydust.ttf", 24); + + Button* newGameButton = new Button(); + Button* loadGameButton = new Button(); + Button* quitButton = new Button(); + + newGameButton->SetFont(_font); + loadGameButton->SetFont(_font); + quitButton->SetFont(_font); + + newGameButton->SetText("New Game"); + loadGameButton->SetText("Load Game"); + quitButton->SetText("Quit"); + + _menu.AddButton(newGameButton); + _menu.AddButton(loadGameButton); + _menu.AddButton(quitButton); + _menu.AlignButtons(Menu::ALIGN_VERTICALLY); + _menu.SetXY(32, windowHeight - 128); +} + +TitleScreen::~TitleScreen(void) { + if(_font) { + delete _font; + _font = NULL; + } +} + +void TitleScreen::Update(float dt) { + _menu.Update(); + switch(_menu.GetTriggeredButton()) { + case 0: + _alive = false; + _result = TitleScreen::NEW_GAME; + break; + + case 1: + _alive = false; + _result = TitleScreen::LOAD_GAME; + break; + + case 2: + _alive = false; + _result = TitleScreen::QUIT; + break; + } +} + +void TitleScreen::Render(void) { + _menu.Render(); +} diff --git a/src/Main/TitleScreen.h b/src/Main/TitleScreen.h new file mode 100644 index 0000000..7555bc9 --- /dev/null +++ b/src/Main/TitleScreen.h @@ -0,0 +1,30 @@ +#pragma once + +#include "../UI/Menu.h" + +class Font; + +class TitleScreen { +public: + enum { + NEW_GAME, + LOAD_GAME, + QUIT + }; + + TitleScreen(void); + ~TitleScreen(void); + + void Update(float dt); + void Render(void); + + bool IsAlive(void) { return _alive; } + int GetResult(void) { return _result; } + +private: + bool _alive; + int _result; + + Font* _font; + Menu _menu; +}; \ No newline at end of file diff --git a/src/Main/main.cpp b/src/Main/main.cpp index 19ac5d3..3a01324 100644 --- a/src/Main/main.cpp +++ b/src/Main/main.cpp @@ -99,12 +99,11 @@ int main(int argc, char** argv) { // screws up for me. -- Allanis. game.OnResize(windowWidth, windowHeight); - bool isRunning = true; - while(isRunning) { + while(game.IsRunning()) { while(SDL_PollEvent(&event)) { if((event.type == SDL_QUIT) || KeyStillDown(SDLK_ESCAPE)) { - isRunning = false; + game.SetRunning(false); break; } if(event.type == SDL_VIDEORESIZE) { diff --git a/src/UI/Button.cpp b/src/UI/Button.cpp new file mode 100644 index 0000000..34f160c --- /dev/null +++ b/src/UI/Button.cpp @@ -0,0 +1,58 @@ +#include "Button.h" +#include "../Font/Font.h" +#include "../IO/Input.h" + +Button::Button(void) { + _text = ""; + _font = NULL; + _highlighted = false; + _triggered = false; + x = 0; + y = 0; + w = 0; + h = 0; +} + +void Button::Update(void) { + _triggered = false; + + int mouseX = ::GetX(); + int mouseY = ::GetY(); + + if((mouseX >= x) && (mouseX < (x + w)) && + (mouseY >= y) && (mouseY < (y + h))) + { + _highlighted = true; + if(MouseUp(SDL_BUTTON(1))) { + _triggered = true; + } + } else { + _highlighted = false; + } +} + +void Button::Render(void) { + if(_font) { + if(_highlighted) { + _font->SetColor(1.0f, 1.0f, 1.0f, 1.0f); + } else { + _font->SetColor(0.5f, 0.5f, 0.5f, 1.0f); + } + _font->RenderText(x, y, _text.GetPointer()); + _font->SetColor(1.0f, 1.0f, 1.0f, 1.0f); + } +} + +void Button::SetFont(Font* font) { + _font = font; + if(_text.Length() > 0) { + font->TextSize(_text.GetPointer(), w, h); + } +} + +void Button::SetText(const String& text) { + _text = text; + if((_text.Length() > 0) && _font) { + _font->TextSize(text.GetPointer(), w, h); + } +} diff --git a/src/UI/Button.h b/src/UI/Button.h new file mode 100644 index 0000000..31b7deb --- /dev/null +++ b/src/UI/Button.h @@ -0,0 +1,44 @@ +#pragma once + +#include "../System/String.h" +#include "../Font/Font.h" + +class Button { +public: + Button(void); + + void Update(void); + void Render(void); + + Font* GetFont(void) { return _font; } + void SetFont(Font* font); + + const String& GetText(void) const { return _text;} + void SetText(const String& text); + + bool IsHighlighted(void) const { return _highlighted; } + void SetHighlighted(bool highlighted) { _highlighted = highlighted; } + + bool Triggered(void) const { return _triggered; } + + int GetX(void) const { return x; } + int GetY(void) const { return y; } + void SetX(int x) { this->x = x; } + void SetY(int y) { this->y = y; } + void SetXY(int x, int y) { SetX(x); SetY(y); } + + int GetWidth(void) const { return w; } + int GetHeight(void) const { return h; } + +private: + Font* _font; + String _text; + + bool _highlighted; + bool _triggered; + + int x; + int y; + int w; + int h; +}; diff --git a/src/UI/Menu.cpp b/src/UI/Menu.cpp new file mode 100644 index 0000000..58baf71 --- /dev/null +++ b/src/UI/Menu.cpp @@ -0,0 +1,67 @@ +#include "Menu.h" +#include "Button.h" + +Menu::Menu(void) { + _triggeredButton = -1; + x = 0; + y = 0; +} + +Menu::~Menu(void) { + for(std::list::iterator i = _buttons.begin(); i != _buttons.end(); ++i) { + delete (*i); + } + _buttons.clear(); +} + +void Menu::AddButton(Button* button) { + _buttons.push_back(button); +} + +void Menu::AlignButtons(int how) { + int x = 0; + int y = 0; + for(std::list::iterator i = _buttons.begin(); i != _buttons.end(); ++i) { + Button* button = (*i); + button->SetXY(x, y); + + if(how == Menu::ALIGN_HORIZONTALLY) { + x += button->GetWidth() + 24; + } else if(how == Menu::ALIGN_VERTICALLY) { + y += button->GetHeight() + 2; + } + } +} + +void Menu::Update(void) { + _triggeredButton = -1; + + int index = 0; + for(std::list::iterator i = _buttons.begin(); i != _buttons.end(); ++i) { + Button* button = (*i); + + int oldX = button->GetX(); + int oldY = button->GetY(); + button->SetXY(oldX + x, oldY + y); + button->Update(); + button->SetXY(oldX, oldY); + + if(button->Triggered()) { + _triggeredButton = index; + } + + index++; + } +} + +void Menu::Render(void) { + for(std::list::iterator i = _buttons.begin(); i != _buttons.end(); ++i) { + Button* button = (*i); + + int oldX = button->GetX(); + int oldY = button->GetY(); + button->SetXY(oldX + x, oldY + y); + button->Render(); + button->SetXY(oldX, oldY); + } +} diff --git a/src/UI/Menu.h b/src/UI/Menu.h new file mode 100644 index 0000000..c403847 --- /dev/null +++ b/src/UI/Menu.h @@ -0,0 +1,37 @@ +#pragma once + +#include + +class Button; + +class Menu { +public: + enum { + ALIGN_HORIZONTALLY, + ALIGN_VERTICALLY + }; + + Menu(void); + ~Menu(void); + + void AddButton(Button* button); + void AlignButtons(int how); + + void Update(void); + void Render(void); + + int GetTriggeredButton() const { return _triggeredButton; } + + int GetX(void) const { return x; } + int GetY(void) const { return y; } + void SetX(int x) { this->x = x; } + void SetY(int y) { this->y = y; } + void SetXY(int x, int y) { SetX(x); SetY(y); } + +private: + std::list _buttons; + int _triggeredButton; + + int x; + int y; +}; \ No newline at end of file