From: Daniel Karbach Date: Sun, 11 Nov 2012 15:36:25 +0000 (+0100) Subject: Merge branch 'master' into menus X-Git-Url: http://git.localhorst.tv/?a=commitdiff_plain;h=f552d26f537af9fa48255bd71cdc1a0a1b860bac;hp=9d645a0059d185291f63c1375bd4e5ae844acde6;p=l2e.git Merge branch 'master' into menus I'm not putting up with changing build settings on every checkout Conflicts: Debug/makefile Debug/sources.mk Debug/src/graphics/subdir.mk Release/makefile Release/sources.mk Release/src/graphics/subdir.mk --- diff --git a/Debug/src/menu/subdir.mk b/Debug/src/menu/subdir.mk new file mode 100644 index 0000000..49f3428 --- /dev/null +++ b/Debug/src/menu/subdir.mk @@ -0,0 +1,42 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +CPP_SRCS += \ +../src/menu/ChangeHero.cpp \ +../src/menu/HeroStatus.cpp \ +../src/menu/InventoryMenu.cpp \ +../src/menu/PartyMenu.cpp \ +../src/menu/Resources.cpp \ +../src/menu/SelectHero.cpp \ +../src/menu/StatusMenu.cpp + +OBJS += \ +./src/menu/ChangeHero.o \ +./src/menu/HeroStatus.o \ +./src/menu/InventoryMenu.o \ +./src/menu/PartyMenu.o \ +./src/menu/Resources.o \ +./src/menu/SelectHero.o \ +./src/menu/StatusMenu.o + +CPP_DEPS += \ +./src/menu/ChangeHero.d \ +./src/menu/HeroStatus.d \ +./src/menu/InventoryMenu.d \ +./src/menu/PartyMenu.d \ +./src/menu/Resources.d \ +./src/menu/SelectHero.d \ +./src/menu/StatusMenu.d + + +# Each subdirectory must supply rules for building sources it contributes +src/menu/%.o: ../src/menu/%.cpp + @echo 'Building file: $<' + @echo 'Invoking: GCC C++ Compiler' + g++ -I/usr/include/SDL -O0 -g3 -Wall -Werror -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/Release/src/menu/subdir.mk b/Release/src/menu/subdir.mk new file mode 100644 index 0000000..bfcd29c --- /dev/null +++ b/Release/src/menu/subdir.mk @@ -0,0 +1,42 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +CPP_SRCS += \ +../src/menu/ChangeHero.cpp \ +../src/menu/HeroStatus.cpp \ +../src/menu/InventoryMenu.cpp \ +../src/menu/PartyMenu.cpp \ +../src/menu/Resources.cpp \ +../src/menu/SelectHero.cpp \ +../src/menu/StatusMenu.cpp + +OBJS += \ +./src/menu/ChangeHero.o \ +./src/menu/HeroStatus.o \ +./src/menu/InventoryMenu.o \ +./src/menu/PartyMenu.o \ +./src/menu/Resources.o \ +./src/menu/SelectHero.o \ +./src/menu/StatusMenu.o + +CPP_DEPS += \ +./src/menu/ChangeHero.d \ +./src/menu/HeroStatus.d \ +./src/menu/InventoryMenu.d \ +./src/menu/PartyMenu.d \ +./src/menu/Resources.d \ +./src/menu/SelectHero.d \ +./src/menu/StatusMenu.d + + +# Each subdirectory must supply rules for building sources it contributes +src/menu/%.o: ../src/menu/%.cpp + @echo 'Building file: $<' + @echo 'Invoking: GCC C++ Compiler' + g++ -DNDEBUG -I/usr/include/SDL -O3 -Wall -Werror -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/src/common/GameConfig.cpp b/src/common/GameConfig.cpp index b35e991..6673a32 100644 --- a/src/common/GameConfig.cpp +++ b/src/common/GameConfig.cpp @@ -12,7 +12,8 @@ namespace common { GameConfig::GameConfig() : state(0) , battleResources(0) -, heroesLayout(0) { +, heroesLayout(0) +, menuResources(0) { } diff --git a/src/common/GameConfig.h b/src/common/GameConfig.h index 16b0142..c13b4ab 100644 --- a/src/common/GameConfig.h +++ b/src/common/GameConfig.h @@ -10,6 +10,7 @@ #include "fwd.h" #include "../battle/fwd.h" +#include "../menu/fwd.h" namespace common { @@ -22,6 +23,8 @@ struct GameConfig { battle::Resources *battleResources; battle::PartyLayout *heroesLayout; + menu::Resources *menuResources; + }; } diff --git a/src/common/GameState.cpp b/src/common/GameState.cpp index 7992d43..ee7b1b2 100644 --- a/src/common/GameState.cpp +++ b/src/common/GameState.cpp @@ -10,7 +10,9 @@ namespace common { GameState::GameState() -: money(0) { +: partySize(1) +, money(0) +, time(0) { party[0] = heroes; party[1] = 0; party[2] = 0; diff --git a/src/common/GameState.h b/src/common/GameState.h index fca50c1..078da1a 100644 --- a/src/common/GameState.h +++ b/src/common/GameState.h @@ -21,10 +21,12 @@ struct GameState { Hero heroes[7]; Hero *party[4]; + int partySize; Inventory inventory; Uint32 money; + Uint32 time; }; diff --git a/src/common/Hero.cpp b/src/common/Hero.cpp index 02c4dcc..8222e12 100644 --- a/src/common/Hero.cpp +++ b/src/common/Hero.cpp @@ -32,6 +32,9 @@ Hero::Hero() , ip(0) , level(0) +, experience(0) +, levelLadder(0) +, numLevels(0) , weapon(0) , armor(0) @@ -63,6 +66,16 @@ void Hero::SubtractHealth(int amount) { } +int Hero::NextLevel() const { + int levelOffset(Level() - 1); + if (levelOffset < numLevels) { + return levelLadder[levelOffset] - Experience(); + } else { + return 0; + } +} + + void Hero::CreateTypeDescription() { Hero h; @@ -81,6 +94,7 @@ void Hero::CreateTypeDescription() { td.AddField("stats", FieldDescription(((char *)&h.stats) - ((char *)&h), Stats::TYPE_ID)); td.AddField("level", FieldDescription(((char *)&h.level) - ((char *)&h), Interpreter::NUMBER_ID)); + td.AddField("ladder", FieldDescription(((char *)&h.levelLadder) - ((char *)&h), Interpreter::NUMBER_ID).SetReferenced().SetAggregate()); td.AddField("battleSprite", FieldDescription(((char *)&h.battleSprite) - ((char *)&h), Sprite::TYPE_ID).SetReferenced().SetDescription("the sprite used for battle scenes")); td.AddField("attackAnimation", FieldDescription(((char *)&h.attackAnimation) - ((char *)&h), Animation::TYPE_ID).SetReferenced().SetDescription("the animation played for physical attacks")); diff --git a/src/common/Hero.h b/src/common/Hero.h index ca4651c..77269c6 100644 --- a/src/common/Hero.h +++ b/src/common/Hero.h @@ -47,6 +47,8 @@ public: const Stats &GetStats() const { return stats; } Uint8 Level() const { return level; } + int Experience() const { return experience; } + int NextLevel() const; Item *Weapon() { return weapon; } Item *Armor() { return armor; } @@ -72,6 +74,7 @@ public: const std::vector &Spells() const { return spells; } graphics::Sprite *BattleSprite() { return battleSprite; } + const graphics::Sprite *BattleSprite() const { return battleSprite; } graphics::Animation *MeleeAnimation() { return meleeAnimation; } graphics::Animation *AttackAnimation() { return attackAnimation; } graphics::Animation *SpellAnimation() { return spellAnimation; } @@ -103,6 +106,10 @@ private: Stats stats; int level; + int experience; + + int *levelLadder; + int numLevels; Item *weapon; Item *armor; diff --git a/src/graphics/Font.cpp b/src/graphics/Font.cpp index be96a2c..59059e0 100644 --- a/src/graphics/Font.cpp +++ b/src/graphics/Font.cpp @@ -39,6 +39,18 @@ void Font::DrawString(const char *s, SDL_Surface *dest, const Vector &posit } } +void Font::DrawStringRight(const char *s, SDL_Surface *dest, const Vector &positionIn, int maxChars) const { + if (!sprite) return; + + int length(0); + while (length < maxChars && s[length] != '\0') { + ++length; + } + Vector position(positionIn.X() - length * CharWidth(), positionIn.Y()); + + DrawString(s, dest, position, length); +} + void Font::DrawDigit(int digit, SDL_Surface *dest, const Vector &position) const { if (!sprite) return; @@ -76,6 +88,14 @@ void Font::DrawNumber(int numberIn, SDL_Surface *dest, const Vector &positi } } +void Font::DrawNumberRight(int number, SDL_Surface *dest, const Vector &positionIn, int digits) const { + if (!sprite) return; + + Vector position(positionIn.X() - digits * CharWidth(), positionIn.Y()); + + DrawNumber(number, dest, position, digits); +} + void Font::CreateTypeDescription() { Font f; diff --git a/src/graphics/Font.h b/src/graphics/Font.h index 07cd35f..b981946 100644 --- a/src/graphics/Font.h +++ b/src/graphics/Font.h @@ -31,8 +31,10 @@ public: int CharHeight() const { return sprite->Height(); } void DrawChar(char c, SDL_Surface *dest, const geometry::Vector &position) const; void DrawString(const char *s, SDL_Surface *dest, const geometry::Vector &position, int maxChars = 0) const; + void DrawStringRight(const char *s, SDL_Surface *dest, const geometry::Vector &position, int maxChars = 0) const; void DrawDigit(int d, SDL_Surface *dest, const geometry::Vector &position) const; void DrawNumber(int n, SDL_Surface *dest, const geometry::Vector &position, int digits = 0) const; + void DrawNumberRight(int n, SDL_Surface *dest, const geometry::Vector &position, int digits = 0) const; public: void SetSprite(const Sprite *s) { sprite = s; } diff --git a/src/graphics/Frame.cpp b/src/graphics/Frame.cpp index 46fa1b5..86b9cd2 100644 --- a/src/graphics/Frame.cpp +++ b/src/graphics/Frame.cpp @@ -7,6 +7,7 @@ #include "Frame.h" +#include "Texture.h" #include "../loader/Interpreter.h" #include "../loader/TypeDescription.h" @@ -40,55 +41,26 @@ void Frame::Draw(SDL_Surface *dest, const Vector &position, int width, int SDL_BlitSurface(surface, &srcRect, dest, &destRect); // top border - srcRect.x += BorderWidth(); - srcRect.w = RepeatWidth(); - destRect.x += BorderWidth(); - int fullRepeatWidth(width - (2 * BorderWidth())); - int repeatCursor(0); - while (repeatCursor < fullRepeatWidth) { - SDL_BlitSurface(surface, &srcRect, dest, &destRect); - destRect.x += RepeatWidth(); - repeatCursor += RepeatWidth(); - } + Texture(surface, Vector(RepeatWidth(), BorderHeight()), Vector(offset.X() + BorderWidth(), offset.Y())) + .Render(dest, Vector(position.X() + BorderWidth(), position.Y()), Vector(position.X() + width - BorderWidth(), position.Y() + BorderHeight())); // top-right corner - srcRect.x += RepeatWidth(); + srcRect.x = offset.X() + RepeatWidth() + BorderWidth(); srcRect.w = BorderWidth(); + destRect.x = position.X() + width - BorderWidth(); SDL_BlitSurface(surface, &srcRect, dest, &destRect); - // middle - destRect.y += BorderHeight(); - int fullRepeatHeight(height - (2 * BorderHeight())); - int hRepeatCursor(0); - while (hRepeatCursor < fullRepeatHeight) { - - // left border - srcRect.x = offset.X(); - srcRect.y = offset.Y() + BorderHeight(); - srcRect.w = BorderWidth(); - srcRect.h = RepeatHeight(); - destRect.x = position.X(); - SDL_BlitSurface(surface, &srcRect, dest, &destRect); - - // fill - repeatCursor = 0; - srcRect.x += BorderWidth(); - srcRect.w = RepeatWidth(); - destRect.x += BorderWidth(); - while (repeatCursor < fullRepeatWidth) { - SDL_BlitSurface(surface, &srcRect, dest, &destRect); - destRect.x += RepeatWidth(); - repeatCursor += RepeatWidth(); - } - - // right border - srcRect.x += RepeatWidth(); - srcRect.w = BorderWidth(); - SDL_BlitSurface(surface, &srcRect, dest, &destRect); - - destRect.y += RepeatHeight(); - hRepeatCursor += RepeatHeight(); - } + // left border + Texture(surface, Vector(BorderWidth(), RepeatHeight()), Vector(offset.X(), offset.Y() + BorderHeight())) + .Render(dest, Vector(position.X(), position.Y() + BorderHeight()), Vector(position.X() + BorderWidth(), position.Y() + height - BorderHeight())); + + // center fill + Texture(surface, RepeatSize(), Vector(offset.X() + BorderWidth(), offset.Y() + BorderHeight())) + .Render(dest, position + BorderSize(), position + Vector(width, height) - BorderSize()); + + // right border + Texture(surface, Vector(BorderWidth(), RepeatHeight()), Vector(offset.X() + BorderWidth() + RepeatWidth(), offset.Y() + BorderHeight())) + .Render(dest, Vector(position.X() + width - BorderWidth(), position.Y() + BorderHeight()), Vector(position.X() + width, position.Y() + height - BorderHeight())); // bottom-left corner srcRect.x = offset.X(); @@ -96,27 +68,17 @@ void Frame::Draw(SDL_Surface *dest, const Vector &position, int width, int srcRect.w = BorderWidth(); srcRect.h = BorderHeight(); destRect.x = position.X(); + destRect.y = position.Y() + height - BorderHeight(); SDL_BlitSurface(surface, &srcRect, dest, &destRect); // bottom border - srcRect.x += BorderWidth(); - srcRect.w = RepeatWidth(); - destRect.x += BorderWidth(); - repeatCursor = 0; - while (repeatCursor < fullRepeatWidth) { - SDL_BlitSurface(surface, &srcRect, dest, &destRect); - destRect.x += RepeatWidth(); - repeatCursor += RepeatWidth(); - } - if (fullRepeatWidth < fullRepeatWidth) { - srcRect.w = fullRepeatWidth - fullRepeatWidth; - SDL_BlitSurface(surface, &srcRect, dest, &destRect); - destRect.x += fullRepeatWidth - fullRepeatWidth; - } + Texture(surface, Vector(RepeatWidth(), BorderHeight()), Vector(offset.X() + BorderWidth(), offset.Y() + BorderHeight() + RepeatHeight())) + .Render(dest, Vector(position.X() + BorderWidth(), position.Y() + height - BorderHeight()), Vector(position.X() + width - BorderWidth(), position.Y() + height)); // bottom-right corner - srcRect.x += RepeatWidth(); + srcRect.x = offset.X() + BorderWidth() + RepeatWidth(); srcRect.w = BorderWidth(); + destRect.x = position.X() + width - BorderWidth(); SDL_BlitSurface(surface, &srcRect, dest, &destRect); } diff --git a/src/graphics/Menu.h b/src/graphics/Menu.h index 4dc6032..e42f24e 100644 --- a/src/graphics/Menu.h +++ b/src/graphics/Menu.h @@ -34,16 +34,16 @@ struct MenuProperties { int charsPerAdditionalText; int additionalTextGap; char delimiter; + bool wrapX; + bool wrapY; MenuProperties() : font(0), disabledFont(0), cursor(0) - , charsPerEntry(0), rows(0), rowGap(0) - , iconSpace(0), cols(0), colGap(0) + , charsPerEntry(0), rows(1), rowGap(0) + , iconSpace(0), cols(1), colGap(0) , charsPerNumber(0), charsPerAdditionalText(0) - , additionalTextGap(0), delimiter(':') { } - - MenuProperties(const Font *font, const Font *disabledFont, const Sprite *cursor, int charsPerEntry, int rows, int rowGap, int iconSpace, int cols, int colGap, int charsPerNumber, char delimiter, int charsPerAdditionalText, int additionalTextGap) - : font(font), disabledFont(disabledFont), cursor(cursor), charsPerEntry(charsPerEntry), rows(rows), rowGap(rowGap), iconSpace(iconSpace), cols(cols), colGap(colGap), charsPerNumber(charsPerNumber), charsPerAdditionalText(charsPerAdditionalText), additionalTextGap(additionalTextGap), delimiter(delimiter) { } + , additionalTextGap(0), delimiter(':') + , wrapX(false), wrapY(false) { } static void CreateTypeDescription(); static void Construct(void *); @@ -57,7 +57,6 @@ class Menu public: Menu(); Menu(const MenuProperties &); - Menu(const Font *font, const Font *disabledFont, const Sprite *cursor, int charsPerEntry, int rows, int rowGap = 0, int iconSpace = 0, int cols = 1, int colGap = 0, int charsPerNumber = 0, char delimiter = ':', int charsPerAdditionalText = 0, int additionalTextGap = 0); public: int Width() const; @@ -131,21 +130,6 @@ Menu::Menu(const MenuProperties &p) } -template -Menu::Menu(const Font *font, const Font *disabledFont, const Sprite *cursor, int charsPerEntry, int rows, int rowGap, int iconSpace, int cols, int colGap, int charsPerNumber, char delimiter, int charsPerAdditionalText, int additionalTextGap) -: MenuProperties( - font, disabledFont ? disabledFont : font, - cursor, charsPerEntry, - rows, rowGap, iconSpace, - cols, colGap, charsPerNumber, - delimiter, - charsPerAdditionalText, - additionalTextGap) -, selected(0) -, topRow(0) { - -} - template int Menu::ColWidth() const { @@ -173,22 +157,38 @@ int Menu::Height() const { template void Menu::NextItem() { - SelectIndex(selected + 1); + int index(selected + 1); + if (wrapX && index % cols == 0) { + index -= cols; + } + SelectIndex(index); } template void Menu::PreviousItem() { - SelectIndex(selected - 1); + int index(selected - 1); + if (wrapX && selected % cols == 0) { + index += cols; + } + SelectIndex(index); } template void Menu::NextRow() { - SelectIndex(selected + cols); + int index(selected + cols); + if (wrapY && index >= int(entries.size())) { + index -= entries.size(); + } + SelectIndex(index); } template void Menu::PreviousRow() { - SelectIndex(selected - cols); + int index(selected - cols); + if (wrapY && index < 0) { + index += entries.size(); + } + SelectIndex(index); } template @@ -214,6 +214,13 @@ void Menu::Draw(SDL_Surface *dest, const geometry::Vector &position) con geometry::Vector iconOffset( (i % cols) * (ColWidth() + colGap), (i / cols) * RowHeight()); + + // Third column hack! + // This fixes the position of the "DROP" item in the inventory menu. + if (i % cols == 2) { + iconOffset += geometry::Vector(font->CharWidth(), 0); + } + if (entries[start + i].icon) { entries[start + i].icon->Draw(dest, position + iconOffset); } @@ -234,7 +241,7 @@ void Menu::Draw(SDL_Surface *dest, const geometry::Vector &position) con if (charsPerNumber) { usedFont->DrawChar(delimiter, dest, position + textOffset); textOffset += geometry::Vector(usedFont->CharWidth(), 0); - usedFont->DrawNumber(entries[start + i].number, dest, position + textOffset); + usedFont->DrawNumber(entries[start + i].number, dest, position + textOffset, charsPerNumber); } } geometry::Vector cursorOffset( diff --git a/src/graphics/Texture.cpp b/src/graphics/Texture.cpp new file mode 100644 index 0000000..2bb0e97 --- /dev/null +++ b/src/graphics/Texture.cpp @@ -0,0 +1,65 @@ +/* + * Texture.cpp + * + * Created on: Oct 21, 2012 + * Author: holy + */ + +#include "Texture.h" + +#include "../sdl/utility.h" + +using geometry::Vector; + +namespace graphics { + +Texture::Texture( + SDL_Surface *surface, + const Vector &size, + const Vector &offset) +: surface(surface) +, size(size) +, offset(offset) { + +} + +Texture::~Texture() { + +} + + +void Texture::Render(SDL_Surface *dest, const Vector &from, const Vector &to) const { + SDL_Rect destRect; + destRect.x = from.X(); + destRect.y = from.Y(); + if (!surface || size == Vector()) { + destRect.w = to.X() - from.X(); + destRect.h = to.Y() - from.Y(); + SDL_FillRect(dest, &destRect, SDL_MapRGB(dest->format, 0xFF, 0x00, 0x00)); + return; + } + + SDL_Rect srcRect; + srcRect.x = offset.X(); + srcRect.y = offset.Y(); + + for (destRect.y = from.Y(); destRect.y < to.Y(); destRect.y += size.Y()) { + srcRect.h = size.Y(); + destRect.h = size.Y(); + if (destRect.y + destRect.h > to.Y()) { + srcRect.h = to.Y() - destRect.y; + destRect.h = to.Y() - destRect.y; + } + for (destRect.x = from.X(); destRect.x < to.X(); destRect.x += size.X()) { + srcRect.w = size.X(); + destRect.w = size.X(); + if (destRect.x + destRect.w > to.X()) { + srcRect.w = to.X() - destRect.x; + destRect.w = to.X() - destRect.x; + } + SDL_BlitSurface(surface, &srcRect, dest, &destRect); + } + } +} + +} diff --git a/src/graphics/Texture.h b/src/graphics/Texture.h new file mode 100644 index 0000000..ecb516a --- /dev/null +++ b/src/graphics/Texture.h @@ -0,0 +1,43 @@ +/* + * Texture.h + * + * Created on: Oct 21, 2012 + * Author: holy + */ + +#ifndef GRAPHICS_TEXTURE_H_ +#define GRAPHICS_TEXTURE_H_ + +#include "../geometry/Vector.h" + +#include + +namespace graphics { + +class Texture { + +public: + explicit Texture( + SDL_Surface *surface = 0, + const geometry::Vector &size = geometry::Vector(), + const geometry::Vector &offset = geometry::Vector()); + ~Texture(); + +public: + void Render(SDL_Surface *dest, const geometry::Vector &from, const geometry::Vector &to) const; + +public: + void SetSurface(SDL_Surface *s) { surface = s; } + void SetSize(const geometry::Vector &s) { size = s; } + void SetOffset(const geometry::Vector &o) { offset = o; } + +private: + SDL_Surface *surface; + geometry::Vector size; + geometry::Vector offset; + +}; + +} + +#endif /* GRAPHICS_TEXTURE_H_ */ diff --git a/src/graphics/fwd.h b/src/graphics/fwd.h index 31dbf27..961890b 100644 --- a/src/graphics/fwd.h +++ b/src/graphics/fwd.h @@ -24,6 +24,7 @@ class Menu; struct MenuProperties; class SimpleAnimation; class Sprite; +class Texture; } diff --git a/src/main.cpp b/src/main.cpp index f70103a..d76eca5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,6 +30,7 @@ #include "graphics/Menu.h" #include "graphics/SimpleAnimation.h" #include "graphics/Sprite.h" +#include "graphics/Texture.h" #include "loader/Caster.h" #include "loader/Interpreter.h" #include "loader/ParsedSource.h" @@ -41,6 +42,7 @@ #include "map/MapState.h" #include "map/Tile.h" #include "map/Trigger.h" +#include "menu/Resources.h" #include "sdl/InitImage.h" #include "sdl/InitScreen.h" #include "sdl/InitSDL.h" @@ -64,6 +66,7 @@ using common::GameConfig; using common::GameState; using common::Spell; using geometry::Vector; +using graphics::Texture; using loader::Caster; using loader::Interpreter; using loader::ParsedSource; @@ -83,8 +86,8 @@ using std::string; using std::vector; int main(int argc, char **argv) { - const int width = 800; - const int height = 480; + const int width = 512; + const int height = 448; const float walkSpeed = 128.0f; @@ -188,6 +191,7 @@ int main(int argc, char **argv) { gameState.party[1] = &gameState.heroes[1]; gameState.party[2] = &gameState.heroes[2]; gameState.party[3] = &gameState.heroes[3]; + gameState.partySize = 4; GameConfig gameConfig; gameConfig.state = &gameState; @@ -268,6 +272,120 @@ int main(int argc, char **argv) { gameState.heroes[3].MapEntity().SetFlags(Entity::FLAG_NONBLOCKING); gameState.heroes[2].MapEntity().AddFollower(&gameState.heroes[3].MapEntity()); + menu::Resources menuResources; + gameConfig.menuResources = &menuResources; + + Texture menubg; + menubg.SetSurface(IMG_Load("test-data/menubg.png")); + menubg.SetSize(Vector(64, 64)); + menuResources.menubg = &menubg; + + menuResources.statusFont = gameConfig.battleResources->normalFont; + + graphics::Sprite statusLabels(IMG_Load("test-data/status-labels.png"), 32, 16); + menuResources.statusLabels = &statusLabels; + + graphics::Frame statusFrame(IMG_Load("test-data/status-frame.png"), 32, 32, 32, 32); + menuResources.statusFrame = &statusFrame; + + graphics::Sprite menuFontSprite(IMG_Load("test-data/menu-font.png"), 16, 16); + graphics::Font menuFont(&menuFontSprite, 0, -2); + + menuResources.normalFont = &menuFont; + + graphics::Sprite menuCursor(IMG_Load("test-data/menu-cursor.png"), 32, 16); + menuResources.menuCursor = &menuCursor; + graphics::Sprite menuActiveCursor(IMG_Load("test-data/menu-cursor-active.png"), 32, 18); + menuResources.menuActiveCursor = &menuActiveCursor; + + graphics::MenuProperties mainMenuProperties; + mainMenuProperties.cols = 2; + mainMenuProperties.rows = 4; + mainMenuProperties.charsPerEntry = 8; + mainMenuProperties.rowGap = 8; + mainMenuProperties.colGap = 32; + mainMenuProperties.cursor = &menuCursor; + mainMenuProperties.font = &menuFont; + mainMenuProperties.wrapX = true; + mainMenuProperties.wrapY = true; + menuResources.mainMenuProperties = &mainMenuProperties; + + menuResources.mainMenuItemText = "ITEM"; + menuResources.mainMenuSpellText = "SPELL"; + menuResources.mainMenuCapsuleText = "CAPSULE"; + menuResources.mainMenuEquipmentText = "EQUIP"; + menuResources.mainMenuStatusText = "STATUS"; + menuResources.mainMenuChangeText = "CHANGE"; + menuResources.mainMenuConfigText = "CONFIG"; + menuResources.mainMenuScenarioText = "SCENARIO"; + + menuResources.mainMenuTimeText = "TIME"; + menuResources.mainMenuGoldText = "GOLD"; + + graphics::Sprite heroCursor(IMG_Load("test-data/hero-cursor.png"), 64, 16); + menuResources.heroCursor = &heroCursor; + menuResources.heroCursorBlinkTime = 532; + + menuResources.noEquipmentText = "No equip"; + + graphics::Sprite shoulderNav(IMG_Load("test-data/shoulder-nav.png"), 160, 16); + menuResources.shoulderNav = &shoulderNav; + + menuResources.atpLabel = "ATP"; + menuResources.dfpLabel = "DFP"; + menuResources.strLabel = "STR"; + menuResources.aglLabel = "AGL"; + menuResources.intLabel = "INT"; + menuResources.gutLabel = "GUT"; + menuResources.mgrLabel = "MGR"; + + menuResources.ipLabel = "IP"; + menuResources.experienceLabel = "NOW EXP"; + menuResources.nextLevelLabel = "NEXT LEVEL"; + + graphics::MenuProperties statusMenuProperties; + statusMenuProperties.cols = 2; + statusMenuProperties.rows = 1; + statusMenuProperties.charsPerEntry = 6; + statusMenuProperties.rowGap = 0; + statusMenuProperties.colGap = 16; + statusMenuProperties.cursor = &menuCursor; + statusMenuProperties.font = &menuFont; + statusMenuProperties.wrapX = true; + menuResources.statusMenuProperties = &statusMenuProperties; + + menuResources.nextLabel = "NEXT"; + menuResources.returnLabel = "RETURN"; + + graphics::MenuProperties itemMenuProperties; + itemMenuProperties.cols = 3; + itemMenuProperties.rows = 1; + itemMenuProperties.charsPerEntry = 5; + itemMenuProperties.rowGap = 8; + itemMenuProperties.colGap = 16; + itemMenuProperties.cursor = &menuCursor; + itemMenuProperties.font = &menuFont; + itemMenuProperties.wrapX = true; + itemMenuProperties.wrapY = true; + menuResources.itemMenuProperties = &itemMenuProperties; + menuResources.itemMenuUseText = "USE"; + menuResources.itemMenuSortText = "SORT"; + menuResources.itemMenuDropText = "DROP"; + + graphics::MenuProperties inventoryMenuProperties; + inventoryMenuProperties.cols = 1; + inventoryMenuProperties.rows = 6; + inventoryMenuProperties.charsPerEntry = 13; + inventoryMenuProperties.rowGap = 8; + inventoryMenuProperties.cursor = &menuCursor; + inventoryMenuProperties.font = &menuFont; + // TODO: disabled font + inventoryMenuProperties.disabledFont = &menuFont; + inventoryMenuProperties.iconSpace = 16; + inventoryMenuProperties.charsPerNumber = 2; + inventoryMenuProperties.delimiter = ':'; + menuResources.inventoryMenuProperties = &inventoryMenuProperties; + InitScreen screen(width, height); app::State *state(0); diff --git a/src/map/MapState.cpp b/src/map/MapState.cpp index 5ec9507..af15630 100644 --- a/src/map/MapState.cpp +++ b/src/map/MapState.cpp @@ -17,6 +17,7 @@ #include "../common/GameConfig.h" #include "../common/GameState.h" #include "../graphics/ColorFade.h" +#include "../menu/PartyMenu.h" #include @@ -26,6 +27,7 @@ using battle::BattleState; using common::GameConfig; using geometry::Vector; using graphics::ColorFade; +using menu::PartyMenu; namespace map { @@ -69,6 +71,11 @@ void MapState::OnResize(int width, int height) { void MapState::HandleEvents(const Input &input) { + if (input.JustPressed(Input::ACTION_X)) { + Ctrl().PushState(new PartyMenu(game)); + return; + } + if (!controlled) return; if (input.IsDown(Input::PAD_UP)) { diff --git a/src/menu/ChangeHero.cpp b/src/menu/ChangeHero.cpp new file mode 100644 index 0000000..f1d871d --- /dev/null +++ b/src/menu/ChangeHero.cpp @@ -0,0 +1,120 @@ +/* + * ChangeHero.cpp + * + * Created on: Nov 4, 2012 + * Author: holy + */ + +#include "ChangeHero.h" + +#include "HeroStatus.h" +#include "PartyMenu.h" +#include "Resources.h" +#include "SelectHero.h" +#include "../app/Application.h" +#include "../app/Input.h" +#include "../common/GameConfig.h" +#include "../common/GameState.h" + +#include + +using app::Input; +using geometry::Vector; +using std::swap; + +namespace menu { + +ChangeHero::ChangeHero(PartyMenu *parent) +: parent(parent) +, highlight(0) +, selection(0) { + +} + + +void ChangeHero::OnEnterState(SDL_Surface *) { + const HeroStatus &status(parent->GetHeroStatus(0)); + highlight = SDL_CreateRGBSurface(0, status.Width(), status.Height(), 32, 0xFF000000, 0xFF0000, 0xFF00, 0); + SDL_FillRect(highlight, 0, SDL_MapRGB(highlight->format, 0xFF, 0xFF, 0xFF)); + SDL_SetAlpha(highlight, SDL_SRCALPHA|SDL_RLEACCEL, 0x20); +} + +void ChangeHero::OnExitState(SDL_Surface *) { + SDL_FreeSurface(highlight); +} + +void ChangeHero::OnResumeState(SDL_Surface *) { + if (selection < 0) { + Ctrl().PopState(); + } else { + selection = -1; + Ctrl().PushState(new SelectHero(this, parent, this, OnHeroSelected)); + } +} + +void ChangeHero::OnPauseState(SDL_Surface *) { + +} + + +void ChangeHero::OnResize(int width, int height) { + +} + + +int ChangeHero::Width() const { + return parent->Width(); +} + +int ChangeHero::Height() const { + return parent->Height(); +} + + +void ChangeHero::HandleEvents(const Input &input) { + +} + +void ChangeHero::UpdateWorld(float deltaT) { + +} + +void ChangeHero::Render(SDL_Surface *screen) { + Vector offset((screen->w - Width()) / 2, (screen->h - Height()) / 2); + + parent->RenderBackground(screen); + RenderHighlight(screen, offset); + parent->RenderHeros(screen, offset); + parent->RenderMenu(screen, offset + Vector(8 * parent->Res().normalFont->CharWidth(), 13 * parent->Res().normalFont->CharHeight() + parent->Res().normalFont->CharHeight() / 8)); + parent->RenderInfo(screen, offset + Vector(14 * parent->Res().normalFont->CharWidth(), 21 * parent->Res().normalFont->CharHeight() + parent->Res().normalFont->CharHeight() / 8)); +} + +void ChangeHero::RenderHighlight(SDL_Surface *screen, const Vector &offset) const { + if (selection < 0) return; + Vector statusOffset(parent->StatusOffset(selection)); + statusOffset -= Vector(0, parent->Res().normalFont->CharHeight() / 8); + SDL_Rect rect; + rect.x = statusOffset.X(); + rect.y = statusOffset.Y(); + SDL_BlitSurface(highlight, 0, screen, &rect); +} + + +void ChangeHero::OnHeroSelected(void *ref, int index) { + ChangeHero *self(reinterpret_cast(ref)); + self->SelectedHero(index); +} + +void ChangeHero::SelectedHero(int index) { + if (selection < 0) { + selection = index; + } else { + if (index != selection) { + swap(parent->Game().state->party[selection], + parent->Game().state->party[index]); + } + selection = -1; + } +} + +} diff --git a/src/menu/ChangeHero.h b/src/menu/ChangeHero.h new file mode 100644 index 0000000..6bb5f31 --- /dev/null +++ b/src/menu/ChangeHero.h @@ -0,0 +1,57 @@ +/* + * ChangeHero.h + * + * Created on: Nov 4, 2012 + * Author: holy + */ + +#ifndef MENU_CHANGEHERO_H_ +#define MENU_CHANGEHERO_H_ + +#include "fwd.h" +#include "../app/State.h" +#include "../geometry/Vector.h" + +#include + +namespace menu { + +class ChangeHero +: public app::State { + +public: + explicit ChangeHero(PartyMenu *parent); + +public: + virtual void HandleEvents(const app::Input &); + virtual void UpdateWorld(float deltaT); + virtual void Render(SDL_Surface *); + +public: + int Width() const; + int Height() const; + +private: + virtual void OnEnterState(SDL_Surface *screen); + virtual void OnExitState(SDL_Surface *screen); + virtual void OnResumeState(SDL_Surface *screen); + virtual void OnPauseState(SDL_Surface *screen); + + virtual void OnResize(int width, int height); + + void SelectedHero(int index); + + void RenderHighlight(SDL_Surface *screen, const geometry::Vector &offset) const; + + static void OnHeroSelected(void *, int); + +private: + PartyMenu *parent; + SDL_Surface *highlight; + int selection; + +}; + +} + +#endif /* MENU_CHANGEHERO_H_ */ diff --git a/src/menu/HeroStatus.cpp b/src/menu/HeroStatus.cpp new file mode 100644 index 0000000..5bc0c3b --- /dev/null +++ b/src/menu/HeroStatus.cpp @@ -0,0 +1,83 @@ +/* + * HeroStatus.cpp + * + * Created on: Oct 21, 2012 + * Author: holy + */ + +#include "HeroStatus.h" + +#include "Resources.h" +#include "../common/Hero.h" +#include "../graphics/Font.h" +#include "../graphics/Sprite.h" + +using geometry::Vector; + +namespace menu { + +HeroStatus::HeroStatus() +: res(0) +, party(0) +, hero(0) { + +} + +HeroStatus::~HeroStatus() { + +} + + +int HeroStatus::Width() const { + return party[hero]->BattleSprite()->Width() + res->statusFont->CharWidth() * 11; +} + +int HeroStatus::Height() const { + return party[hero]->BattleSprite()->Height() + res->statusFont->CharWidth(); +} + + +void HeroStatus::Render(SDL_Surface *screen, const Vector &offset) const { + if (!party) return; + + party[hero]->BattleSprite()->Draw(screen, offset, 0, 0); + + // for some reason, fonts are shifted by one pixel in the original + Vector nameOffset( + party[hero]->BattleSprite()->Width(), + res->statusFont->CharHeight() * 7 / 8); + nameOffset += offset; + res->statusFont->DrawString(party[hero]->Name(), screen, nameOffset, 5); + + Vector levelLabelOffset(nameOffset.X() + 6 * res->statusFont->CharWidth(), nameOffset.Y()); + res->statusLabels->Draw(screen, levelLabelOffset, 0, 0); + + Vector levelOffset(levelLabelOffset.X() + 2 * res->statusFont->CharWidth(), levelLabelOffset.Y()); + res->statusFont->DrawNumber(party[hero]->Level(), screen, levelOffset, 2); + + Vector healthLabelOffset(nameOffset.X(), nameOffset.Y() + res->statusFont->CharHeight()); + res->statusLabels->Draw(screen, healthLabelOffset, 0, 1); + + Vector healthOffset(nameOffset.X() + 3 * res->statusFont->CharWidth(), nameOffset.Y() + res->statusFont->CharHeight()); + res->statusFont->DrawNumber(party[hero]->Health(), screen, healthOffset, 3); + + Vector healthSeparatorOffset(healthOffset.X() + 3 * res->statusFont->CharWidth(), healthOffset.Y()); + res->statusFont->DrawChar('/', screen, healthSeparatorOffset); + + Vector maxHealthOffset(healthSeparatorOffset.X() + res->statusFont->CharWidth(), healthOffset.Y()); + res->statusFont->DrawNumber(party[hero]->MaxHealth(), screen, maxHealthOffset, 3); + + Vector manaLabelOffset(healthLabelOffset.X(), healthLabelOffset.Y() + res->statusFont->CharHeight()); + res->statusLabels->Draw(screen, manaLabelOffset, 0, 2); + + Vector manaOffset(healthOffset.X(), healthOffset.Y() + res->statusFont->CharHeight()); + res->statusFont->DrawNumber(party[hero]->Mana(), screen, manaOffset, 3); + + Vector manaSeparatorOffset(healthSeparatorOffset.X(), manaOffset.Y()); + res->statusFont->DrawChar('/', screen, manaSeparatorOffset); + + Vector maxManaOffset(maxHealthOffset.X(), manaOffset.Y()); + res->statusFont->DrawNumber(party[hero]->MaxMana(), screen, maxManaOffset, 3); +} + +} diff --git a/src/menu/HeroStatus.h b/src/menu/HeroStatus.h new file mode 100644 index 0000000..27c048e --- /dev/null +++ b/src/menu/HeroStatus.h @@ -0,0 +1,44 @@ +/* + * HeroStatus.h + * + * Created on: Oct 21, 2012 + * Author: holy + */ + +#ifndef MENU_HEROSTATUS_H_ +#define MENU_HEROSTATUS_H_ + +#include "fwd.h" +#include "../common/fwd.h" +#include "../geometry/Vector.h" + +#include + +namespace menu { + +class HeroStatus { + +public: + HeroStatus(); + ~HeroStatus(); + +public: + void SetResources(const Resources *r) { res = r; } + void SetHero(common::Hero **p, int h) { party = p; hero = h; } + + int Width() const; + int Height() const; + geometry::Vector Size() const { return geometry::Vector(Width(), Height()); } + + void Render(SDL_Surface *screen, const geometry::Vector &offset) const; + +private: + const Resources *res; + common::Hero **party; + int hero; + +}; + +} + +#endif /* MENU_HEROSTATUS_H_ */ diff --git a/src/menu/InventoryMenu.cpp b/src/menu/InventoryMenu.cpp new file mode 100644 index 0000000..2ea7fb3 --- /dev/null +++ b/src/menu/InventoryMenu.cpp @@ -0,0 +1,135 @@ +/* + * InventoryMenu.cpp + * + * Created on: Nov 4, 2012 + * Author: holy + */ + +#include "InventoryMenu.h" + +#include "PartyMenu.h" +#include "Resources.h" +#include "../app/Input.h" +#include "../common/GameConfig.h" +#include "../common/GameState.h" +#include "../common/Inventory.h" +#include "../common/Item.h" +#include "../graphics/Font.h" +#include "../graphics/Frame.h" + +using app::Input; +using common::Inventory; +using common::Item; +using geometry::Vector; +using graphics::Font; +using graphics::Frame; + +namespace menu { + +InventoryMenu::InventoryMenu(PartyMenu *parent) +: parent(parent) +, menu(*parent->Res().itemMenuProperties) +, itemMenu(*parent->Res().inventoryMenuProperties) { + menu.Add(parent->Res().itemMenuUseText, 0); + menu.Add(parent->Res().itemMenuSortText, 1); + menu.Add(parent->Res().itemMenuDropText, 2); +} + + +void InventoryMenu::OnEnterState(SDL_Surface *) { + const Inventory &inv(parent->Game().state->inventory); + itemMenu.Clear(); + itemMenu.Reserve(inv.MaxItems()); + for (int i(0); i < inv.MaxItems(); ++i) { + const Item *item(inv.ItemAt(i)); + if (item) { + itemMenu.Add(item->Name(), item, item->CanUseOnStatusScreen(), item->MenuIcon(), inv.ItemCountAt(i)); + } else { + itemMenu.AddEmptyEntry(); + } + } +} + +void InventoryMenu::OnExitState(SDL_Surface *) { + +} + +void InventoryMenu::OnResumeState(SDL_Surface *) { + +} + +void InventoryMenu::OnPauseState(SDL_Surface *) { + +} + + +void InventoryMenu::OnResize(int width, int height) { + +} + + +void InventoryMenu::HandleEvents(const Input &input) { + if (input.JustPressed(Input::PAD_LEFT)) { + menu.PreviousItem(); + } + if (input.JustPressed(Input::PAD_RIGHT)) { + menu.NextItem(); + } + + if (input.JustPressed(Input::PAD_UP)) { + itemMenu.PreviousItem(); + } + if (input.JustPressed(Input::PAD_DOWN)) { + itemMenu.NextItem(); + } +} + +void InventoryMenu::UpdateWorld(float deltaT) { + +} + + +void InventoryMenu::Render(SDL_Surface *screen) { + const Font &font(*parent->Res().normalFont); + Vector offset((screen->w - Width()) / 2, (screen->h - Height()) / 2); + Vector menuOffset(font.CharWidth(), 13 * font.CharHeight() + font.CharHeight() / 8); + Vector inventoryOffset(font.CharWidth(), 16 * font.CharHeight() + font.CharHeight() / 8); + + parent->RenderBackground(screen); + parent->RenderHeros(screen, offset); + RenderMenu(screen, menuOffset + offset); + RenderInventory(screen, inventoryOffset + offset); +} + +int InventoryMenu::Width() const { + return parent->Width(); +} + +int InventoryMenu::Height() const { + return parent->Height(); +} + +void InventoryMenu::RenderMenu(SDL_Surface *screen, const Vector &offset) const { + const Font &font(*parent->Res().normalFont); + const Frame &frame(*parent->Res().statusFrame); + + const Vector labelOffset(2 * font.CharWidth(), font.CharHeight()); + const Vector menuFrameOffset(offset.X() + 8 * font.CharWidth(), offset.Y()); + const Vector menuOffset(menuFrameOffset.X() + 3 * font.CharWidth(), menuFrameOffset.Y() + font.CharHeight()); + + frame.Draw(screen, offset, 8 * font.CharWidth(), 3 * font.CharHeight()); + font.DrawString(parent->Res().mainMenuItemText, screen, labelOffset + offset); + frame.Draw(screen, menuFrameOffset, 22 * font.CharWidth(), 3 * font.CharHeight()); + menu.Draw(screen, menuOffset); +} + +void InventoryMenu::RenderInventory(SDL_Surface *screen, const Vector &offset) const { + const Font &font(*parent->Res().normalFont); + const Frame &frame(*parent->Res().statusFrame); + const Vector menuOffset(3 * font.CharWidth(), font.CharHeight() + font.CharHeight() / 4); + + frame.Draw(screen, offset, 30 * font.CharWidth(), 11 * font.CharHeight()); + itemMenu.Draw(screen, offset + menuOffset); +} + +} diff --git a/src/menu/InventoryMenu.h b/src/menu/InventoryMenu.h new file mode 100644 index 0000000..20cbe17 --- /dev/null +++ b/src/menu/InventoryMenu.h @@ -0,0 +1,53 @@ +/* + * InventoryMenu.h + * + * Created on: Nov 4, 2012 + * Author: holy + */ + +#ifndef MENU_INVENTORYMENU_H_ +#define MENU_INVENTORYMENU_H_ + +#include "fwd.h" +#include "../app/State.h" +#include "../common/fwd.h" +#include "../geometry/Vector.h" +#include "../graphics/Menu.h" + +namespace menu { + +class InventoryMenu +: public app::State { + +public: + explicit InventoryMenu(PartyMenu *parent); + +public: + virtual void HandleEvents(const app::Input &); + virtual void UpdateWorld(float deltaT); + virtual void Render(SDL_Surface *); + + int Width() const; + int Height() const; + +private: + virtual void OnEnterState(SDL_Surface *screen); + virtual void OnExitState(SDL_Surface *screen); + virtual void OnResumeState(SDL_Surface *screen); + virtual void OnPauseState(SDL_Surface *screen); + + virtual void OnResize(int width, int height); + + void RenderMenu(SDL_Surface *screen, const geometry::Vector &offset) const; + void RenderInventory(SDL_Surface *screen, const geometry::Vector &offset) const; + +private: + PartyMenu *parent; + graphics::Menu menu; + graphics::Menu itemMenu; + +}; + +} + +#endif /* MENU_INVENTORYMENU_H_ */ diff --git a/src/menu/PartyMenu.cpp b/src/menu/PartyMenu.cpp new file mode 100644 index 0000000..07b7770 --- /dev/null +++ b/src/menu/PartyMenu.cpp @@ -0,0 +1,209 @@ +/* + * PartyMenu.cpp + * + * Created on: Oct 21, 2012 + * Author: holy + */ + +#include "PartyMenu.h" + +#include "ChangeHero.h" +#include "InventoryMenu.h" +#include "Resources.h" +#include "SelectHero.h" +#include "StatusMenu.h" +#include "../app/Application.h" +#include "../app/Input.h" +#include "../common/GameConfig.h" +#include "../common/GameState.h" +#include "../geometry/Vector.h" +#include "../graphics/Font.h" +#include "../graphics/Frame.h" +#include "../graphics/Texture.h" + +using app::Input; +using common::GameConfig; +using geometry::Vector; + +namespace menu { + +PartyMenu::PartyMenu(GameConfig *game) +: game(game) +, mainMenu(*game->menuResources->mainMenuProperties) { + for (int i(0); i < 4; ++i) { + status[i].SetHero(game->state->party, i); + status[i].SetResources(game->menuResources); + } + statusPositions[0] = Vector(0, 0); + statusPositions[1] = Vector(status[0].Width(), 0); + statusPositions[2] = Vector(0, status[0].Height()); + statusPositions[3] = Vector(status[0].Width(), status[0].Height()); + + mainMenu.Add(Res().mainMenuItemText, 0); + mainMenu.Add(Res().mainMenuStatusText, 4); + mainMenu.Add(Res().mainMenuSpellText, 1); + mainMenu.Add(Res().mainMenuChangeText, 5); + mainMenu.Add(Res().mainMenuCapsuleText, 2); + mainMenu.Add(Res().mainMenuConfigText, 6); + mainMenu.Add(Res().mainMenuEquipmentText, 3); + mainMenu.Add(Res().mainMenuScenarioText, 7); +} + +PartyMenu::~PartyMenu() { + +} + + +void PartyMenu::OnEnterState(SDL_Surface *) { + +} + +void PartyMenu::OnExitState(SDL_Surface *) { + +} + +void PartyMenu::OnResumeState(SDL_Surface *) { + +} + +void PartyMenu::OnPauseState(SDL_Surface *) { + +} + + +void PartyMenu::OnResize(int width, int height) { + +} + + +void PartyMenu::HandleEvents(const Input &input) { + if (input.JustPressed(Input::ACTION_B)) { + Ctrl().PopState(); + return; + } + + if (input.JustPressed(Input::PAD_UP)) { + mainMenu.PreviousRow(); + } else if (input.JustPressed(Input::PAD_RIGHT)) { + mainMenu.NextItem(); + } else if (input.JustPressed(Input::PAD_DOWN)) { + mainMenu.NextRow(); + } else if (input.JustPressed(Input::PAD_LEFT)) { + mainMenu.PreviousItem(); + } + + if (input.JustPressed(Input::ACTION_A)) { + switch (mainMenu.Selected()) { + case MENU_ITEM_ITEM: + Ctrl().PushState(new InventoryMenu(this)); + break; + case MENU_ITEM_SPELL: + break; + case MENU_ITEM_CAPSULE: + break; + case MENU_ITEM_EQUIP: + break; + case MENU_ITEM_STATUS: + Ctrl().PushState(new SelectHero(this, this, this, OnStatusSelect)); + break; + case MENU_ITEM_CHANGE: + Ctrl().PushState(new ChangeHero(this)); + break; + case MENU_ITEM_CONFIG: + break; + case MENU_ITEM_SCENARIO: + break; + default: + break; + } + } +} + +void PartyMenu::UpdateWorld(float deltaT) { + +} + +void PartyMenu::Render(SDL_Surface *screen) { + Vector offset((screen->w - Width()) / 2, (screen->h - Height()) / 2); + + RenderBackground(screen); + RenderHeros(screen, offset); + RenderMenu(screen, offset + Vector(8 * Res().normalFont->CharWidth(), 13 * Res().normalFont->CharHeight() + Res().normalFont->CharHeight() / 8)); + RenderInfo(screen, offset + Vector(14 * Res().normalFont->CharWidth(), 21 * Res().normalFont->CharHeight() + Res().normalFont->CharHeight() / 8)); +} + +int PartyMenu::Width() const { + return 2 * (status[0].Width() + Res().normalFont->CharWidth()); +} + +int PartyMenu::Height() const { + return 2 * Res().normalFont->CharHeight() + + 2 * status[0].Height() + + Res().normalFont->CharHeight() + + 8 * Res().normalFont->CharHeight() + + 5 * Res().normalFont->CharHeight() + + 2 * Res().normalFont->CharHeight(); +} + +void PartyMenu::RenderBackground(SDL_Surface *screen) const { + Res().menubg->Render(screen, Vector(), Vector(screen->w, screen->h)); +} + +void PartyMenu::RenderHeros(SDL_Surface *screen, const Vector &offset) const { + for (int i(0); i < 4; ++i) { + status[i].Render(screen, offset + StatusOffset(i)); + } +} + +Vector PartyMenu::StatusOffset(int index) const { + return statusPositions[index] + Vector(Res().normalFont->CharWidth(), 2 * Res().normalFont->CharHeight()); +} + +void PartyMenu::RenderMenu(SDL_Surface *screen, const Vector &offset) const { + Vector menuOffset(3 * Res().normalFont->CharWidth(), Res().normalFont->CharHeight() + Res().normalFont->CharHeight() / 4); + + Res().statusFrame->Draw(screen, offset, 23 * Res().normalFont->CharWidth(), 8 * Res().normalFont->CharHeight()); + mainMenu.Draw(screen, offset + menuOffset); +} + +void PartyMenu::RenderInfo(SDL_Surface *screen, const Vector &offset) const { + Res().statusFrame->Draw(screen, offset, 17 * Res().normalFont->CharWidth(), 5 * Res().normalFont->CharHeight()); + + Vector timeLabelOffset(2 * Res().normalFont->CharWidth(), Res().normalFont->CharHeight() + Res().normalFont->CharHeight() / 4); + Res().normalFont->DrawString(Res().mainMenuTimeText, screen, offset + timeLabelOffset); + + Vector hoursOffset(timeLabelOffset.X() + 6 * Res().normalFont->CharWidth(), timeLabelOffset.Y()); + Res().normalFont->DrawNumber(game->state->time / 60 / 60, screen, offset + hoursOffset, 4); + + Vector timeSeparatorOffset(hoursOffset.X() + 4 * Res().normalFont->CharWidth(), hoursOffset.Y()); + Res().normalFont->DrawChar(':', screen, offset + timeSeparatorOffset); + + Vector minutesOffset(timeSeparatorOffset.X() + Res().normalFont->CharWidth(), timeSeparatorOffset.Y()); + Res().normalFont->DrawNumber(game->state->time / 60, screen, offset + minutesOffset, 2); + if (game->state->time / 60 < 10) { + Res().normalFont->DrawChar('0', screen, offset + minutesOffset); + } + + Vector goldLabelOffset(2 * Res().normalFont->CharWidth(), 2 * Res().normalFont->CharHeight() + Res().normalFont->CharHeight() * 3 / 4); + Res().normalFont->DrawString(Res().mainMenuGoldText, screen, offset + goldLabelOffset); + + Vector goldOffset(goldLabelOffset.X() + 6 * Res().normalFont->CharWidth(), goldLabelOffset.Y()); + Res().normalFont->DrawNumber(game->state->money, screen, offset + goldOffset, 7); +} + + +Resources &PartyMenu::Res() { + return *game->menuResources; +} + +const Resources &PartyMenu::Res() const { + return *game->menuResources; +} + +void PartyMenu::OnStatusSelect(void *ref, int index) { + PartyMenu *self(reinterpret_cast(ref)); + self->Ctrl().ChangeState( + new StatusMenu(self, index)); +} + +} diff --git a/src/menu/PartyMenu.h b/src/menu/PartyMenu.h new file mode 100644 index 0000000..fa1b92f --- /dev/null +++ b/src/menu/PartyMenu.h @@ -0,0 +1,82 @@ +/* + * PartyMenu.h + * + * Created on: Oct 21, 2012 + * Author: holy + */ + +#ifndef MENU_PARTYMENU_H_ +#define MENU_PARTYMENU_H_ + +#include "fwd.h" +#include "HeroStatus.h" +#include "../app/State.h" +#include "../common/fwd.h" +#include "../geometry/Vector.h" +#include "../graphics/Menu.h" + +namespace menu { + +class PartyMenu +: public app::State { + +public: + explicit PartyMenu(common::GameConfig *); + virtual ~PartyMenu(); + +public: + virtual void HandleEvents(const app::Input &); + virtual void UpdateWorld(float deltaT); + virtual void Render(SDL_Surface *); + +public: + common::GameConfig &Game() { return *game; } + const common::GameConfig &Game() const { return *game; } + Resources &Res(); + const Resources &Res() const; + + int Width() const; + int Height() const; + +public: + void RenderBackground(SDL_Surface *screen) const; + void RenderHeros(SDL_Surface *screen, const geometry::Vector &offset) const; + void RenderMenu(SDL_Surface *screen, const geometry::Vector &offset) const; + void RenderInfo(SDL_Surface *screen, const geometry::Vector &offset) const; + + geometry::Vector StatusOffset(int index) const; + const HeroStatus &GetHeroStatus(int index) const { return status[index]; } + + static void OnStatusSelect(void *, int); + +private: + virtual void OnEnterState(SDL_Surface *screen); + virtual void OnExitState(SDL_Surface *screen); + virtual void OnResumeState(SDL_Surface *screen); + virtual void OnPauseState(SDL_Surface *screen); + + virtual void OnResize(int width, int height); + +private: + enum MenuItem { + MENU_ITEM_ITEM, + MENU_ITEM_SPELL, + MENU_ITEM_CAPSULE, + MENU_ITEM_EQUIP, + MENU_ITEM_STATUS, + MENU_ITEM_CHANGE, + MENU_ITEM_CONFIG, + MENU_ITEM_SCENARIO, + }; + +private: + HeroStatus status[4]; + geometry::Vector statusPositions[4]; + common::GameConfig *game; + graphics::Menu mainMenu; + +}; + +} + +#endif /* MENU_PARTYMENU_H_ */ diff --git a/src/menu/Resources.cpp b/src/menu/Resources.cpp new file mode 100644 index 0000000..28f5cb6 --- /dev/null +++ b/src/menu/Resources.cpp @@ -0,0 +1,69 @@ +/* + * Resources.cpp + * + * Created on: Oct 21, 2012 + * Author: holy + */ + +#include "Resources.h" + +namespace menu { + +Resources::Resources() +: menubg(0) +, normalFont(0) +, statusFont(0) + +, menuCursor(0) +, menuActiveCursor(0) + +, statusLabels(0) +, statusFrame(0) + +, mainMenuProperties(0) +, mainMenuItemText(0) +, mainMenuSpellText(0) +, mainMenuCapsuleText(0) +, mainMenuEquipmentText(0) +, mainMenuStatusText(0) +, mainMenuChangeText(0) +, mainMenuConfigText(0) +, mainMenuScenarioText(0) + +, mainMenuTimeText(0) +, mainMenuGoldText(0) + +, heroCursor(0) +, heroCursorBlinkTime(0) + +, noEquipmentText(0) + +, shoulderNav(0) + +, atpLabel(0) +, dfpLabel(0) +, strLabel(0) +, aglLabel(0) +, intLabel(0) +, gutLabel(0) +, mgrLabel(0) + +, ipLabel(0) +, experienceLabel(0) +, nextLevelLabel(0) + +, statusMenuProperties(0) + +, nextLabel(0) +, returnLabel(0) + +, itemMenuProperties(0) +, itemMenuUseText(0) +, itemMenuSortText(0) +, itemMenuDropText(0) + +, inventoryMenuProperties(0) { + +} + +} diff --git a/src/menu/Resources.h b/src/menu/Resources.h new file mode 100644 index 0000000..05ceaf3 --- /dev/null +++ b/src/menu/Resources.h @@ -0,0 +1,78 @@ +/* + * Resources.h + * + * Created on: Oct 21, 2012 + * Author: holy + */ + +#ifndef MENU_RESOURCES_H_ +#define MENU_RESOURCES_H_ + +#include "../graphics/fwd.h" + +namespace menu { + +struct Resources { + + graphics::Texture *menubg; + + graphics::Font *normalFont; + graphics::Font *statusFont; + + graphics::Sprite *menuCursor; + graphics::Sprite *menuActiveCursor; + + graphics::Sprite *statusLabels; + graphics::Frame *statusFrame; + + graphics::MenuProperties *mainMenuProperties; + const char *mainMenuItemText; + const char *mainMenuSpellText; + const char *mainMenuCapsuleText; + const char *mainMenuEquipmentText; + const char *mainMenuStatusText; + const char *mainMenuChangeText; + const char *mainMenuConfigText; + const char *mainMenuScenarioText; + + const char *mainMenuTimeText; + const char *mainMenuGoldText; + + graphics::Sprite *heroCursor; + int heroCursorBlinkTime; + + const char *noEquipmentText; + + graphics::Sprite *shoulderNav; + + const char *atpLabel; + const char *dfpLabel; + const char *strLabel; + const char *aglLabel; + const char *intLabel; + const char *gutLabel; + const char *mgrLabel; + + const char *ipLabel; + const char *experienceLabel; + const char *nextLevelLabel; + + graphics::MenuProperties *statusMenuProperties; + + const char *nextLabel; + const char *returnLabel; + + graphics::MenuProperties *itemMenuProperties; + const char *itemMenuUseText; + const char *itemMenuSortText; + const char *itemMenuDropText; + + graphics::MenuProperties *inventoryMenuProperties; + + Resources(); + +}; + +} + +#endif /* MENU_RESOURCES_H_ */ diff --git a/src/menu/SelectHero.cpp b/src/menu/SelectHero.cpp new file mode 100644 index 0000000..12690db --- /dev/null +++ b/src/menu/SelectHero.cpp @@ -0,0 +1,134 @@ +/* + * SelectHero.cpp + * + * Created on: Oct 22, 2012 + * Author: holy + */ + +#include "SelectHero.h" + +#include "HeroStatus.h" +#include "PartyMenu.h" +#include "Resources.h" +#include "../app/Application.h" +#include "../app/Input.h" +#include "../common/GameConfig.h" +#include "../common/GameState.h" +#include "../common/Hero.h" +#include "../geometry/Vector.h" +#include "../graphics/Sprite.h" + +using app::Input; +using geometry::Vector; + +namespace menu { + +SelectHero::SelectHero(app::State *parent, PartyMenu *pm, void *ref, Callback cb, int cursor) +: parent(parent) +, partyMenu(pm) +, ref(ref) +, callback(cb) +, cursor(cursor) { + +} + + +void SelectHero::OnEnterState(SDL_Surface *) { + cursorBlink = GraphicsTimers().StartInterval(Res().heroCursorBlinkTime); +} + +void SelectHero::OnExitState(SDL_Surface *) { + +} + +void SelectHero::OnResumeState(SDL_Surface *) { + +} + +void SelectHero::OnPauseState(SDL_Surface *) { + +} + + +void SelectHero::OnResize(int width, int height) { + +} + + +void SelectHero::HandleEvents(const Input &input) { + if (input.JustPressed(Input::ACTION_A)) { + callback(ref, cursor); + } + if (input.JustPressed(Input::ACTION_B)) { + Ctrl().PopState(); + } + + if (input.JustPressed(Input::PAD_UP)) { + SelectUp(); + } else if (input.JustPressed(Input::PAD_RIGHT)) { + SelectRight(); + } else if (input.JustPressed(Input::PAD_DOWN)) { + SelectDown(); + } else if (input.JustPressed(Input::PAD_LEFT)) { + SelectLeft(); + } +} + +void SelectHero::SelectUp() { + cursor = (cursor + 2) % partyMenu->Game().state->partySize; + cursorBlink.Restart(); +} + +void SelectHero::SelectRight() { + cursor = (cursor + 1) % partyMenu->Game().state->partySize; + cursorBlink.Restart(); +} + +void SelectHero::SelectDown() { + cursor = (cursor + 2) % partyMenu->Game().state->partySize; + cursorBlink.Restart(); +} + +void SelectHero::SelectLeft() { + cursor = (cursor + 3) % partyMenu->Game().state->partySize; + cursorBlink.Restart(); +} + + +common::GameConfig &SelectHero::Game() { + return partyMenu->Game(); +} + +const common::GameConfig &SelectHero::Game() const { + return partyMenu->Game(); +} + +Resources &SelectHero::Res() { + return partyMenu->Res(); +} + +const Resources &SelectHero::Res() const { + return partyMenu->Res(); +} + + +void SelectHero::UpdateWorld(float deltaT) { + +} + + +void SelectHero::Render(SDL_Surface *screen) { + parent->Render(screen); + if (cursorBlink.Iteration() % 2 == 0) { + RenderCursor(screen); + } +} + +void SelectHero::RenderCursor(SDL_Surface *screen) const { + Vector position( + 0, Game().state->party[cursor]->BattleSprite()->Height()); + position += partyMenu->StatusOffset(cursor); + Res().heroCursor->Draw(screen, position); +} + +} diff --git a/src/menu/SelectHero.h b/src/menu/SelectHero.h new file mode 100644 index 0000000..5e67152 --- /dev/null +++ b/src/menu/SelectHero.h @@ -0,0 +1,67 @@ +/* + * SelectHero.h + * + * Created on: Oct 22, 2012 + * Author: holy + */ + +#ifndef MENU_SELECTHERO_H_ +#define MENU_SELECTHERO_H_ + +#include "fwd.h" +#include "../app/State.h" +#include "../app/Timer.h" +#include "../common/fwd.h" + +#include + +namespace menu { + +class SelectHero +: public app::State { + +public: + typedef void (*Callback)(void *, int selection); + +public: + SelectHero(app::State *parent, PartyMenu *partyMenu, void *ref, Callback, int initialHero = 0); + +public: + virtual void HandleEvents(const app::Input &); + virtual void UpdateWorld(float deltaT); + virtual void Render(SDL_Surface *); + +private: + virtual void OnEnterState(SDL_Surface *screen); + virtual void OnExitState(SDL_Surface *screen); + virtual void OnResumeState(SDL_Surface *screen); + virtual void OnPauseState(SDL_Surface *screen); + + virtual void OnResize(int width, int height); + +private: + common::GameConfig &Game(); + const common::GameConfig &Game() const; + Resources &Res(); + const Resources &Res() const; + + void SelectUp(); + void SelectRight(); + void SelectDown(); + void SelectLeft(); + + void RenderCursor(SDL_Surface *screen) const; + +private: + app::State *parent; + PartyMenu *partyMenu; + void *ref; + Callback callback; + app::Timer cursorBlink; + int cursor; + +}; + +} + +#endif /* MENU_SELECTHERO_H_ */ diff --git a/src/menu/StatusMenu.cpp b/src/menu/StatusMenu.cpp new file mode 100644 index 0000000..3a9b38f --- /dev/null +++ b/src/menu/StatusMenu.cpp @@ -0,0 +1,266 @@ +/* + * StatusMenu.cpp + * + * Created on: Oct 22, 2012 + * Author: holy + */ + +#include "StatusMenu.h" + +#include "HeroStatus.h" +#include "PartyMenu.h" +#include "Resources.h" +#include "../app/Application.h" +#include "../app/Input.h" +#include "../common/GameConfig.h" +#include "../common/GameState.h" +#include "../common/Hero.h" +#include "../common/Item.h" +#include "../common/Stats.h" +#include "../graphics/Font.h" +#include "../graphics/Frame.h" + +using app::Input; +using common::Hero; +using common::Item; +using common::Stats; +using geometry::Vector; +using graphics::Font; +using graphics::Frame; + +namespace menu { + +StatusMenu::StatusMenu(PartyMenu *parent, int cursor) +: parent(parent) +, cursor(cursor) +, menu(*parent->Res().statusMenuProperties) { + menu.Add(parent->Res().nextLabel, 0); + menu.Add(parent->Res().returnLabel, 1); +} + + +void StatusMenu::OnEnterState(SDL_Surface *) { + +} + +void StatusMenu::OnExitState(SDL_Surface *) { + +} + +void StatusMenu::OnResumeState(SDL_Surface *) { + +} + +void StatusMenu::OnPauseState(SDL_Surface *) { + +} + + +void StatusMenu::OnResize(int width, int height) { + +} + + +void StatusMenu::HandleEvents(const Input &input) { + if (input.JustPressed(Input::SHOULDER_RIGHT)) { + NextHero(); + } + if (input.JustPressed(Input::SHOULDER_LEFT)) { + PreviousHero(); + } + + if (input.JustPressed(Input::PAD_LEFT)) { + menu.PreviousItem(); + } + if (input.JustPressed(Input::PAD_RIGHT)) { + menu.NextItem(); + } + + if (input.JustPressed(Input::ACTION_A)) { + if (menu.Selected() == 0) { + NextHero(); + } else if (menu.Selected() == 1) { + Ctrl().PopState(); + } + } + if (input.JustPressed(Input::ACTION_B)) { + Ctrl().PopState(); + } +} + +void StatusMenu::UpdateWorld(float deltaT) { + +} + +void StatusMenu::Render(SDL_Surface *screen) { + Vector offset((screen->w - Width()) / 2, (screen->h - Height()) / 2); + Vector shoulderNavOffset( + 5 * parent->Res().statusFont->CharWidth(), + parent->Res().statusFont->CharHeight()); + Vector statsOffset( + 4 * parent->Res().statusFont->CharWidth(), + 8 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8); + Vector equipOffset( + 17 * parent->Res().statusFont->CharWidth(), + 4 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8); + Vector experienceOffset( + 11 * parent->Res().statusFont->CharWidth(), + 17 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8); + Vector nextLevelOffset( + 11 * parent->Res().statusFont->CharWidth(), + 20 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8); + Vector ikariOffset( + 17 * parent->Res().statusFont->CharWidth(), + 17 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8); + Vector menuOffset( + parent->Res().statusFont->CharWidth(), + 23 * parent->Res().statusFont->CharHeight() - parent->Res().statusFont->CharHeight() / 8); + + parent->RenderBackground(screen); + parent->Res().shoulderNav->Draw(screen, offset + shoulderNavOffset); + RenderStatus(screen, offset + parent->StatusOffset(0)); + RenderStats(screen, offset + statsOffset); + RenderEquipment(screen, offset + equipOffset); + RenderExperience(screen, experienceOffset); + RenderNextLevel(screen, nextLevelOffset); + RenderIkari(screen, ikariOffset); + RenderMenu(screen, menuOffset); +} + +int StatusMenu::Width() const { + return parent->Width(); +} + +int StatusMenu::Height() const { + return parent->Height(); +} + +void StatusMenu::RenderStatus(SDL_Surface *screen, const Vector &offset) const { + parent->GetHeroStatus(cursor).Render(screen, offset); +} + +void StatusMenu::RenderStats(SDL_Surface *screen, const Vector &offset) const { + const Stats &stats(GetHero().GetStats()); + Vector lineBreak(0, parent->Res().statusFont->CharHeight()); + + Vector position(offset); + RenderStatsLine(parent->Res().atpLabel, stats.Attack(), screen, position); + + position += lineBreak; + RenderStatsLine(parent->Res().dfpLabel, stats.Defense(), screen, position); + + position += lineBreak; + RenderStatsLine(parent->Res().strLabel, stats.Strength(), screen, position); + + position += lineBreak; + RenderStatsLine(parent->Res().aglLabel, stats.Agility(), screen, position); + + position += lineBreak; + RenderStatsLine(parent->Res().intLabel, stats.Intelligence(), screen, position); + + position += lineBreak; + RenderStatsLine(parent->Res().gutLabel, stats.Gut(), screen, position); + + position += lineBreak; + RenderStatsLine(parent->Res().mgrLabel, stats.MagicResistance(), screen, position); +} + +void StatusMenu::RenderStatsLine(const char *label, int number, SDL_Surface *screen, const Vector &position) const { + const Font &font(*parent->Res().statusFont); + const Vector numberOffset(4 * font.CharWidth(), 0); + + font.DrawString(label, screen, position, 3); + font.DrawNumber(number, screen, position + numberOffset, 3); +} + +void StatusMenu::RenderEquipment(SDL_Surface *screen, const Vector &offset) const { + const Hero &hero(GetHero()); + Vector lineBreak(0, 2 * parent->Res().statusFont->CharHeight()); + + Vector position(offset); + RenderEquipmentLine(hero.Weapon(), screen, position); + + position += lineBreak; + RenderEquipmentLine(hero.Armor(), screen, position); + + position += lineBreak; + RenderEquipmentLine(hero.Shield(), screen, position); + + position += lineBreak; + RenderEquipmentLine(hero.Helmet(), screen, position); + + position += lineBreak; + RenderEquipmentLine(hero.Ring(), screen, position); + + position += lineBreak; + RenderEquipmentLine(hero.Jewel(), screen, position); +} + +void StatusMenu::RenderEquipmentLine(const Item *item, SDL_Surface *screen, const Vector &position) const { + const Font &font(*parent->Res().statusFont); + const Vector textOffset(font.CharWidth(), 0); + if (item) { + if (item->MenuIcon()) { + item->MenuIcon()->Draw(screen, position); + } + font.DrawString(item->Name(), screen, position + textOffset); + } else { + font.DrawString(parent->Res().noEquipmentText, screen, position + textOffset); + } +} + +void StatusMenu::RenderExperience(SDL_Surface *screen, const geometry::Vector &offset) const { + const Font &font(*parent->Res().statusFont); + font.DrawStringRight(parent->Res().experienceLabel, screen, offset, 10); + + Vector numberOffset(offset.X(), offset.Y() + font.CharHeight()); + font.DrawNumberRight(GetHero().Experience(), screen, numberOffset, 7); +} + +void StatusMenu::RenderNextLevel(SDL_Surface *screen, const geometry::Vector &offset) const { + const Font &font(*parent->Res().statusFont); + font.DrawStringRight(parent->Res().nextLevelLabel, screen, offset, 10); + + Vector numberOffset(offset.X(), offset.Y() + font.CharHeight()); + font.DrawNumberRight(GetHero().NextLevel(), screen, numberOffset, 7); +} + +void StatusMenu::RenderIkari(SDL_Surface *screen, const geometry::Vector &offset) const { + const Font &font(*parent->Res().statusFont); + font.DrawString(parent->Res().ipLabel, screen, offset, 5); + + Vector numberOffset(offset.X() + 5 * font.CharWidth(), offset.Y()); + font.DrawNumber(GetHero().RelativeIP(100), screen, numberOffset, 3); + + Vector percentOffset(offset.X() + 8 * font.CharWidth(), offset.Y()); + font.DrawChar('%', screen, percentOffset); +} + +void StatusMenu::RenderMenu(SDL_Surface *screen, const geometry::Vector &offset) const { + const Font &font(*parent->Res().normalFont); + const Frame &frame(*parent->Res().statusFrame); + + Vector labelOffset(2 * font.CharWidth(), font.CharHeight()); + frame.Draw(screen, offset, 10 * font.CharWidth(), 3 * font.CharHeight()); + font.DrawString(parent->Res().mainMenuStatusText, screen, offset + labelOffset); + + Vector menuFrameOffset(10 * font.CharWidth(), 0); + Vector menuOffset(13 * font.CharWidth(), font.CharHeight()); + frame.Draw(screen, offset + menuFrameOffset, 20 * font.CharWidth(), 3 * font.CharHeight()); + menu.Draw(screen, offset + menuOffset); +} + + +void StatusMenu::NextHero() { + cursor = (cursor + 1) % parent->Game().state->partySize; +} + +void StatusMenu::PreviousHero() { + cursor = (cursor + parent->Game().state->partySize - 1) % parent->Game().state->partySize; +} + +const Hero &StatusMenu::GetHero() const { + return *parent->Game().state->party[cursor]; +} + +} diff --git a/src/menu/StatusMenu.h b/src/menu/StatusMenu.h new file mode 100644 index 0000000..5f6f986 --- /dev/null +++ b/src/menu/StatusMenu.h @@ -0,0 +1,68 @@ +/* + * StatusMenu.h + * + * Created on: Oct 22, 2012 + * Author: holy + */ + +#ifndef MENU_STATUSMENU_H_ +#define MENU_STATUSMENU_H_ + +#include "fwd.h" +#include "../app/State.h" +#include "../common/fwd.h" +#include "../geometry/Vector.h" +#include "../graphics/Menu.h" + +namespace menu { + +class StatusMenu +: public app::State { + +public: + StatusMenu(PartyMenu *parent, int heroIndex); + +public: + virtual void HandleEvents(const app::Input &); + virtual void UpdateWorld(float deltaT); + virtual void Render(SDL_Surface *); + +public: + int Width() const; + int Height() const; + +private: + virtual void OnEnterState(SDL_Surface *screen); + virtual void OnExitState(SDL_Surface *screen); + virtual void OnResumeState(SDL_Surface *screen); + virtual void OnPauseState(SDL_Surface *screen); + + virtual void OnResize(int width, int height); + + void NextHero(); + void PreviousHero(); + + const common::Hero &GetHero() const; + + void RenderStatus(SDL_Surface *screen, const geometry::Vector &offset) const; + void RenderStats(SDL_Surface *screen, const geometry::Vector &offset) const; + void RenderStatsLine(const char *label, int number, SDL_Surface *screen, const geometry::Vector &position) const; + void RenderEquipment(SDL_Surface *screen, const geometry::Vector &offset) const; + void RenderEquipmentLine(const common::Item *, SDL_Surface *screen, const geometry::Vector &position) const; + /// @param offset the top right corner! + void RenderExperience(SDL_Surface *screen, const geometry::Vector &offset) const; + /// @param offset the top right corner! + void RenderNextLevel(SDL_Surface *screen, const geometry::Vector &offset) const; + void RenderIkari(SDL_Surface *screen, const geometry::Vector &offset) const; + void RenderMenu(SDL_Surface *screen, const geometry::Vector &offset) const; + +private: + PartyMenu *parent; + int cursor; + graphics::Menu menu; + +}; + +} + +#endif /* MENU_STATUSMENU_H_ */ diff --git a/src/menu/fwd.h b/src/menu/fwd.h new file mode 100644 index 0000000..5e08e00 --- /dev/null +++ b/src/menu/fwd.h @@ -0,0 +1,23 @@ +/* + * fwd.h + * + * Created on: Oct 21, 2012 + * Author: holy + */ + +#ifndef MENU_FWD_H_ +#define MENU_FWD_H_ + +namespace menu { + +class ChangeHero; +class HeroStatus; +class InventoryMenu; +class PartyMenu; +struct Resources; +class SelectHero; +class StatusMenu; + +} + +#endif /* MENU_FWD_H_ */ diff --git a/test-data/hero-cursor.png b/test-data/hero-cursor.png new file mode 100644 index 0000000..0496815 Binary files /dev/null and b/test-data/hero-cursor.png differ diff --git a/test-data/menu-cursor-active.png b/test-data/menu-cursor-active.png new file mode 100644 index 0000000..bee2487 Binary files /dev/null and b/test-data/menu-cursor-active.png differ diff --git a/test-data/menu-cursor.png b/test-data/menu-cursor.png new file mode 100644 index 0000000..b5743f1 Binary files /dev/null and b/test-data/menu-cursor.png differ diff --git a/test-data/menu-font.png b/test-data/menu-font.png new file mode 100644 index 0000000..a8122a8 Binary files /dev/null and b/test-data/menu-font.png differ diff --git a/test-data/menubg.png b/test-data/menubg.png new file mode 100644 index 0000000..1b42927 Binary files /dev/null and b/test-data/menubg.png differ diff --git a/test-data/normal-font.png b/test-data/normal-font.png index 8a1532b..0c49e2c 100644 Binary files a/test-data/normal-font.png and b/test-data/normal-font.png differ diff --git a/test-data/shoulder-nav.png b/test-data/shoulder-nav.png new file mode 100644 index 0000000..54edbe6 Binary files /dev/null and b/test-data/shoulder-nav.png differ diff --git a/test-data/status-frame.png b/test-data/status-frame.png new file mode 100644 index 0000000..c6ea569 Binary files /dev/null and b/test-data/status-frame.png differ diff --git a/test-data/status-labels.png b/test-data/status-labels.png new file mode 100644 index 0000000..93fcebc Binary files /dev/null and b/test-data/status-labels.png differ diff --git a/test-data/test.l2s b/test-data/test.l2s index 4a4bb05..1267b9f 100644 --- a/test-data/test.l2s +++ b/test-data/test.l2s @@ -88,6 +88,9 @@ export Hero maxim { gut: 100, mgr: 10 }, + ladder: [ + 10 + ], attackAnimation: ComplexAnimation { sprite: maximSprite, frametime: frameTime,