From c0860451b5fd681c3b3b8d985e8831276bbd917f Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Mon, 6 Aug 2012 16:54:35 +0200 Subject: [PATCH] added attack type selection menu in battle state also added a test sprite for the menu icons executables need to be run from the project root in order for main to find the test data files --- Debug/objects.mk | 2 +- Debug/src/battle/subdir.mk | 3 ++ Debug/src/sdl/subdir.mk | 3 ++ Release/objects.mk | 2 +- Release/src/battle/subdir.mk | 3 ++ Release/src/sdl/subdir.mk | 3 ++ src/battle/AttackTypeMenu.cpp | 49 ++++++++++++++++++++++++ src/battle/AttackTypeMenu.h | 48 ++++++++++++++++++++++++ src/battle/BattleState.cpp | 5 ++- src/battle/BattleState.h | 9 ++++- src/main.cpp | 64 ++++++++++++++++++-------------- src/sdl/InitImage.cpp | 27 ++++++++++++++ src/sdl/InitImage.h | 26 +++++++++++++ test-data/attack-type-icons.png | Bin 0 -> 4544 bytes 14 files changed, 210 insertions(+), 34 deletions(-) create mode 100644 src/battle/AttackTypeMenu.cpp create mode 100644 src/battle/AttackTypeMenu.h create mode 100644 src/sdl/InitImage.cpp create mode 100644 src/sdl/InitImage.h create mode 100644 test-data/attack-type-icons.png diff --git a/Debug/objects.mk b/Debug/objects.mk index b99d1e5..718d8a1 100644 --- a/Debug/objects.mk +++ b/Debug/objects.mk @@ -4,5 +4,5 @@ USER_OBJS := -LIBS := -lSDL +LIBS := -lSDL -lSDL_image diff --git a/Debug/src/battle/subdir.mk b/Debug/src/battle/subdir.mk index 52e0e02..d0073bc 100644 --- a/Debug/src/battle/subdir.mk +++ b/Debug/src/battle/subdir.mk @@ -4,18 +4,21 @@ # Add inputs and outputs from these tool invocations to the build variables CPP_SRCS += \ +../src/battle/AttackTypeMenu.cpp \ ../src/battle/BattleState.cpp \ ../src/battle/Hero.cpp \ ../src/battle/Monster.cpp \ ../src/battle/PartyLayout.cpp OBJS += \ +./src/battle/AttackTypeMenu.o \ ./src/battle/BattleState.o \ ./src/battle/Hero.o \ ./src/battle/Monster.o \ ./src/battle/PartyLayout.o CPP_DEPS += \ +./src/battle/AttackTypeMenu.d \ ./src/battle/BattleState.d \ ./src/battle/Hero.d \ ./src/battle/Monster.d \ diff --git a/Debug/src/sdl/subdir.mk b/Debug/src/sdl/subdir.mk index 67239ce..b800be3 100644 --- a/Debug/src/sdl/subdir.mk +++ b/Debug/src/sdl/subdir.mk @@ -4,14 +4,17 @@ # Add inputs and outputs from these tool invocations to the build variables CPP_SRCS += \ +../src/sdl/InitImage.cpp \ ../src/sdl/InitSDL.cpp \ ../src/sdl/InitScreen.cpp OBJS += \ +./src/sdl/InitImage.o \ ./src/sdl/InitSDL.o \ ./src/sdl/InitScreen.o CPP_DEPS += \ +./src/sdl/InitImage.d \ ./src/sdl/InitSDL.d \ ./src/sdl/InitScreen.d diff --git a/Release/objects.mk b/Release/objects.mk index b99d1e5..718d8a1 100644 --- a/Release/objects.mk +++ b/Release/objects.mk @@ -4,5 +4,5 @@ USER_OBJS := -LIBS := -lSDL +LIBS := -lSDL -lSDL_image diff --git a/Release/src/battle/subdir.mk b/Release/src/battle/subdir.mk index 6cff662..d1c5b2f 100644 --- a/Release/src/battle/subdir.mk +++ b/Release/src/battle/subdir.mk @@ -4,18 +4,21 @@ # Add inputs and outputs from these tool invocations to the build variables CPP_SRCS += \ +../src/battle/AttackTypeMenu.cpp \ ../src/battle/BattleState.cpp \ ../src/battle/Hero.cpp \ ../src/battle/Monster.cpp \ ../src/battle/PartyLayout.cpp OBJS += \ +./src/battle/AttackTypeMenu.o \ ./src/battle/BattleState.o \ ./src/battle/Hero.o \ ./src/battle/Monster.o \ ./src/battle/PartyLayout.o CPP_DEPS += \ +./src/battle/AttackTypeMenu.d \ ./src/battle/BattleState.d \ ./src/battle/Hero.d \ ./src/battle/Monster.d \ diff --git a/Release/src/sdl/subdir.mk b/Release/src/sdl/subdir.mk index ad789ab..3bef090 100644 --- a/Release/src/sdl/subdir.mk +++ b/Release/src/sdl/subdir.mk @@ -4,14 +4,17 @@ # Add inputs and outputs from these tool invocations to the build variables CPP_SRCS += \ +../src/sdl/InitImage.cpp \ ../src/sdl/InitSDL.cpp \ ../src/sdl/InitScreen.cpp OBJS += \ +./src/sdl/InitImage.o \ ./src/sdl/InitSDL.o \ ./src/sdl/InitScreen.o CPP_DEPS += \ +./src/sdl/InitImage.d \ ./src/sdl/InitSDL.d \ ./src/sdl/InitScreen.d diff --git a/src/battle/AttackTypeMenu.cpp b/src/battle/AttackTypeMenu.cpp new file mode 100644 index 0000000..2a23a09 --- /dev/null +++ b/src/battle/AttackTypeMenu.cpp @@ -0,0 +1,49 @@ +/* + * AttackTypeMenu.cpp + * + * Created on: Aug 6, 2012 + * Author: holy + */ + +#include "AttackTypeMenu.h" + +#include "../app/Input.h" +#include "../geometry/operators.h" +#include "../geometry/Vector.h" +#include "../graphics/Sprite.h" + +using app::Input; +using geometry::Point; +using geometry::Vector; + +namespace battle { + +void AttackTypeMenu::ReadInput(const Input &input) { + if (input.IsDown(Input::PAD_UP)) { + selected = MAGIC; + } else if (input.IsDown(Input::PAD_RIGHT)) { + selected = DEFEND; + } else if (input.IsDown(Input::PAD_DOWN)) { + selected = IKARI; + } else if (input.IsDown(Input::PAD_LEFT)) { + selected = ITEM; + } else { + selected = SWORD; + } +} + +void AttackTypeMenu::Render(SDL_Surface *screen, const geometry::Point ¢er) { + Vector swordOffset(icons->Width() / -2, icons->Height() / -2); + Vector magicOffset(swordOffset.X(), swordOffset.Y() - icons->Height()); + Vector defendOffset(swordOffset.X() + icons->Width(), swordOffset.Y()); + Vector ikariOffset(swordOffset.X(), swordOffset.Y() + icons->Height()); + Vector itemOffset(swordOffset.X() - icons->Width(), swordOffset.Y()); + + icons->Draw(screen, center + swordOffset, SWORD, (selected == SWORD) ? 1 : 0); + icons->Draw(screen, center + magicOffset, MAGIC, (selected == MAGIC) ? 1 : 0); + icons->Draw(screen, center + defendOffset, DEFEND, (selected == DEFEND) ? 1 : 0); + icons->Draw(screen, center + ikariOffset, IKARI, (selected == IKARI) ? 1 : 0); + icons->Draw(screen, center + itemOffset, ITEM, (selected == ITEM) ? 1 : 0); +} + +} diff --git a/src/battle/AttackTypeMenu.h b/src/battle/AttackTypeMenu.h new file mode 100644 index 0000000..b63ec97 --- /dev/null +++ b/src/battle/AttackTypeMenu.h @@ -0,0 +1,48 @@ +/* + * AttackTypeMenu.h + * + * Created on: Aug 6, 2012 + * Author: holy + */ + +#ifndef BATTLE_ATTACKTYPEMENU_H_ +#define BATTLE_ATTACKTYPEMENU_H_ + +namespace app { class Input; } +namespace graphics { class Sprite; } + +#include "../geometry/Point.h" + +#include + +namespace battle { + +class AttackTypeMenu { + +public: + enum Icon { + SWORD, + MAGIC, + DEFEND, + IKARI, + ITEM + }; + +public: + explicit AttackTypeMenu(const graphics::Sprite *icons) + : icons(icons), selected(SWORD) { } + +public: + void ReadInput(const app::Input &); + Icon Selected() const { return selected; } + void Render(SDL_Surface *screen, const geometry::Point ¢er); + +private: + const graphics::Sprite *icons; + Icon selected; + +}; + +} + +#endif /* BATTLE_ATTACKTYPEMENU_H_ */ diff --git a/src/battle/BattleState.cpp b/src/battle/BattleState.cpp index 9f1acac..b11f52c 100644 --- a/src/battle/BattleState.cpp +++ b/src/battle/BattleState.cpp @@ -55,7 +55,7 @@ void BattleState::ExitState() { void BattleState::HandleInput(const Input &input) { - + attackTypeMenu.ReadInput(input); } void BattleState::UpdateWorld(float deltaT) { @@ -69,7 +69,8 @@ void BattleState::Render(SDL_Surface *screen) { RenderBackground(screen, offset); RenderMonsters(screen, offset); - RenderHeroes(screen, offset); +// RenderHeroes(screen, offset); + attackTypeMenu.Render(screen, Point(background->w / 2, background->h * 3 / 4)); } void BattleState::RenderBackground(SDL_Surface *screen, const Vector &offset) { diff --git a/src/battle/BattleState.h b/src/battle/BattleState.h index 397e5e3..9e504ed 100644 --- a/src/battle/BattleState.h +++ b/src/battle/BattleState.h @@ -8,6 +8,7 @@ #ifndef BATTLE_BATTLESTATE_H_ #define BATTLE_BATTLESTATE_H_ +#include "AttackTypeMenu.h" #include "Hero.h" #include "Monster.h" #include "../app/State.h" @@ -18,19 +19,22 @@ #include namespace app { class Input; } +namespace graphics { class Sprite; } namespace battle { class PartyLayout; +// TODO: maybe split battle state into substates for each menu? class BattleState : public app::State { public: - BattleState(SDL_Surface *background, const PartyLayout &monstersLayout, const PartyLayout &heroesLayout) + BattleState(SDL_Surface *background, const PartyLayout &monstersLayout, const PartyLayout &heroesLayout, const graphics::Sprite *attackIcons) : background(background) , monstersLayout(&monstersLayout) - , heroesLayout(&heroesLayout) { } + , heroesLayout(&heroesLayout) + , attackTypeMenu(attackIcons) { } public: void AddMonster(const Monster &); @@ -55,6 +59,7 @@ private: SDL_Surface *background; const PartyLayout *monstersLayout; const PartyLayout *heroesLayout; + AttackTypeMenu attackTypeMenu; std::vector > monsterPositions; std::vector > heroesPositions; std::vector monsters; diff --git a/src/main.cpp b/src/main.cpp index 6bce28f..4ea0e0e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,11 +13,14 @@ #include "battle/PartyLayout.h" #include "geometry/Point.h" #include "graphics/Sprite.h" +#include "sdl/InitImage.h" #include "sdl/InitScreen.h" #include "sdl/InitSDL.h" #include #include +#include +#include using app::Application; using app::Input; @@ -27,6 +30,7 @@ using battle::Monster; using battle::PartyLayout; using geometry::Point; using graphics::Sprite; +using sdl::InitImage; using sdl::InitScreen; using sdl::InitSDL; @@ -39,38 +43,42 @@ int main(int argc, char **argv) { const int width = 800; const int height = 480; - // temporary test data - SDL_Surface *bg(SDL_CreateRGBSurface(0, width, height, 32, 0xFF000000, 0xFF0000, 0xFF00, 0xFF)); - SDL_FillRect(bg, 0, SDL_MapRGB(bg->format, 0xFF, 0xFF, 0xFF)); - SDL_Rect r; - r.x = 1; - r.y = 1; - r.w = width - 2; - r.h = height - 2; - SDL_FillRect(bg, &r, SDL_MapRGB(bg->format, 0, 0, 0)); - PartyLayout monstersLayout; - monstersLayout.AddPosition(Point(50, 100)); - monstersLayout.AddPosition(Point(100, 100)); - monstersLayout.AddPosition(Point(150, 100)); - monstersLayout.AddPosition(Point(200, 100)); - PartyLayout heroesLayout; - heroesLayout.AddPosition(Point(27, 219)); - heroesLayout.AddPosition(Point(104, 227)); - heroesLayout.AddPosition(Point(66, 238)); - heroesLayout.AddPosition(Point(143, 246)); - SDL_Surface *white96(SDL_CreateRGBSurface(0, 96, 96, 32, 0xFF000000, 0xFF0000, 0xFF00, 0xFF)); - SDL_FillRect(white96, 0, SDL_MapRGB(bg->format, 0xFF, 0xFF, 0xFF)); - Sprite dummySprite(white96, 96, 96); - Monster monster; - monster.SetSprite(&dummySprite); - Hero hero; - hero.SetSprite(&dummySprite); - try { InitSDL sdl; + InitImage image(IMG_INIT_PNG); InitScreen screen(width, height); - BattleState *battleState(new BattleState(bg, monstersLayout, heroesLayout)); + // temporary test data + SDL_Surface *bg(SDL_CreateRGBSurface(0, width, height, 32, 0xFF000000, 0xFF0000, 0xFF00, 0xFF)); + SDL_FillRect(bg, 0, SDL_MapRGB(bg->format, 0xFF, 0xFF, 0xFF)); + SDL_Rect r; + r.x = 1; + r.y = 1; + r.w = width - 2; + r.h = height - 2; + SDL_FillRect(bg, &r, SDL_MapRGB(bg->format, 0, 0, 0)); + PartyLayout monstersLayout; + monstersLayout.AddPosition(Point(50, 100)); + monstersLayout.AddPosition(Point(100, 100)); + monstersLayout.AddPosition(Point(150, 100)); + monstersLayout.AddPosition(Point(200, 100)); + PartyLayout heroesLayout; + heroesLayout.AddPosition(Point(27, 219)); + heroesLayout.AddPosition(Point(104, 227)); + heroesLayout.AddPosition(Point(66, 238)); + heroesLayout.AddPosition(Point(143, 246)); + SDL_Surface *white96(SDL_CreateRGBSurface(0, 96, 96, 32, 0xFF000000, 0xFF0000, 0xFF00, 0xFF)); + SDL_FillRect(white96, 0, SDL_MapRGB(bg->format, 0xFF, 0xFF, 0xFF)); + Sprite dummySprite(white96, 96, 96); + Monster monster; + monster.SetSprite(&dummySprite); + Hero hero; + hero.SetSprite(&dummySprite); + + SDL_Surface *attackIcons(IMG_Load("test-data/attack-type-icons.png")); + Sprite attackIconsSprite(attackIcons, 32, 32); + + BattleState *battleState(new BattleState(bg, monstersLayout, heroesLayout, &attackIconsSprite)); battleState->AddMonster(monster); battleState->AddMonster(monster); battleState->AddMonster(monster); diff --git a/src/sdl/InitImage.cpp b/src/sdl/InitImage.cpp new file mode 100644 index 0000000..2c7dfcd --- /dev/null +++ b/src/sdl/InitImage.cpp @@ -0,0 +1,27 @@ +/* + * InitImage.cpp + * + * Created on: Aug 6, 2012 + * Author: holy + */ + +#include "InitImage.h" + +#include +#include + +using std::runtime_error; + +namespace sdl { + +InitImage::InitImage(int flags) { + if (IMG_Init(flags) != flags) { + throw runtime_error(IMG_GetError()); + } +} + +InitImage::~InitImage() { + IMG_Quit(); +} + +} diff --git a/src/sdl/InitImage.h b/src/sdl/InitImage.h new file mode 100644 index 0000000..425b7fe --- /dev/null +++ b/src/sdl/InitImage.h @@ -0,0 +1,26 @@ +/* + * InitImage.h + * + * Created on: Aug 6, 2012 + * Author: holy + */ + +#ifndef SDL_INITIMAGE_H_ +#define SDL_INITIMAGE_H_ + +namespace sdl { + +class InitImage { + +public: + explicit InitImage(int flags); + ~InitImage(); +private: + InitImage(const InitImage &); + InitImage &operator =(const InitImage &); + +}; + +} + +#endif /* SDL_INITIMAGE_H_ */ diff --git a/test-data/attack-type-icons.png b/test-data/attack-type-icons.png new file mode 100644 index 0000000000000000000000000000000000000000..65791f5dfeed0ce57714a7d08f53eb40ceb4e3ef GIT binary patch literal 4544 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 literal 0 HcmV?d00001 -- 2.39.2