Profile stats, first-run hints, tiered balance, a wave-driven whip, and more options
- Profile Stats: damage dealt, kills and wins (single player and multiplayer) and the most and least played weapons and trinkets, counted from running totals in the simulation so online rewinds correct them. Protocol 6. - First-run control hints in the sandbox (and Chat in lobbies), each gone for good once used. - The ready countdown and a timed round's last five seconds beep (new countdown sound), and those seconds show big. When time runs out, everyone short of the most health dies. - Weapon balance tuned into tiers: Whip and Grenade Launcher on top, then melee, ranged, and utility (Vacuum, Grapple, Uzi) at the bottom. - The whip's lash is a chain of links a wave rolls down: windup, loop, crack, then a floppy recoil. - Muzzles come from Muzzle nulls in weapons.anm2 (read in at build time), for shots and the flash, which now follows the weapon. - Settings: Quit, Scale (1x-4x or Free), FPS meter and limit beside Vsync, Mute on Unfocus, Damage Numbers, Rumble, Stick Deadzone, and an Online section (Host, Chat, Ping) shared with the Multiplayer page. - The menu header lays out tabs and buttons by their names. About is sandbox-only. The score no longer shifts with the menu's tab. - Smaller meters, 90 tips (all ending in !), and a shorter lobby welcome.
This commit is contained in:
1 parent
e9d8cac926
commit
b96defa1e6
32 files changed
+1368
-396
No files matched your search
+244
-55
@@ -54,6 +54,8 @@ constexpr float CHARGE_BAR_HEIGHT = 8;
|
||||
constexpr float CHARGE_BAR_WIDTH = 20;
|
||||
constexpr float DPS_SCALE = 2;
|
||||
constexpr float FIGHT_BANNER_TIME = 0.6f;
|
||||
// How many of the countdown's last seconds beep (and, in a timed round, show big).
|
||||
constexpr int COUNTDOWN_BEEPS = 5;
|
||||
constexpr float HEALTH_BAR_HEIGHT = 7;
|
||||
constexpr float HEALTH_BAR_WIDTH = 28;
|
||||
constexpr float ROUND_SCALE = 3;
|
||||
@@ -114,6 +116,14 @@ constexpr float FIELD_INSET = 4;
|
||||
constexpr float SLIDER_INSET = 3;
|
||||
constexpr float TEXT_INSET = (WIDGET_HEIGHT - LINE_HEIGHT) / 2;
|
||||
constexpr float HINT_FADE = 0.5f;
|
||||
constexpr const char* HINT_SPACING = " ";
|
||||
// How wide a row of first-run hints may run, clear of the hotbars in the corners.
|
||||
constexpr float HINT_ROW_WIDTH = 360;
|
||||
// Each first-run hint's control (Move takes Move Right too) and what it does.
|
||||
constexpr Control HINT_CONTROLS[HINT_COUNT] = {CONTROL_LEFT, CONTROL_JUMP, CONTROL_DOWN, CONTROL_ATTACK,
|
||||
CONTROL_CHARGE, CONTROL_MENU, CONTROL_READY, CONTROL_CHAT};
|
||||
constexpr const char* HINT_LABELS[HINT_COUNT] = {"Move", "Jump", "Crouch / Drop", "Attack",
|
||||
"Charged Attack", "Menu", "Reset", "Chat"};
|
||||
constexpr float TOOLTIP_OFFSET = 12;
|
||||
constexpr float TOOLTIP_PADDING = 6;
|
||||
constexpr float TABLE_GAP = 8;
|
||||
@@ -132,44 +142,107 @@ constexpr Vec2 LABEL_OFFSETS[ICON_TINY] = {{4, 2}, {3, 2}};
|
||||
constexpr Vec2 ICON_LABEL_OFFSET = {LABEL_OFFSETS[ICON_FULL].x - (SLOT_SIZE - ICON_SIZE) / 2,
|
||||
LABEL_OFFSETS[ICON_FULL].y - (SLOT_SIZE - ICON_SIZE) / 2};
|
||||
|
||||
// Tips shown under the ready button, one at random: movement and knockback, cooldowns and Charge, projectiles, each
|
||||
// Weapon and Trinket in turn, then the menus.
|
||||
constexpr const char* TIPS[] = {
|
||||
"Big hits launch fighters, and slamming into walls while launched hurts.",
|
||||
"Swing the Hammer into a wall to rebound off it, even mid-launch.",
|
||||
"Ranged shots lose damage the farther they fly. Get close.",
|
||||
"Explosions hit hardest at their centre.",
|
||||
"Your own explosions push you but never hurt you. Rocket jump!",
|
||||
"Arrows stuck in walls are solid to you. Stand on them.",
|
||||
"Charged boomerangs are platforms only you can ride.",
|
||||
"Standing in your own flames brakes you, even mid-launch.",
|
||||
"Shots carry your momentum. Fire while charging forward for extra damage.",
|
||||
"Every hit is stronger the faster you're moving.",
|
||||
"Let go of a charge early for a normal attack that hits harder.",
|
||||
"Mines need a moment to arm before they'll go off.",
|
||||
"The Whip's charged blast only lands at the very tip.",
|
||||
"A charged grapple hit drags you straight to your target.",
|
||||
"Platforms block shots. Use them as cover.",
|
||||
"With Iron Weights, hold Down to slam the ground. Faster falls hit harder.",
|
||||
"Ricochet shots add damage with every bounce.",
|
||||
"Your charge carries over when you swap weapons.",
|
||||
"Charge recalls your boomerangs once they're all out.",
|
||||
"Attack or Charge reels a thrown flail ball back in.",
|
||||
"Uzi and Blaster hits barely push. Melee and explosions send fighters flying.",
|
||||
"Rapid small hits can't juggle you. Knockback tops up, it doesn't stack.",
|
||||
"Crack the Whip against a wall to be pulled toward it.",
|
||||
"Recoil is movement. Fire away from where you want to go.",
|
||||
"Splitter copies fan wider with each level.",
|
||||
"Dual Wield fires your previous weapon from your off hand too.",
|
||||
"Tesla Coil chains lightning between your weapons out in the world.",
|
||||
"Each round levels up every item, and health rises with it.",
|
||||
"With the Feather, hold Up in the air to float.",
|
||||
"The Lance's charged poke lunges you forward.",
|
||||
"In a race, dithered pits send you back to the last solid ground you stood on.",
|
||||
"Race blocks grow back a few seconds after they break. Don't dawdle.",
|
||||
"Hits in a race don't hurt, but they still knock. Push rivals into pits.",
|
||||
"Shotgun recoil can double as a jump.",
|
||||
"Getting knocked into walls hurts! Do your best to reduce your speed when attacked!",
|
||||
"Don't get cornered! Knockback damage can add up fast!",
|
||||
"Crouch to reduce knockback!",
|
||||
"Crawl around by crouching and moving!",
|
||||
"Roll around on sloped surfaces with Down!",
|
||||
"Platforms block shots. Use them as cover!",
|
||||
|
||||
"Weapons don't share cooldowns! Switch Weapons to maximize damage!",
|
||||
"When a Weapon enters cooldown, it will fade and return to normal when it's done!",
|
||||
"Your cursor's color and vibration can show you your Weapon's cooldown or Charge!",
|
||||
"Let go of a Charge early for a Basic Attack that hits harder!",
|
||||
"Your Charge carries over when you swap Weapons!",
|
||||
"Higher damaging attacks will glow and vibrate!",
|
||||
"Going faster makes you glow and vibrate, showing that your attacks deal more damage!",
|
||||
|
||||
"Almost every attack counts as a projectile! See how you can change their traits with Trinkets!",
|
||||
"Projectiles inherit your velocity. Go fast for big damage!",
|
||||
"Projectiles lose damage the longer they're out. Get close!",
|
||||
"Projectiles will fade with time; this fade shows their damage potential!",
|
||||
"Increasing a projectile's lifetime or speed can both increase its range!",
|
||||
"Explosions hit hardest at their center!",
|
||||
"Your explosions don't hurt, and only push you. Try rocket jumping!",
|
||||
"Recoil is movement. Fire away from where you want to go!",
|
||||
|
||||
"Mix and match Weapons and Trinkets for nigh-infinite amounts of combos!",
|
||||
"The Fist's Charged Attack doesn't always send you straight up! Change your aim!",
|
||||
"Slam a Hammer into surfaces to fly far!",
|
||||
"The Lance's Charged Attack lunges you forward!",
|
||||
"Crack the Whip against a wall to be pulled toward it!",
|
||||
"The Whip's Charged Attack only blasts at the very tip, but does big damage!",
|
||||
"Charge a Flail to throw its ball, and Charge again to reel it back!",
|
||||
"You can have the Flail's ball extended and another Weapon equipped for a dangerous combo!",
|
||||
"Charged Boomerangs are platforms only you can ride!",
|
||||
"Charge recalls your Boomerangs!",
|
||||
"A Grapple's Charged Attack yanks you to your target!",
|
||||
"Swing around on or release a latched Grapple for big speed!",
|
||||
"You can have a Grapple latched and another Weapon equipped for an acrobatic fight!",
|
||||
"A Bow's arrows stuck in walls are semi-solid platforms!",
|
||||
"The Bow's arrows fly faster and further with Charge!",
|
||||
"Fire a wide volley with the Uzi's Charged Attack!",
|
||||
"Use a Shotgun's recoil for great movement!",
|
||||
"The Bolter's projectiles can cling onto surfaces, perfect for area denial!",
|
||||
"Cook a Grenade Launcher's grenade via Charging to explode it sooner!",
|
||||
"Fully Charging a Grenade Launcher will cause an explosion in your face!",
|
||||
"Hit the Grenade Launcher's projectile and explosion at the same time for big damage! Double Donk!",
|
||||
"Mines need a moment to arm before they'll go off!",
|
||||
"The Flamethrower's Charged Attack detonates mid-air! Space an explosion!",
|
||||
"The Vacuum's Charged Attack deals big knockback! Send foes flying!",
|
||||
"The Vacuum's Charged Attack turns enemy shots into your own!",
|
||||
"Hold your own projectiles in the Vacuum's suction to keep them fresh!",
|
||||
"The Vacuum's suction and Charged Attack can move projectiles around. Manipulate the battlefield!",
|
||||
"Use the Grimoire's wisps as a close-range attack or to pepper from afar!",
|
||||
"Use the Grimoire's teleporting Charged Attack to escape danger!",
|
||||
|
||||
"Diazepam reduces Weapon spread, perfect for concentrated attacks!",
|
||||
"Splitter copies fan wider with each level!",
|
||||
"The off-hand Weapon from Dual Wield is the one you last switched from!",
|
||||
"Ricochet makes projectiles deal more damage the more they've bounced!",
|
||||
"Ricochet bounces reset a projectile's lifetime!",
|
||||
"Tesla Coil arcs electricity between your projectiles. Make traps or wide danger zones!",
|
||||
"The kickback the Recoil Coil gives is perfect for movement!",
|
||||
"Stay in place with a Shock Absorber!",
|
||||
"Embiggener makes you a bigger target, but gives a solid damage buff!",
|
||||
"Make yourself a living hazard with a Pebble Helmet!",
|
||||
"With a Speedometer, moving fast and attacking deals bigger damage!",
|
||||
"A pair of Wings will make you dash to where you're aiming when you jump mid-air!",
|
||||
"With the Feather, hold Up in the air to float!",
|
||||
"With Iron Weights, faster falls produce bigger blasts!",
|
||||
"Cling, slide, and kick off walls with a Climb Claw!",
|
||||
|
||||
"Create a Lobby and share its link or code with friends for multiplayer fun!",
|
||||
"When in a Lobby, queue up a game in the menu!",
|
||||
"Queuing takes place in the Sandbox! Holler fighters over to your queued area and Ready up!",
|
||||
"Change a game's rules underneath the Rules option!",
|
||||
"If a game has a time limit, the winner will be decided based on who has the most health!",
|
||||
"Is your name \"Fighter\"? Change it in Profile!",
|
||||
"Change your fighter and HUD color in Profile!",
|
||||
"Feeling naked and unsexy? Wear some Fashion within your Profile!",
|
||||
"Set and load custom gear Loadouts in your Profile!",
|
||||
"Save a gear Loadout and use Shift + a number to equip it!",
|
||||
"Turn on DPS in Settings to see the damage you deal each second!",
|
||||
"Turn on Speed in Settings to see how fast you're going!",
|
||||
"Turn on FPS in Settings to see how smoothly the game runs!",
|
||||
"Is previewing your aim too intrusive? Toggle Aim Preview off in Settings!",
|
||||
"Want to see how things actually collide? Toggle Display Collision in Settings!",
|
||||
"Game too loud? Turn down the Volume or Mute it in Settings!",
|
||||
"Don't like the Controls? Tweak them to your liking in Settings!",
|
||||
"Want to experiment with more Weapon or Trinket slots in the Sandbox? Change them in Settings!",
|
||||
"Want to fight in the Sandbox with others? Check PvP in Settings or use the /pvp command!",
|
||||
"The Dummy in the Sandbox doesn't feel pain! Beat it as much as you'd like, it enjoys it!",
|
||||
"Throw tomatoes to mock a game's winner in between rounds by clicking anywhere on screen!",
|
||||
"Sling slurs and trashtalk all you wish with a Chat message!",
|
||||
"A number of useful / commands are present in Chat! Type /help to see!",
|
||||
"Want to see the sexy person who made this game? Check About in the menu!",
|
||||
};
|
||||
|
||||
static CountdownInfo countdown_info_get(Game& game);
|
||||
static float rival_ping_get(Game& game, int fighter);
|
||||
|
||||
// How opaque a HUD element (other than a hotbar slot) is, fading as the mouse comes over it.
|
||||
static float hover_alpha_get(float hover)
|
||||
@@ -287,7 +360,7 @@ void Ui::bars_draw(Game& game)
|
||||
const char* name = name_get(game, i);
|
||||
Vec2 size = game.text.size_get(name);
|
||||
bottom -= size.y;
|
||||
float ping = game.session.isActive ? game.session.ping_get(game, match.owners[i]) : PING_NONE;
|
||||
float ping = rival_ping_get(game, i);
|
||||
float width = size.x + (ping == PING_NONE ? 0 : NAME_PING_GAP + ping_width_get(game, ping));
|
||||
float left = std::round(centerX - width / 2);
|
||||
game.text.draw(renderer, name, {.color = color, .position = {left, bottom}});
|
||||
@@ -314,7 +387,7 @@ void Ui::bar_draw(Renderer& renderer, Rect bar, float fill, Color color, float s
|
||||
color);
|
||||
}
|
||||
|
||||
// In practice, a hint to open the menu (with its key), fading once it first opens. In a match, the round wins and
|
||||
// In practice, the first-run hints (see hints_draw). In a match, the round wins and
|
||||
// clock along the top, and a banner for the countdown (with who's ready, a Ready button and a tip), the start of the
|
||||
// fight, the end of a round and the end of the match.
|
||||
void Ui::match_draw(Game& game)
|
||||
@@ -325,12 +398,7 @@ void Ui::match_draw(Game& game)
|
||||
Input& input = game.input;
|
||||
if (match.state == MATCH_PRACTICE)
|
||||
{
|
||||
char key[TOOLTIP_LENGTH];
|
||||
char reset[TOOLTIP_LENGTH];
|
||||
input.control_name_get(CONTROL_MENU, key, sizeof(key));
|
||||
input.control_name_get(CONTROL_READY, reset, sizeof(reset));
|
||||
SDL_snprintf(text, sizeof(text), "%s: Menu %s: Reset", key, reset);
|
||||
text_center_draw(game, text, CANVAS_HEIGHT - HOTBAR_MARGIN - LINE_HEIGHT, 1, hintAlpha);
|
||||
hints_draw(game);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -340,8 +408,8 @@ void Ui::match_draw(Game& game)
|
||||
else
|
||||
{
|
||||
// The score: each fighter's wins in its own colour, the dashes between them white. It's centred along the top,
|
||||
// unless a long weapon hotbar reaches it, when it moves right to clear the hotbar (the clock under it moves
|
||||
// with it).
|
||||
// unless a long weapon hotbar reaches it in the HUD, when it moves right to clear the hotbar (the clock under
|
||||
// it moves with it). It stays put while the menu moves the hotbar.
|
||||
Renderer& renderer = game.renderer;
|
||||
int length = 0;
|
||||
for (int i = 0; i < game.sim.fighterCount; i++)
|
||||
@@ -349,7 +417,7 @@ void Ui::match_draw(Game& game)
|
||||
Vec2 scale = {SCORE_SCALE, SCORE_SCALE};
|
||||
float scoreWidth = game.text.size_get(text, FONT_SMALL, SCORE_SCALE).x;
|
||||
int weapons = game.local_get().weaponSlots;
|
||||
Rect last = game.menu.slot_rect(ITEM_WEAPON, weapons - 1, weapons);
|
||||
Rect last = game.menu.slot_hud_rect(ITEM_WEAPON, weapons - 1, weapons);
|
||||
float hotbarRight = last.x + last.w;
|
||||
float x = std::round(std::max((CANVAS_WIDTH - scoreWidth) / 2, hotbarRight + SCORE_HOTBAR_GAP));
|
||||
float center = x + scoreWidth / 2;
|
||||
@@ -379,6 +447,7 @@ void Ui::match_draw(Game& game)
|
||||
HOTBAR_MARGIN + game.text.line_height_get(FONT_SMALL, SCORE_SCALE)}});
|
||||
}
|
||||
|
||||
countdown_beep(game);
|
||||
switch (match.state)
|
||||
{
|
||||
case MATCH_COUNTDOWN:
|
||||
@@ -439,6 +508,12 @@ void Ui::match_draw(Game& game)
|
||||
}
|
||||
if (match.timer > -FIGHT_BANNER_TIME)
|
||||
text_center_draw(game, isRace ? "Go!" : "Fight!", BANNER_Y, BANNER_SCALE);
|
||||
// A timed round's last seconds count down big.
|
||||
if (match.time_limit_get() > 0 && countdownBeeped > 0)
|
||||
{
|
||||
SDL_snprintf(text, sizeof(text), "%d", countdownBeeped);
|
||||
text_center_draw(game, text, BANNER_Y, BANNER_SCALE);
|
||||
}
|
||||
break;
|
||||
case MATCH_ROUND_OVER:
|
||||
if (match.winner >= 0)
|
||||
@@ -828,6 +903,108 @@ static CountdownInfo countdown_info_get(Game& game)
|
||||
return info;
|
||||
}
|
||||
|
||||
// Marks a first-run hint learned once this screen's fighter has done what it says (a full charge for the charged
|
||||
// attack), keeping it in the settings across launches, and fades learned ones out.
|
||||
void Ui::hints_update(Game& game)
|
||||
{
|
||||
Fighter& local = game.local_get();
|
||||
int& learned = game.settings.hintsLearned;
|
||||
bool isDone[HINT_COUNT] = {
|
||||
local.is_down(CONTROL_LEFT) || local.is_down(CONTROL_RIGHT),
|
||||
local.is_down(CONTROL_JUMP),
|
||||
local.is_down(CONTROL_DOWN),
|
||||
local.is_down(CONTROL_ATTACK),
|
||||
local.charge >= 1,
|
||||
game.menu.isOpen,
|
||||
local.is_down(CONTROL_READY),
|
||||
game.chat.isOpen,
|
||||
};
|
||||
for (int i = 0; i < HINT_COUNT; i++)
|
||||
{
|
||||
int bit = 1 << i;
|
||||
if (isDone[i] && !(learned & bit) && !game.session.is_watching(game))
|
||||
{
|
||||
learned |= bit;
|
||||
game.settings.changed();
|
||||
}
|
||||
hintAlphas[i] = learned & bit ? std::max(0.0f, hintAlphas[i] - TICK / HINT_FADE) : 1;
|
||||
}
|
||||
}
|
||||
|
||||
// The first-run hints still showing, each with its key, centred in rows along the bottom of the sandbox, a row going up
|
||||
// when they'd run too wide for one.
|
||||
void Ui::hints_draw(Game& game)
|
||||
{
|
||||
Input& input = game.input;
|
||||
char texts[HINT_COUNT][TOOLTIP_LENGTH];
|
||||
float widths[HINT_COUNT];
|
||||
int shown[HINT_COUNT];
|
||||
int count = 0;
|
||||
for (int i = 0; i < HINT_COUNT; i++)
|
||||
{
|
||||
if (hintAlphas[i] <= 0 || (i == HINT_CHAT && !game.session.isActive))
|
||||
continue;
|
||||
char key[TOOLTIP_LENGTH];
|
||||
char other[TOOLTIP_LENGTH];
|
||||
input.control_name_get(HINT_CONTROLS[i], key, sizeof(key));
|
||||
input.control_name_get(CONTROL_RIGHT, other, sizeof(other));
|
||||
if (i == HINT_MOVE)
|
||||
SDL_snprintf(texts[count], sizeof(texts[count]), "%s/%s: %s", key, other, HINT_LABELS[i]);
|
||||
else
|
||||
SDL_snprintf(texts[count], sizeof(texts[count]), i == HINT_CHARGE ? "Hold %s: %s" : "%s: %s", key,
|
||||
HINT_LABELS[i]);
|
||||
widths[count] = game.text.size_get(texts[count]).x;
|
||||
shown[count++] = i;
|
||||
}
|
||||
|
||||
// Rows fill greedily, then stack up from the bottom.
|
||||
float gap = game.text.size_get(HINT_SPACING).x;
|
||||
float limit = HINT_ROW_WIDTH;
|
||||
int rowStarts[HINT_COUNT + 1];
|
||||
int rows = 0;
|
||||
float width = limit;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (width + gap + widths[i] > limit)
|
||||
{
|
||||
rowStarts[rows++] = i;
|
||||
width = widths[i];
|
||||
continue;
|
||||
}
|
||||
width += gap + widths[i];
|
||||
}
|
||||
rowStarts[rows] = count;
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
float total = -gap;
|
||||
for (int i = rowStarts[row]; i < rowStarts[row + 1]; i++)
|
||||
total += widths[i] + gap;
|
||||
float x = std::round((CANVAS_WIDTH - total) / 2);
|
||||
float y = CANVAS_HEIGHT - HOTBAR_MARGIN - LINE_HEIGHT * (rows - row);
|
||||
for (int i = rowStarts[row]; i < rowStarts[row + 1]; i++)
|
||||
{
|
||||
game.text.draw(game.renderer, texts[i],
|
||||
{.color = color_fade(tint, hintAlphas[shown[i]]), .position = {x, y}});
|
||||
x += widths[i] + gap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The last COUNTDOWN_BEEPS seconds of the ready countdown, or of a timed round, beep as each number ticks over.
|
||||
void Ui::countdown_beep(Game& game)
|
||||
{
|
||||
Match& match = game.sim.match;
|
||||
float left = 0;
|
||||
if (match.state == MATCH_COUNTDOWN)
|
||||
left = match.timer;
|
||||
if (match.state == MATCH_FIGHT && match.time_limit_get() > 0)
|
||||
left = match.time_limit_get() - match.clock;
|
||||
int second = left > 0 && left <= COUNTDOWN_BEEPS ? (int)std::ceil(left) : 0;
|
||||
if (second > 0 && second != countdownBeeped)
|
||||
game.audio.play(SOUND_COUNTDOWN);
|
||||
countdownBeeped = second;
|
||||
}
|
||||
|
||||
// The countdown while the menu covers the middle (as when choosing items), drawn over the menu's dimming: the round and
|
||||
// seconds left in the margin left of the menu, who's ready in the margin right of it (with the key to ready up until
|
||||
// this screen has), and the tip under the hotbars, below the gamepad hints if they're showing. The round's name drops
|
||||
@@ -893,8 +1070,8 @@ void Ui::text_center_draw(Game& game, const char* text, float y, float scale, Co
|
||||
{.color = color, .position = {std::round((CANVAS_WIDTH - width) / 2), std::round(y)}, .scale = {scale, scale}});
|
||||
}
|
||||
|
||||
// Top right: during a match, the local fighter's health as a number beside a bar, then damage per second and the
|
||||
// local fighter's speed in units per second.
|
||||
// Top right: during a match, the local fighter's health as a number beside a bar, then, smaller, frames drawn per
|
||||
// second (counted over each second), damage per second and the local fighter's speed in units per second.
|
||||
void Ui::status_draw(Game& game)
|
||||
{
|
||||
char text[TOOLTIP_LENGTH];
|
||||
@@ -918,13 +1095,26 @@ void Ui::status_draw(Game& game)
|
||||
y += rowHeight;
|
||||
}
|
||||
|
||||
// The DPS and speed meters each show only if they're on in the settings.
|
||||
// The meters each show only if they're on in the settings.
|
||||
auto meter_draw = [&](const char* label) {
|
||||
float x = std::round(right - game.text.size_get(label, FONT_SMALL, DPS_SCALE).x);
|
||||
float x = std::round(right - game.text.size_get(label).x);
|
||||
left = std::min(left, x);
|
||||
game.text.draw(game.renderer, label, {.color = tint, .position = {x, y}, .scale = {DPS_SCALE, DPS_SCALE}});
|
||||
y += rowHeight;
|
||||
game.text.draw(game.renderer, label, {.color = tint, .position = {x, y}});
|
||||
y += game.text.line_height_get();
|
||||
};
|
||||
Uint64 now = SDL_GetTicks();
|
||||
fpsFrames++;
|
||||
if (now - fpsSince >= SDL_MS_PER_SECOND)
|
||||
{
|
||||
fps = fpsFrames * (float)SDL_MS_PER_SECOND / (now - fpsSince);
|
||||
fpsSince = now;
|
||||
fpsFrames = 0;
|
||||
}
|
||||
if (game.settings.isFpsShown)
|
||||
{
|
||||
SDL_snprintf(text, sizeof(text), "%d FPS", (int)std::round(fps));
|
||||
meter_draw(text);
|
||||
}
|
||||
if (game.settings.isDpsShown)
|
||||
{
|
||||
SDL_snprintf(text, sizeof(text), "%.1f DPS", game.effects.dps_get());
|
||||
@@ -2055,9 +2245,7 @@ static void bars_arrange(CooldownBar* bars)
|
||||
// Keeps the HUD's timers and the cooldown bars up to date.
|
||||
void Ui::update(Game& game)
|
||||
{
|
||||
isMenuSeen |= game.menu.isOpen;
|
||||
if (isMenuSeen)
|
||||
hintAlpha = std::max(0.0f, hintAlpha - TICK / HINT_FADE);
|
||||
hints_update(game);
|
||||
spectate_update(game);
|
||||
|
||||
// The HUD's elements change while the mouse is over them, and change back after.
|
||||
@@ -2364,7 +2552,8 @@ void Ui::spectate_draw(Game& game)
|
||||
// A fighter's connection for its window, online (PING_NONE otherwise).
|
||||
static float rival_ping_get(Game& game, int fighter)
|
||||
{
|
||||
return game.session.isActive ? game.session.ping_get(game, game.sim.match.owners[fighter]) : PING_NONE;
|
||||
bool isShown = game.session.isActive && game.settings.isPingShown;
|
||||
return isShown ? game.session.ping_get(game, game.sim.match.owners[fighter]) : PING_NONE;
|
||||
}
|
||||
|
||||
// Lays out the other fighters' windows in the HUD's right column, from the bottom up to the readouts above, in no more
|
||||
|
||||
Reference in new issue
Block a user