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

#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