Skip to content

Instantly share code, notes, and snippets.

@Anime-pdf
Last active November 27, 2024 16:58
Show Gist options
  • Save Anime-pdf/9ac49a934d5deb13ab42d7129daac2d3 to your computer and use it in GitHub Desktop.
Save Anime-pdf/9ac49a934d5deb13ab42d7129daac2d3 to your computer and use it in GitHub Desktop.
Simple rainbow generator for ddnet-based servers
#include "rainbow_generator.h"
#include <base/color.h>
#include <base/system.h>
CRainbowGenerator *CRainbowGenerator::ms_SInstance = nullptr;
CRainbowGenerator *CRainbowGenerator::GetInstance()
{
if(ms_SInstance == nullptr)
{
ms_SInstance = new CRainbowGenerator();
}
return ms_SInstance;
}
CRainbowGenerator::CRainbowGenerator()
{
for(int &Seed : m_Seed)
Seed = secure_rand() % 256 + 1;
m_Hue = secure_rand() % 256 + 1;
}
void CRainbowGenerator::Tick()
{
m_Hue = Clamp(++m_Hue);
}
int CRainbowGenerator::Clamp(const int Color)
{
if(Color > 256)
return Color % 255;
return Color;
}
unsigned CRainbowGenerator::Rainbow(const int ClientId, const unsigned OffsetMultiplier) const
{
return ColorHSLA(Clamp(m_Hue + (m_Seed[ClientId] * OffsetMultiplier)), 1, 0.3f).Pack();
}
#ifndef BASE_UTILS_RAINBOW_GENERATOR_H
#define BASE_UTILS_RAINBOW_GENERATOR_H
#include <engine/shared/protocol.h> // MAX_CLIENTS
class CRainbowGenerator
{
public:
CRainbowGenerator(CRainbowGenerator &Other) = delete;
void operator=(const CRainbowGenerator &) = delete;
static CRainbowGenerator *GetInstance();
void Tick();
unsigned Rainbow(int ClientId, unsigned OffsetMultiplier = 1) const;
private:
CRainbowGenerator();
static CRainbowGenerator *ms_SInstance;
int m_Seed[MAX_CLIENTS];
int m_Hue;
static int Clamp(int Color);
};
#endif // BASE_UTILS_RAINBOW_GENERATOR_H

Singleton class for generating and smoothly changing rainbow.

Offered API:

	static CRainbowGenerator *GetInstance(); // Returns instance of generator
	void Tick(); // Ticks Hue 
	unsigned Rainbow(int ClientId, unsigned OffsetMultiplier = 1) const; // Returns color in TW-code

Each ClientId holds individual offset to make different colors for every player.
If you want to make 2 different colors for single ClientId, use OffsetMultiplier, default is 1, increment it.

Usage

Smoothly 'ticking' hue:

void CGameContext::OnTick()
{
  // some code
  CRainbowGenerator::GetInstance()->Tick();
  // some code
}

Apply rainbow to player skin and feet:

void CPlayer::Snap(int SnappingClient)
{
  // some code
  pClientInfo->m_UseCustomColor = m_Rainbow ? true : m_TeeInfos.m_UseCustomColor;
  pClientInfo->m_ColorBody = m_Rainbow ? CRainbowGenerator::GetInstance()->Rainbow(m_ClientId) : m_TeeInfos.m_ColorBody;
  pClientInfo->m_ColorFeet = m_Rainbow ? CRainbowGenerator::GetInstance()->Rainbow(m_ClientId) : m_TeeInfos.m_ColorFeet;
  // some code 
}

Apply rainbow to player skin and feet, make offset for feet:

void CPlayer::Snap(int SnappingClient)
{
  // some code
  pClientInfo->m_UseCustomColor = m_Rainbow ? true : m_TeeInfos.m_UseCustomColor;
  pClientInfo->m_ColorBody = m_Rainbow ? CRainbowGenerator::GetInstance()->Rainbow(m_ClientId) : m_TeeInfos.m_ColorBody;
  pClientInfo->m_ColorFeet = m_Rainbow ? CRainbowGenerator::GetInstance()->Rainbow(m_ClientId, 2) : m_TeeInfos.m_ColorFeet;
  // some code 
}

rainbow

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment