Skip to content

Commit

Permalink
Use golden angle to generate unique, distinct DDTeam colors
Browse files Browse the repository at this point in the history
The DDTeam colors were previously generated in HSL by taking the team index and multiplying it by 360/64° to calculate the hue, which results in team colors being evenly distributed over the entire color range like a rainbow. However, this causes colors of adjacent teams to be very similar and therefore hard to distinguish.

Now, the hue is calculated by multiplying the team index with the golden angle (~137.50776°) and taking the modulo 360° of that. Due to the properties of the golden angle, this can generate never repeating sequences of unique colors where the adjacent colors are very distinct.

Duplicate code is reduced by adding the `CGameClient::GetDDTeamColor` function.
  • Loading branch information
Robyt3 committed Sep 13, 2023
1 parent 36f72b9 commit dcd86cb
Show file tree
Hide file tree
Showing 7 changed files with 19 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/game/client/components/chat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -977,7 +977,7 @@ void CChat::OnPrepareLines()
else if(m_aLines[r].m_NameColor == TEAM_SPECTATORS)
NameColor = ColorRGBA(0.75f, 0.5f, 0.75f, 1.f);
else if(m_aLines[r].m_ClientID >= 0 && g_Config.m_ClChatTeamColors && m_pClient->m_Teams.Team(m_aLines[r].m_ClientID))
NameColor = color_cast<ColorRGBA>(ColorHSLA(m_pClient->m_Teams.Team(m_aLines[r].m_ClientID) / 64.0f, 1.0f, 0.75f));
NameColor = m_pClient->GetDDTeamColor(m_pClient->m_Teams.Team(m_aLines[r].m_ClientID), 0.75f);
else
NameColor = ColorRGBA(0.8f, 0.8f, 0.8f, 1.f);

Expand Down
15 changes: 6 additions & 9 deletions src/game/client/components/killmessages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,21 +278,18 @@ void CKillMessages::OnRender()

float x = StartX;

ColorRGBA TColor(1.f, 1.f, 1.f, 1.f);
ColorRGBA TOutlineColor(0.f, 0.f, 0.f, 0.3f);

// render victim name
x -= m_aKillmsgs[r].m_VictimTextWidth;
ColorRGBA TextColor;
if(m_aKillmsgs[r].m_VictimID >= 0 && g_Config.m_ClChatTeamColors && m_aKillmsgs[r].m_VictimDDTeam)
{
TColor = color_cast<ColorRGBA>(ColorHSLA(m_aKillmsgs[r].m_VictimDDTeam / 64.0f, 1.0f, 0.75f));
TColor.a = 1.f;
}
TextColor = m_pClient->GetDDTeamColor(m_aKillmsgs[r].m_VictimDDTeam, 0.75f);
else
TextColor = TextRender()->DefaultTextColor();

CreateKillmessageNamesIfNotCreated(m_aKillmsgs[r]);

if(m_aKillmsgs[r].m_VictimTextContainerIndex.Valid())
TextRender()->RenderTextContainer(m_aKillmsgs[r].m_VictimTextContainerIndex, TColor, TOutlineColor, x, y + (46.f - 36.f) / 2.f);
TextRender()->RenderTextContainer(m_aKillmsgs[r].m_VictimTextContainerIndex, TextColor, TextRender()->DefaultTextOutlineColor(), x, y + (46.f - 36.f) / 2.f);

// render victim tee
x -= 24.0f;
Expand Down Expand Up @@ -380,7 +377,7 @@ void CKillMessages::OnRender()
x -= m_aKillmsgs[r].m_KillerTextWidth;

if(m_aKillmsgs[r].m_KillerTextContainerIndex.Valid())
TextRender()->RenderTextContainer(m_aKillmsgs[r].m_KillerTextContainerIndex, TColor, TOutlineColor, x, y + (46.f - 36.f) / 2.f);
TextRender()->RenderTextContainer(m_aKillmsgs[r].m_KillerTextContainerIndex, TextColor, TextRender()->DefaultTextOutlineColor(), x, y + (46.f - 36.f) / 2.f);
}

y += 46.0f;
Expand Down
2 changes: 1 addition & 1 deletion src/game/client/components/nameplates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ void CNamePlates::RenderNameplatePos(vec2 Position, const CNetObj_PlayerInfo *pP

float tw = m_aNamePlates[ClientID].m_NameTextWidth;
if(g_Config.m_ClNameplatesTeamcolors && m_pClient->m_Teams.Team(ClientID))
rgb = color_cast<ColorRGBA>(ColorHSLA(m_pClient->m_Teams.Team(ClientID) / 64.0f, 1.0f, 0.75f));
rgb = m_pClient->GetDDTeamColor(m_pClient->m_Teams.Team(ClientID), 0.75f);

ColorRGBA TColor;
ColorRGBA TOutlineColor;
Expand Down
2 changes: 1 addition & 1 deletion src/game/client/components/scoreboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch

if(DDTeam != TEAM_FLOCK)
{
ColorRGBA Color = color_cast<ColorRGBA>(ColorHSLA(DDTeam / 64.0f, 1.0f, 0.5f, 0.5f));
const ColorRGBA Color = m_pClient->GetDDTeamColor(DDTeam).WithAlpha(0.5f);
int Corners = 0;
if(OldDDTeam != DDTeam)
Corners |= IGraphics::CORNER_TL | IGraphics::CORNER_TR;
Expand Down
2 changes: 1 addition & 1 deletion src/game/client/components/spectator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ void CSpectator::OnRender()

if(DDTeam != TEAM_FLOCK)
{
ColorRGBA Color = color_cast<ColorRGBA>(ColorHSLA(DDTeam / 64.0f, 1.0f, 0.5f, 0.5f));
const ColorRGBA Color = m_pClient->GetDDTeamColor(DDTeam).WithAlpha(0.5f);
int Corners = 0;
if(OldDDTeam != DDTeam)
Corners |= IGraphics::CORNER_TL | IGraphics::CORNER_TR;
Expand Down
8 changes: 8 additions & 0 deletions src/game/client/gameclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,14 @@ bool CGameClient::Predict() const
return !m_Snap.m_SpecInfo.m_Active && m_Snap.m_pLocalCharacter;
}

ColorRGBA CGameClient::GetDDTeamColor(int DDTeam, float Lightness) const
{
// Use golden angle to generate unique colors with distinct adjacent colors.
// The first DDTeam (team 1) gets angle 0°, i.e. red hue.
const float Hue = std::fmod((DDTeam - 1) * (137.50776f / 360.0f), 1.0f);
return color_cast<ColorRGBA>(ColorHSLA(Hue, 1.0f, Lightness));
}

void CGameClient::OnRelease()
{
// release all systems
Expand Down
1 change: 1 addition & 0 deletions src/game/client/gameclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,7 @@ class CGameClient : public IGameClient
bool Predict() const;
bool PredictDummy() { return g_Config.m_ClPredictDummy && Client()->DummyConnected() && m_Snap.m_LocalClientID >= 0 && m_PredictedDummyID >= 0 && !m_aClients[m_PredictedDummyID].m_Paused; }
const CTuningParams *GetTuning(int i) { return &m_aTuningList[i]; }
ColorRGBA GetDDTeamColor(int DDTeam, float Lightness = 0.5f) const;

CGameWorld m_GameWorld;
CGameWorld m_PredictedWorld;
Expand Down

0 comments on commit dcd86cb

Please sign in to comment.