You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
2.8 KiB
117 lines
2.8 KiB
#include "floatingnumbers.h" |
|
|
|
#include <cstdint> |
|
#include <ctime> |
|
#include <deque> |
|
#include <fmt/format.h> |
|
#include <string> |
|
|
|
#ifdef USE_SDL3 |
|
#include <SDL3/SDL_timer.h> |
|
#else |
|
#include <SDL.h> |
|
#endif |
|
|
|
#include "engine/render/text_render.hpp" |
|
#include "options.h" |
|
#include "utils/str_cat.hpp" |
|
|
|
namespace devilution { |
|
|
|
namespace { |
|
|
|
struct FloatingNumber { |
|
Point startPos; |
|
Displacement startOffset; |
|
Displacement endOffset; |
|
std::string text; |
|
uint32_t time; |
|
uint32_t lastMerge; |
|
UiFlags style; |
|
int id; |
|
bool reverseDirection; |
|
}; |
|
|
|
std::deque<FloatingNumber> FloatingQueue; |
|
|
|
void ClearExpiredNumbers() |
|
{ |
|
while (!FloatingQueue.empty()) { |
|
const FloatingNumber &num = FloatingQueue.front(); |
|
if (num.time > SDL_GetTicks()) |
|
break; |
|
|
|
FloatingQueue.pop_front(); |
|
} |
|
} |
|
|
|
GameFontTables GetGameFontSize(UiFlags flags) |
|
{ |
|
if (HasAnyOf(flags, UiFlags::FontSize30)) |
|
return GameFont30; |
|
if (HasAnyOf(flags, UiFlags::FontSize24)) |
|
return GameFont24; |
|
return GameFont12; |
|
} |
|
|
|
} // namespace |
|
|
|
void AddFloatingNumber(Point pos, Displacement offset, std::string text, UiFlags style, int id, bool reverseDirection) |
|
{ |
|
Displacement endOffset; |
|
if (!reverseDirection) |
|
endOffset = { 0, -140 }; |
|
else |
|
endOffset = { 0, 140 }; |
|
|
|
for (auto &num : FloatingQueue) { |
|
if (id != 0 && num.id == id && (SDL_GetTicks() - static_cast<int>(num.lastMerge)) <= 100) { |
|
num.text = text; |
|
num.lastMerge = SDL_GetTicks(); |
|
num.style = style; |
|
num.startPos = pos; |
|
return; |
|
} |
|
} |
|
FloatingNumber num { |
|
pos, offset, endOffset, text, |
|
static_cast<uint32_t>(SDL_GetTicks() + 2500), |
|
static_cast<uint32_t>(SDL_GetTicks()), |
|
style | UiFlags::Outlined, id, reverseDirection |
|
}; |
|
FloatingQueue.push_back(num); |
|
} |
|
|
|
void DrawFloatingNumbers(const Surface &out, Point viewPosition, Displacement offset) |
|
{ |
|
for (auto &floatingNum : FloatingQueue) { |
|
Displacement worldOffset = viewPosition - floatingNum.startPos; |
|
worldOffset = worldOffset.worldToScreen() + offset + Displacement { TILE_WIDTH / 2, -TILE_HEIGHT / 2 } + floatingNum.startOffset; |
|
|
|
if (*GetOptions().Graphics.zoom) { |
|
worldOffset *= 2; |
|
} |
|
|
|
Point screenPosition { worldOffset.deltaX, worldOffset.deltaY }; |
|
|
|
const int lineWidth = GetLineWidth(floatingNum.text, GetGameFontSize(floatingNum.style)); |
|
screenPosition.x -= lineWidth / 2; |
|
const uint32_t timeLeft = floatingNum.time - SDL_GetTicks(); |
|
const float mul = 1 - (timeLeft / 2500.0f); |
|
screenPosition += floatingNum.endOffset * mul; |
|
|
|
DrawString(out, floatingNum.text, Rectangle { screenPosition, { lineWidth, 0 } }, |
|
{ .flags = floatingNum.style }); |
|
} |
|
|
|
ClearExpiredNumbers(); |
|
} |
|
|
|
void ClearFloatingNumbers() |
|
{ |
|
srand(static_cast<unsigned int>(time(nullptr))); |
|
|
|
FloatingQueue.clear(); |
|
} |
|
|
|
} // namespace devilution
|
|
|