using app::Input;
using geometry::Point;
using geometry::Vector;
+using graphics::Menu;
using std::vector;
heroesLayout->CalculatePositions(background->w, background->h, heroesPositions);
attackChoices.resize(heroes.size());
for (vector<Hero>::size_type i(0), end(heroes.size()); i < end; ++i) {
+ // TODO: extract menu dimensions to resources
+ Menu</* Spell */ void *> spellMenu(res->normalFont, 12, 6, 8, 2, 32);
+ spellMenu.Add("Strong : 3", 0);
+ spellMenu.Add("Stronger : 8", 0);
+ spellMenu.Add("Champion :16", 0);
+ spellMenu.Add("Rally :10", 0);
+ spellMenu.Add("Valor :30", 0);
+ spellMenus.push_back(spellMenu);
heroTags.push_back(HeroTag(&heroes[i], &attackChoices[i], res, HeroTag::Alignment((i + 1) % 2)));
}
}
#include "../app/State.h"
#include "../geometry/Point.h"
#include "../geometry/Vector.h"
+#include "../graphics/Menu.h"
#include <vector>
#include <SDL.h>
bool HasChosenAttackType() const { return attackChoices[activeHero].GetType() != AttackChoice::UNDECIDED; }
void SetAttackType(AttackChoice::Type t) { attackChoices[activeHero].SetType(t); }
bool AttackSelectionDone() const { return activeHero >= (int) heroes.size(); }
+ const graphics::Menu</* Spell */ void *> GetSpellMenu() const { return spellMenus[activeHero]; }
public:
geometry::Vector<int> CalculateScreenOffset(SDL_Surface *screen) const {
std::vector<geometry::Point<int> > heroesPositions;
std::vector<Monster> monsters;
std::vector<Hero> heroes;
+ std::vector<graphics::Menu</* Spell */ void *> > spellMenus;
std::vector<HeroTag> heroTags;
std::vector<AttackChoice> attackChoices;
int activeHero;
void SelectSpell::Render(SDL_Surface *screen) {
parent->Render(screen);
+ Vector<int> offset(battle->CalculateScreenOffset(screen));
+ RenderFrame(screen, offset);
+ RenderMenu(screen, offset);
+}
+
+void SelectSpell::RenderFrame(SDL_Surface *screen, const Vector<int> &offset) {
const Frame *frame(battle->Res().selectFrame);
Point<int> position(frame->BorderWidth(), frame->BorderHeight());
- Vector<int> offset(battle->CalculateScreenOffset(screen));
int width(battle->BackgroundWidth() - 2 * frame->BorderWidth());
// TODO: replace with font height
int height(frame->BorderHeight() * 13);
frame->Draw(screen, position + offset, width, height);
}
+void SelectSpell::RenderMenu(SDL_Surface *screen, const Vector<int> &offset) {
+ Point<int> position(2 * battle->Res().selectFrame->BorderWidth(), 2 * battle->Res().selectFrame->BorderHeight());
+ battle->GetSpellMenu().Draw(screen, position + offset);
+}
+
}
#include "../../app/State.h"
+#include "../../geometry/Vector.h"
+
namespace battle {
class BattleState;
virtual void UpdateWorld(float deltaT);
virtual void Render(SDL_Surface *);
+private:
+ void RenderFrame(SDL_Surface *, const geometry::Vector<int> &offset);
+ void RenderMenu(SDL_Surface *, const geometry::Vector<int> &offset);
+
private:
app::Application *ctrl;
BattleState *battle;
--- /dev/null
+/*
+ * Menu.h
+ *
+ * Created on: Aug 8, 2012
+ * Author: holy
+ */
+
+#ifndef GRAPHICS_MENU_H_
+#define GRAPHICS_MENU_H_
+
+#include "Font.h"
+#include "../geometry/operators.h"
+#include "../geometry/Point.h"
+#include "../geometry/Vector.h"
+
+#include <vector>
+#include <SDL.h>
+
+namespace graphics {
+
+class Sprite;
+
+template<class T>
+class Menu {
+
+public:
+ Menu(const Font *font, int charsPerEntry, int rows, int rowGap = 0, int cols = 1, int colGap = 0);
+
+public:
+ int Width() const;
+ int Height() const;
+ int ColWidth() const { return font->CharWidth() * charsPerEntry; }
+ int RowHeight() const { return font->CharHeight() + rowGap; }
+
+ T &Selected() { return entries[selected].value; }
+ const T &Selected() const { return entries[selected].value; }
+ const char *SelectedTitle() const { return entries[selected].title; }
+
+ void NextItem();
+ void PreviousItem();
+ void NextRow();
+ void PreviousRow();
+ void SelectIndex(int index);
+
+ void Add(const char *title, const T &value, const Sprite *icon = 0) { entries.push_back(Entry(title, value, icon)); }
+ void Reserve(int n) { entries.reserve(n); }
+
+ void Draw(SDL_Surface *dest, geometry::Point<int> position) const;
+
+private:
+ int GetRow(int index) const { return index / cols; }
+ int GetCol(int index) const { return index % cols; }
+
+private:
+ struct Entry {
+ Entry(const char *title, const T &value, const Sprite *icon = 0)
+ : title(title), icon(icon), value(value) { }
+ const char *title;
+ const Sprite *icon;
+ T value;
+ };
+ const Font *font;
+ std::vector<Entry> entries;
+ int charsPerEntry;
+ int rows;
+ int rowGap;
+ int cols;
+ int colGap;
+ int selected;
+ int topRow;
+
+};
+
+
+template<class T>
+Menu<T>::Menu(const Font *font, int charsPerEntry, int rows, int rowGap, int cols, int colGap)
+: font(font)
+, charsPerEntry(charsPerEntry)
+, rows(rows)
+, rowGap(rowGap)
+, cols(cols)
+, colGap(colGap)
+, selected(0)
+, topRow(0) {
+
+}
+
+
+template<class T>
+int Menu<T>::Width() const {
+ return cols * ColWidth() + (cols - 1) * colGap;
+}
+
+template<class T>
+int Menu<T>::Height() const {
+ return rows * font->CharHeight() + (rows - 1) * rowGap;
+}
+
+
+template<class T>
+void Menu<T>::NextItem() {
+ SelectIndex(selected + 1);
+}
+
+template<class T>
+void Menu<T>::PreviousItem() {
+ SelectIndex(selected - 1);
+}
+
+template<class T>
+void Menu<T>::NextRow() {
+ SelectIndex(selected + cols);
+}
+
+template<class T>
+void Menu<T>::PreviousRow() {
+ SelectIndex(selected - cols);
+}
+
+template<class T>
+void Menu<T>::SelectIndex(int index) {
+ if (index < 0 || entries.size() < index) return;
+ selected = index;
+ if (GetRow(selected) - rows > topRow) {
+ topRow = GetRow(selected) - rows;
+ } else if (GetRow(selected) < topRow) {
+ topRow = GetRow(selected);
+ }
+}
+
+
+template<class T>
+void Menu<T>::Draw(SDL_Surface *dest, geometry::Point<int> position) const {
+ int start(topRow * cols);
+ int slots((topRow + rows) * cols);
+ int items(entries.size() - start);
+ int end(items < slots ? items : slots);
+ for (int i(0), count(end - start); i < count; ++i) {
+ geometry::Vector<int> offset((i % cols) * (ColWidth() + colGap), (i / cols) * RowHeight());
+ font->DrawString(entries[start + i].title, dest, position + offset, charsPerEntry);
+ }
+}
+
+}
+
+#endif /* GRAPHICS_MENU_H_ */
normalFont.MapRange('N', 'Z', 0, 2);
normalFont.MapRange('a', 'm', 0, 3);
normalFont.MapRange('n', 'z', 0, 4);
+ normalFont.MapChar(':', 10, 0);
+ normalFont.MapChar('!', 10, 0);
+ normalFont.MapChar('?', 10, 0);
battleRes.normalFont = &normalFont;
BattleState *battleState(new BattleState(bg, monstersLayout, heroesLayout, &battleRes));