Peoplemon  0.1.0
Peoplemon 3 game source documentation
StatBoxes.cpp
Go to the documentation of this file.
2 
3 #include <Core/Properties.hpp>
4 #include <Core/Resources.hpp>
5 
6 namespace core
7 {
8 namespace battle
9 {
10 namespace view
11 {
12 namespace
13 {
14 constexpr float SlideSpeed = 400.f;
15 constexpr float BarRate = 0.45f; // 45% of total width per second
16 constexpr glm::vec2 BarSize(96.f, 6.f);
17 
18 constexpr glm::vec2 XpBarPos(52.f, 88.f);
19 constexpr glm::vec2 XpBarSize(192.f, 4.f);
20 
21 constexpr glm::vec2 OpBoxPos(0.f, 0.f);
22 constexpr glm::vec2 OpBarPos(100.f, 50.f);
23 
24 constexpr glm::vec2 LpBoxPos(540.f, 357.f);
25 constexpr glm::vec2 LpBarPos(148.f, 54.f);
26 
27 constexpr float NameSize = 18.f;
28 constexpr float LevelSize = 15.f;
29 const sf::Color LevelColor(20.f, 20.f, 140.f);
30 
31 std::string makeHpStr(unsigned int cur, unsigned int max) {
32  std::stringstream ss;
33  ss << cur << "/" << max;
34  return ss.str();
35 }
36 
37 } // namespace
38 
39 StatBoxes::StatBoxes(bl::engine::Engine& engine)
40 : engine(engine)
41 , localPlayer(nullptr)
42 , opponent(nullptr)
43 , pState(State::Hidden)
44 , oState(State::Hidden)
45 , opHpBarTarget(0.f)
46 , lpHpBarTarget(0.f)
47 , lpXpBarTarget(0.f) {}
48 
49 void StatBoxes::init(bl::rc::scene::CodeScene* scene) {
50  constexpr auto join = bl::util::FileUtil::joinPath;
51  const std::string& ImgPath = Properties::ImagePath();
52 
53  opBoxTxtr = engine.renderer().texturePool().getOrLoadTexture(join(ImgPath, "Battle/opBox.png"));
54  opBox.create(engine, opBoxTxtr);
55  opBox.getTransform().setPosition(-opBoxTxtr->size().x, OpBoxPos.y);
56  opBox.addToScene(scene, bl::rc::UpdateSpeed::Static);
57 
58  lpBoxTxtr = engine.renderer().texturePool().getOrLoadTexture(join(ImgPath, "Battle/pBox.png"));
59  lpBox.create(engine, lpBoxTxtr);
60  lpBox.getTransform().setPosition(Properties::WindowWidth() + lpBoxTxtr->size().x, LpBoxPos.y);
61  lpBox.addToScene(scene, bl::rc::UpdateSpeed::Static);
62 
63  lpXpBar.create(engine, {100.f, 100.f});
64  lpXpBar.setFillColor(sf::Color::Blue);
65  lpXpBar.addToScene(scene, bl::rc::UpdateSpeed::Dynamic);
66 
67  opName.create(engine, Properties::MenuFont(), "", NameSize, sf::Color::Black, sf::Text::Bold);
68  opName.addToScene(scene, bl::rc::UpdateSpeed::Static);
69 
70  opLevel.create(engine, Properties::MenuFont(), "", LevelSize, LevelColor, sf::Text::Bold);
71  opLevel.addToScene(scene, bl::rc::UpdateSpeed::Static);
72 
73  lpName.create(engine, Properties::MenuFont(), "", NameSize, sf::Color::Black, sf::Text::Bold);
74  lpName.addToScene(scene, bl::rc::UpdateSpeed::Static);
75 
76  lpLevel.create(engine, Properties::MenuFont(), "", LevelSize, LevelColor, sf::Text::Bold);
77  lpLevel.addToScene(scene, bl::rc::UpdateSpeed::Static);
78 
79  lpHp.create(engine, Properties::MenuFont(), "", 14, sf::Color::Black);
80  lpHp.addToScene(scene, bl::rc::UpdateSpeed::Static);
81 
82  lpHpBar.create(engine, {100.f, 100.f});
83  lpHpBar.addToScene(scene, bl::rc::UpdateSpeed::Dynamic);
84 
85  opHpBar.create(engine, {100.f, 100.f});
86  opHpBar.addToScene(scene, bl::rc::UpdateSpeed::Dynamic);
87 
88  opAil.create(engine, engine.renderer().texturePool().getBlankTexture());
89  opAil.addToScene(scene, bl::rc::UpdateSpeed::Static);
90 
91  lpAil.create(engine, engine.renderer().texturePool().getBlankTexture());
92  lpAil.addToScene(scene, bl::rc::UpdateSpeed::Static);
93 
94  // opponent positions + parenting
95  opHpBar.getTransform().setPosition(OpBarPos);
96  opHpBar.setParent(opBox);
97  opAil.getTransform().setPosition(glm::vec2(10.f, 46.f));
98  opAil.setParent(opBox);
99  opName.getTransform().setPosition(glm::vec2(5.f, 18.f));
100  opName.setParent(opBox);
101  opLevel.getTransform().setPosition(glm::vec2(168.f, 21.f));
102  opLevel.setParent(opBox);
103 
104  // player positions + parenting
105  lpAil.getTransform().setPosition(glm::vec2(33.f, 61.f));
106  lpAil.setParent(lpBox);
107  lpName.getTransform().setPosition(glm::vec2(41.f, 22.f));
108  lpName.setParent(lpBox);
109  lpLevel.getTransform().setPosition(glm::vec2(218.f, 24.f));
110  lpLevel.setParent(lpBox);
111  lpHp.getTransform().setPosition(glm::vec2(131.f, 66.f));
112  lpHp.setParent(lpBox);
113  lpHpBar.getTransform().setPosition(LpBarPos);
114  lpHpBar.setParent(lpBox);
115  lpXpBar.getTransform().setPosition(XpBarPos);
116  lpXpBar.setParent(lpBox);
117 
118  // size bars to 0 to start
119  lpHpBar.scaleToSize({0.f, BarSize.y});
120  opHpBar.scaleToSize({0.f, BarSize.y});
121  lpXpBar.scaleToSize({0.f, XpBarSize.y});
122 }
123 
125  opponent = ppl;
126  opHpBar.scaleToSize({0.f, BarSize.y});
127  if (oState == State::Hidden) { oState = State::Sliding; }
128  sync(false);
129 }
130 
132  localPlayer = ppl;
133  lpHpBar.scaleToSize({0.f, BarSize.y});
134  lpXpBar.scaleToSize({0.f, XpBarSize.y});
135  if (pState == State::Hidden) { pState = State::Sliding; }
136  sync(true);
137 }
138 
139 void StatBoxes::sync(bool fromSwitch) {
140  if (localPlayer) {
141  lpName.getSection().setString(localPlayer->base().name());
142  lpLevel.getSection().setString(std::to_string(localPlayer->base().currentLevel()));
143  lpHp.getSection().setString(
144  makeHpStr(localPlayer->base().currentHp(), localPlayer->currentStats().hp));
145  lpAil.setTexture(ailmentTexture(localPlayer->base().currentAilment()), true);
146  lpHpBarTarget = (static_cast<float>(localPlayer->base().currentHp()) /
147  static_cast<float>(localPlayer->currentStats().hp)) *
148  BarSize.x;
149  lpXpBarTarget = (static_cast<float>(localPlayer->base().currentXP()) /
150  static_cast<float>(localPlayer->base().nextLevelXP())) *
151  XpBarSize.x;
152  if (fromSwitch) { lpXpBar.scaleToSize({lpXpBarTarget, XpBarSize.y}); }
153  }
154  else {
155  BL_LOG_WARN << "sync() called with null player peoplemon";
156  lpHpBarTarget = 0.f;
157  lpXpBarTarget = 0.f;
158  lpName.getSection().setString("");
159  }
160 
161  if (opponent) {
162  opName.getSection().setString(opponent->base().name());
163  opLevel.getSection().setString(std::to_string(opponent->base().currentLevel()));
164  opAil.setTexture(ailmentTexture(opponent->base().currentAilment()), true);
165  opHpBarTarget = (static_cast<float>(opponent->base().currentHp()) /
166  static_cast<float>(opponent->currentStats().hp)) *
167  BarSize.x;
168  }
169  else {
170  BL_LOG_WARN << "sync() called with null opponent peoplemon";
171  opHpBarTarget = 0.f;
172  opName.getSection().setString("");
173  }
174 }
175 
176 void StatBoxes::update(float dt) {
177  const float change = dt * BarRate * BarSize.x;
178 
179  // opponent box slide
180  if (oState == State::Sliding) {
181  const float dx = SlideSpeed * dt;
182  opBox.getTransform().move({dx, 0.f});
183  if (opBox.getTransform().getLocalPosition().x > OpBoxPos.x) {
184  opBox.getTransform().setPosition(OpBoxPos);
185  oState = State::Showing;
186  }
187  }
188  else if (oState == State::Showing) {
189  // opponent bar size
190  if (opHpBar.getGlobalSize().x < opHpBarTarget) {
191  const float nw = std::min(opHpBarTarget, opHpBar.getGlobalSize().x + change);
192  opHpBar.scaleToSize({nw, BarSize.y});
193  }
194  else if (opHpBar.getGlobalSize().x > opHpBarTarget) {
195  const float nw = std::max(opHpBarTarget, opHpBar.getGlobalSize().x - change);
196  opHpBar.scaleToSize({nw, BarSize.y});
197  }
198 
199  // opponent bar color
200  const float opHp = opHpBar.getSize().x / BarSize.x;
201  opHpBar.setFillColor(Properties::HPBarColor(opHp));
202  }
203 
204  // player box slide
205  if (pState == State::Sliding) {
206  const float dx = SlideSpeed * dt;
207  lpBox.getTransform().move({-dx, 0.f});
208  if (lpBox.getTransform().getLocalPosition().x < LpBoxPos.x) {
209  lpBox.getTransform().setPosition(LpBoxPos);
210  pState = State::Showing;
211  }
212  }
213  else if (pState == State::Showing) {
214  // player bar size
215  if (lpHpBar.getGlobalSize().x < lpHpBarTarget) {
216  const float nw = std::min(lpHpBarTarget, lpHpBar.getGlobalSize().x + change);
217  lpHpBar.scaleToSize({nw, BarSize.y});
218  }
219  else if (lpHpBar.getGlobalSize().x > lpHpBarTarget) {
220  const float nw = std::max(lpHpBarTarget, lpHpBar.getGlobalSize().x - change);
221  lpHpBar.scaleToSize({nw, BarSize.y});
222  }
223 
224  // player bar color
225  const float lphp = lpHpBar.getGlobalSize().x / BarSize.x;
226  lpHpBar.setFillColor(Properties::HPBarColor(lphp));
227 
228  // xp bar size
229  const float xpChange = dt * BarRate * XpBarSize.x;
230  if (lpXpBar.getGlobalSize().x < lpXpBarTarget) {
231  const float nw = std::min(lpXpBarTarget, lpXpBar.getGlobalSize().x + xpChange);
232  lpXpBar.scaleToSize({nw, XpBarSize.y});
233  }
234  else if (lpXpBar.getGlobalSize().x > lpXpBarTarget) {
235  // no transition down
236  lpXpBar.scaleToSize({lpXpBarTarget, XpBarSize.y});
237  }
238  }
239 }
240 
241 bool StatBoxes::synced() const {
242  return opHpBar.getGlobalSize().x == opHpBarTarget &&
243  lpHpBar.getGlobalSize().x == lpHpBarTarget && lpXpBar.getGlobalSize().x == lpXpBarTarget;
244 }
245 
246 void StatBoxes::render(bl::rc::scene::CodeScene::RenderContext& ctx) {
247  if (oState != State::Hidden) {
248  opHpBar.draw(ctx);
249  opBox.draw(ctx);
250  opName.draw(ctx);
251  opLevel.draw(ctx);
252  opAil.draw(ctx);
253  }
254 
255  if (pState != State::Hidden) {
256  lpHpBar.draw(ctx);
257  lpXpBar.draw(ctx);
258  lpBox.draw(ctx);
259  lpName.draw(ctx);
260  lpHp.draw(ctx);
261  lpLevel.draw(ctx);
262  lpAil.draw(ctx);
263  }
264 }
265 
266 bl::rc::res::TextureRef StatBoxes::ailmentTexture(pplmn::Ailment ail) {
267  const auto src = Properties::AilmentTexture(ail);
268  return src.empty() ? engine.renderer().texturePool().getBlankTexture() :
269  engine.renderer().texturePool().getOrLoadTexture(src);
270 }
271 
272 } // namespace view
273 } // namespace battle
274 } // namespace core
Ailment
Represents an ailment that a Peoplemon can have.
Definition: Ailment.hpp:16
Core classes and functionality for both the editor and game.
StatBoxes(bl::engine::Engine &engine)
Construct a new Stat Boxes component.
Definition: StatBoxes.cpp:39
void sync(bool fromSwitch=false)
Updates the UI to reflect the current peoplemon state.
Definition: StatBoxes.cpp:139
void init(bl::rc::scene::CodeScene *scene)
Creates entities and adds them to the scene.
Definition: StatBoxes.cpp:49
void update(float dt)
Updates bar sizes if they need to change.
Definition: StatBoxes.cpp:176
void setOpponent(pplmn::BattlePeoplemon *ppl)
Sets the opponent's peoplemon. Syncs right away.
Definition: StatBoxes.cpp:124
void setPlayer(pplmn::BattlePeoplemon *ppl)
Sets the player's peoplemon. Syncs right away.
Definition: StatBoxes.cpp:131
bool synced() const
Returns true if the view is in sync, false if an animation is in progress.
Definition: StatBoxes.cpp:241
void render(bl::rc::scene::CodeScene::RenderContext &ctx)
Renders the boxes.
Definition: StatBoxes.cpp:246
Represents a Peoplemon in battle. Stores some extra state that only exists in battle....
OwnedPeoplemon & base()
Returns the wrapped peoplemon.
const Stats & currentStats() const
Returns the current stats of the peoplemon, including changes.
Ailment & currentAilment()
Access the current ailment of this peoplemon.
unsigned int nextLevelXP() const
Returns the xp required to level up.
std::uint16_t & currentHp()
Access the current HP.
unsigned int currentLevel() const
Returns the current level of this peoplemon.
unsigned int currentXP() const
Returns the current XP of this peoplemon.
const std::string & name() const
Returns the name of this peoplemon, custom or defualt.
static int WindowWidth()
Definition: Properties.cpp:250
static const sf::VulkanFont & MenuFont()
Definition: Properties.cpp:363
static std::string AilmentTexture(pplmn::Ailment ailment)
Definition: Properties.cpp:653
static sf::Color HPBarColor(float percent)
Definition: Properties.cpp:647
static const std::string & ImagePath()
Definition: Properties.cpp:333