1
0
Fork 0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-12-23 01:59:43 +01:00

Simplify time formatting functions

Here's my notes on all the existing functions and what kind of time
formats they output:

- Game::giventimestring(int hrs, int min, int sec)
	H:MM:SS
	MM:SS

- Game::timestring()
// uses game.hours/minutes/seconds
	H:MM:SS
	MM:SS

- Game::partimestring()
// uses game.timetrialpar (seconds)
	MM:SS

- Game::resulttimestring()
// uses game.timetrialresulttime (sec) + timetrialresultframes (1/30s)
	MM:SS.CC

- Game::timetstring(int t)
// t = seconds
	MM:SS

- Game::timestringcenti(char* buffer, const size_t buffer_size)
// uses game.hours/minutes/seconds/frames
	H:MM:SS.CC
	MM:SS.CC

- UtilityClass::timestring(int t)
// t = frames, 30 frames = 1 second
	S:CC
	M:SS:CC

This is kind of a mess, and there's a lot of functions that do the same
thing except using different variables. For localization, I also want
translators to be able to localize all these time formats - many
languages use the decimal comma instead of the decimal point (12:34,56)
maybe some languages really prefer something like 1時02分11秒44瞬...
Which I don't know to be correct, but it's good to be prepared for it
and not restrict translators arbitrarily to only changing ":" and "."
when we can start making the system better in the first place.

I added a new function, UtilityClass::format_time. This is the place
where all time formats come together, given the number of seconds and
optionally frames. I have simplified the above-mentioned functions
somewhat, but I haven't given them a complete refactor or renaming -
I mainly made sure that they all use the same backend so I can make the
formats consistent and properly localizable.

(And before we start shoving more temporary char buffers everywhere
just to get rid of the std::string's, maybe we need to think of a
globally used working buffer of size SCREEN_WIDTH_CHARS+1, as a
register of sorts, for when any line of text needs to be made or
processed, then printed, and then goes unused. Maybe help.textrow,
or something like that.)

As for this commit, the available time formats are now more consistent
and changed a little in some places. Leading zeroes for the first unit
are now no longer included, time trial results and the Super Gravitron
can now display hours when they went to 60 minutes before, and we now
always use .CC instead of :CC. These are the formats:
- H:MM:SS
- H:MM:SS.CC
- M:SS
- M:SS.CC
- S.CC  (only used when always_minutes=false, for the Gravitrons)

Here's what changes to the current functions:
- Game::partimestring() is removed - it was used in two places, and
  could be replaced by game.timetstring(game.timetrialpar)
- Game::giventimestring(h,m,s) and Game::timestring() are now wrappers
  for the other functions
- The four remaining functions (Game::resulttimestring(),
  Game::timetstring(t), Game::timestringcenti(buffer, buffer_size)
  and UtilityClass::timestring(t)) are now wrappers for the "central
  function", UtilityClass::format_time.
- UtilityClass::twodigits(int t) is now unused so it's also removed.
- I also added int UtilityClass::hms_to_seconds(int h, int m, int s)
This commit is contained in:
Dav999-v 2021-12-25 17:13:46 +01:00 committed by Misa Elizabeth Kai
parent dd24343141
commit 3e36bfd56f
5 changed files with 56 additions and 93 deletions

View file

@ -1412,7 +1412,7 @@ void Game::updatestate(void)
obj.removetrigger(82); obj.removetrigger(82);
hascontrol = false; hascontrol = false;
timetrialresulttime = seconds + (minutes * 60) + (hours * 60 * 60); timetrialresulttime = help.hms_to_seconds(hours, minutes, seconds);
timetrialresultframes = frames; timetrialresultframes = frames;
timetrialresulttrinkets = trinkets(); timetrialresulttrinkets = trinkets();
timetrialresultshinytarget = timetrialshinytarget; timetrialresultshinytarget = timetrialshinytarget;
@ -2605,13 +2605,16 @@ void Game::updatestate(void)
graphics.textboxcenterx(); graphics.textboxcenterx();
break; break;
case 3502: case 3502:
{
state++; state++;
statedelay = 45+15; statedelay = 45+15;
graphics.createtextboxflipme(" All Crew Members Rescued! ", -1, 64, 0, 0, 0); graphics.createtextboxflipme(" All Crew Members Rescued! ", -1, 64, 0, 0, 0);
savetime = timestring(); char buffer[SCREEN_WIDTH_CHARS + 1];
savetime += "." + help.twodigits(frames*100 / 30); timestringcenti(buffer, sizeof(buffer));
savetime = buffer;
break; break;
}
case 3503: case 3503:
{ {
state++; state++;
@ -5748,86 +5751,33 @@ void Game::gameclock(void)
std::string Game::giventimestring( int hrs, int min, int sec ) std::string Game::giventimestring( int hrs, int min, int sec )
{ {
std::string tempstring = ""; return timetstring(help.hms_to_seconds(hrs, min, sec));
if (hrs > 0)
{
tempstring += help.String(hrs) + ":";
}
tempstring += help.twodigits(min) + ":" + help.twodigits(sec);
return tempstring;
} }
std::string Game::timestring(void) std::string Game::timestring(void)
{ {
std::string tempstring = ""; return giventimestring(hours, minutes, seconds);
if (hours > 0)
{
tempstring += help.String(hours) + ":";
}
tempstring += help.twodigits(minutes) + ":" + help.twodigits(seconds);
return tempstring;
}
std::string Game::partimestring(void)
{
//given par time in seconds:
std::string tempstring = "";
if (timetrialpar >= 60)
{
tempstring = help.twodigits(timetrialpar / 60) + ":" + help.twodigits(timetrialpar % 60);
}
else
{
tempstring = "00:" + help.twodigits(timetrialpar);
}
return tempstring;
} }
std::string Game::resulttimestring(void) std::string Game::resulttimestring(void)
{ {
//given result time in seconds: //given result time in seconds:
std::string tempstring = ""; char output[SCREEN_WIDTH_CHARS + 1];
if (timetrialresulttime >= 60) help.format_time(output, sizeof(output), timetrialresulttime, timetrialresultframes, true);
{ return output;
tempstring = help.twodigits(timetrialresulttime / 60) + ":"
+ help.twodigits(timetrialresulttime % 60);
}
else
{
tempstring = "00:" + help.twodigits(timetrialresulttime);
}
tempstring += "." + help.twodigits(timetrialresultframes*100 / 30);
return tempstring;
} }
std::string Game::timetstring( int t ) std::string Game::timetstring( int t )
{ {
//given par time in seconds: //given par time in seconds:
std::string tempstring = ""; char output[SCREEN_WIDTH_CHARS + 1];
if (t >= 60) help.format_time(output, sizeof(output), t, -1, true);
{ return output;
tempstring = help.twodigits(t / 60) + ":" + help.twodigits(t % 60);
}
else
{
tempstring = "00:" + help.twodigits(t);
}
return tempstring;
} }
void Game::timestringcenti(char* buffer, const size_t buffer_size) void Game::timestringcenti(char* buffer, const size_t buffer_size)
{ {
/* 16 chars should be plenty for int32s */ help.format_time(buffer, buffer_size, help.hms_to_seconds(hours, minutes, seconds), frames, true);
char hours_str[16] = {'\0'};
if (hours > 0)
{
SDL_snprintf(hours_str, sizeof(hours_str), "%i:", hours);
}
SDL_snprintf(
buffer, buffer_size,
"%s%02i:%02i.%02i",
hours_str, minutes, seconds, frames * 100 / 30
);
} }
void Game::returnmenu(void) void Game::returnmenu(void)

View file

@ -139,8 +139,6 @@ public:
std::string timestring(void); std::string timestring(void);
std::string partimestring(void);
std::string resulttimestring(void); std::string resulttimestring(void);
std::string timetstring(int t); std::string timetstring(int t);

View file

@ -1708,7 +1708,7 @@ void gamerender(void)
if (graphics.fademode==0 && !game.intimetrial && !game.isingamecompletescreen() && (!game.swnmode || game.swngame != 1) && game.showingametimer) if (graphics.fademode==0 && !game.intimetrial && !game.isingamecompletescreen() && (!game.swnmode || game.swngame != 1) && game.showingametimer)
{ {
char buffer[SCREEN_WIDTH_TILES + 1]; /* ASCII only */ char buffer[SCREEN_WIDTH_CHARS + 1];
graphics.bprint(6, 6, "TIME:", 255,255,255); graphics.bprint(6, 6, "TIME:", 255,255,255);
game.timestringcenti(buffer, sizeof(buffer)); game.timestringcenti(buffer, sizeof(buffer));
graphics.bprint(46, 6, buffer, 196, 196, 196); graphics.bprint(46, 6, buffer, 196, 196, 196);
@ -1918,7 +1918,7 @@ void gamerender(void)
} }
else else
{ {
char buffer[SCREEN_WIDTH_TILES + 1]; /* ASCII only */ char buffer[SCREEN_WIDTH_CHARS + 1];
game.timestringcenti(buffer, sizeof(buffer)); game.timestringcenti(buffer, sizeof(buffer));
//Draw OSD stuff //Draw OSD stuff
@ -1954,12 +1954,12 @@ void gamerender(void)
if(game.timetrialparlost) if(game.timetrialparlost)
{ {
graphics.bprint(195, 214, "PAR TIME:", 80, 80, 80); graphics.bprint(195, 214, "PAR TIME:", 80, 80, 80);
graphics.bprint(275, 214, game.partimestring(), 80, 80, 80); graphics.bprint(275, 214, game.timetstring(game.timetrialpar), 80, 80, 80);
} }
else else
{ {
graphics.bprint(195, 214, "PAR TIME:", 255, 255, 255); graphics.bprint(195, 214, "PAR TIME:", 255, 255, 255);
graphics.bprint(275, 214, game.partimestring(), 196, 196, 196); graphics.bprint(275, 214, game.timetstring(game.timetrialpar), 196, 196, 196);
} }
} }
} }

View file

@ -4,6 +4,7 @@
#include <SDL.h> #include <SDL.h>
#include <sstream> #include <sstream>
#include "Constants.h"
#include "Maths.h" #include "Maths.h"
static const char* GCChar(const SDL_GameControllerButton button) static const char* GCChar(const SDL_GameControllerButton button)
@ -168,37 +169,49 @@ std::string UtilityClass::GCString(const std::vector<SDL_GameControllerButton>&
return retval; return retval;
} }
std::string UtilityClass::twodigits( int t ) int UtilityClass::hms_to_seconds(int h, int m, int s)
{ {
if (t < 10) return h*3600 + m*60 + s;
}
void UtilityClass::format_time(char* buffer, const size_t buffer_size, int seconds, int frames, bool always_minutes)
{
int s = seconds % 60;
int m = (seconds / 60) % 60;
int h = seconds / 3600;
if (h > 0)
{ {
return "0" + String(t); /* H:MM:SS / H:MM:SS.CC */
SDL_snprintf(buffer, buffer_size,
frames == -1 ? "%d:%02d:%02d" : "%d:%02d:%02d.%02d",
h, m, s, frames * 100 / 30
);
} }
if (t >= 100) else if (m > 0 || always_minutes || frames == -1)
{ {
return "??"; /* M:SS / M:SS.CC */
SDL_snprintf(buffer, buffer_size,
frames == -1 ? "%d:%02d" : "%d:%02d.%02d",
m, s, frames * 100 / 30
);
}
else
{
/* S.CC */
SDL_snprintf(buffer, buffer_size,
"%d.%02d",
s, frames * 100 / 30
);
} }
return String(t);
} }
std::string UtilityClass::timestring( int t ) std::string UtilityClass::timestring( int t )
{ {
//given a time t in frames, return a time in seconds //given a time t in frames, return a time in seconds
std::string tempstring = ""; char output[SCREEN_WIDTH_CHARS + 1];
int temp = t / 30; format_time(output, sizeof(output), t / 30, t % 30, false);
if (temp < 60) //less than one minute return output;
{
t = t % 30;
tempstring = String(temp) + ":" + twodigits(t * 100 / 30);
}
else
{
int temp2 = temp / 60;
temp = temp % 60;
t = t % 30;
tempstring = String(temp2) + ":" + twodigits(temp) + ":" + twodigits(t * 100 / 30);
}
return tempstring;
} }
std::string UtilityClass::number_words( int _t ) std::string UtilityClass::number_words( int _t )

View file

@ -95,7 +95,9 @@ public:
static std::string GCString(const std::vector<SDL_GameControllerButton>& buttons); static std::string GCString(const std::vector<SDL_GameControllerButton>& buttons);
std::string twodigits(int t); int hms_to_seconds(int h, int m, int s);
void format_time(char* buffer, const size_t buffer_size, int seconds, int frames, bool always_minutes);
std::string timestring(int t); std::string timestring(int t);