mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
Merge pull request #7355 from Robyt3/Client-Graph-SmoothTime-Refactoring
Refactor `CGraph` and `CSmoothTime`, move to separate compilation units, minor fixes to graph rendering
This commit is contained in:
commit
dad2c14abb
|
@ -2117,6 +2117,8 @@ if(CLIENT)
|
|||
friends.h
|
||||
ghost.cpp
|
||||
ghost.h
|
||||
graph.cpp
|
||||
graph.h
|
||||
graphics_defines.h
|
||||
graphics_threaded.cpp
|
||||
graphics_threaded.h
|
||||
|
@ -2131,6 +2133,8 @@ if(CLIENT)
|
|||
serverbrowser_http.h
|
||||
serverbrowser_ping_cache.cpp
|
||||
serverbrowser_ping_cache.h
|
||||
smooth_time.cpp
|
||||
smooth_time.h
|
||||
sound.cpp
|
||||
sound.h
|
||||
sqlite.cpp
|
||||
|
|
|
@ -74,214 +74,6 @@ using namespace std::chrono_literals;
|
|||
static const ColorRGBA gs_ClientNetworkPrintColor{0.7f, 1, 0.7f, 1.0f};
|
||||
static const ColorRGBA gs_ClientNetworkErrPrintColor{1.0f, 0.25f, 0.25f, 1.0f};
|
||||
|
||||
void CGraph::Init(float Min, float Max)
|
||||
{
|
||||
SetMin(Min);
|
||||
SetMax(Max);
|
||||
m_Index = 0;
|
||||
}
|
||||
|
||||
void CGraph::SetMin(float Min)
|
||||
{
|
||||
m_MinRange = m_Min = Min;
|
||||
}
|
||||
|
||||
void CGraph::SetMax(float Max)
|
||||
{
|
||||
m_MaxRange = m_Max = Max;
|
||||
}
|
||||
|
||||
void CGraph::Scale()
|
||||
{
|
||||
m_Min = m_MinRange;
|
||||
m_Max = m_MaxRange;
|
||||
for(auto Value : m_aValues)
|
||||
{
|
||||
if(Value > m_Max)
|
||||
m_Max = Value;
|
||||
else if(Value < m_Min)
|
||||
m_Min = Value;
|
||||
}
|
||||
}
|
||||
|
||||
void CGraph::Add(float v, float r, float g, float b)
|
||||
{
|
||||
m_Index = (m_Index + 1) % MAX_VALUES;
|
||||
InsertAt(m_Index, v, r, g, b);
|
||||
}
|
||||
|
||||
void CGraph::InsertAt(size_t Index, float v, float r, float g, float b)
|
||||
{
|
||||
dbg_assert(Index < MAX_VALUES, "Index out of bounds");
|
||||
m_aValues[Index] = v;
|
||||
m_aColors[Index][0] = r;
|
||||
m_aColors[Index][1] = g;
|
||||
m_aColors[Index][2] = b;
|
||||
}
|
||||
|
||||
void CGraph::Render(IGraphics *pGraphics, ITextRender *pTextRender, float x, float y, float w, float h, const char *pDescription)
|
||||
{
|
||||
pGraphics->TextureClear();
|
||||
|
||||
pGraphics->QuadsBegin();
|
||||
pGraphics->SetColor(0.0f, 0.0f, 0.0f, 0.75f);
|
||||
IGraphics::CQuadItem QuadItem(x, y, w, h);
|
||||
pGraphics->QuadsDrawTL(&QuadItem, 1);
|
||||
pGraphics->QuadsEnd();
|
||||
|
||||
pGraphics->LinesBegin();
|
||||
pGraphics->SetColor(0.95f, 0.95f, 0.95f, 1.0f);
|
||||
IGraphics::CLineItem LineItem(x, y + h / 2, x + w, y + h / 2);
|
||||
pGraphics->LinesDraw(&LineItem, 1);
|
||||
pGraphics->SetColor(0.5f, 0.5f, 0.5f, 0.75f);
|
||||
IGraphics::CLineItem aLineItems[2] = {
|
||||
IGraphics::CLineItem(x, y + (h * 3) / 4, x + w, y + (h * 3) / 4),
|
||||
IGraphics::CLineItem(x, y + h / 4, x + w, y + h / 4)};
|
||||
pGraphics->LinesDraw(aLineItems, std::size(aLineItems));
|
||||
for(int i = 1; i < MAX_VALUES; i++)
|
||||
{
|
||||
float a0 = (i - 1) / (float)MAX_VALUES;
|
||||
float a1 = i / (float)MAX_VALUES;
|
||||
int i0 = (m_Index + i - 1) % MAX_VALUES;
|
||||
int i1 = (m_Index + i) % MAX_VALUES;
|
||||
|
||||
float v0 = (m_aValues[i0] - m_Min) / (m_Max - m_Min);
|
||||
float v1 = (m_aValues[i1] - m_Min) / (m_Max - m_Min);
|
||||
|
||||
IGraphics::CColorVertex aColorVertices[2] = {
|
||||
IGraphics::CColorVertex(0, m_aColors[i0][0], m_aColors[i0][1], m_aColors[i0][2], 0.75f),
|
||||
IGraphics::CColorVertex(1, m_aColors[i1][0], m_aColors[i1][1], m_aColors[i1][2], 0.75f)};
|
||||
pGraphics->SetColorVertex(aColorVertices, std::size(aColorVertices));
|
||||
IGraphics::CLineItem LineItem2(x + a0 * w, y + h - v0 * h, x + a1 * w, y + h - v1 * h);
|
||||
pGraphics->LinesDraw(&LineItem2, 1);
|
||||
}
|
||||
pGraphics->LinesEnd();
|
||||
|
||||
const float FontSize = 12.0f;
|
||||
const float Spacing = 2.0f;
|
||||
|
||||
pTextRender->Text(x + Spacing, y + h - FontSize - Spacing, FontSize, pDescription);
|
||||
|
||||
char aBuf[32];
|
||||
str_format(aBuf, sizeof(aBuf), "%.2f", m_Max);
|
||||
pTextRender->Text(x + w - pTextRender->TextWidth(FontSize, aBuf) - Spacing, y + Spacing, FontSize, aBuf);
|
||||
|
||||
str_format(aBuf, sizeof(aBuf), "%.2f", m_Min);
|
||||
pTextRender->Text(x + w - pTextRender->TextWidth(FontSize, aBuf) - Spacing, y + h - FontSize - Spacing, FontSize, aBuf);
|
||||
}
|
||||
|
||||
void CSmoothTime::Init(int64_t Target)
|
||||
{
|
||||
m_Snap = time_get();
|
||||
m_Current = Target;
|
||||
m_Target = Target;
|
||||
m_SnapMargin = m_Snap;
|
||||
m_CurrentMargin = 0;
|
||||
m_TargetMargin = 0;
|
||||
m_aAdjustSpeed[0] = 0.3f;
|
||||
m_aAdjustSpeed[1] = 0.3f;
|
||||
m_Graph.Init(0.0f, 0.5f);
|
||||
}
|
||||
|
||||
void CSmoothTime::SetAdjustSpeed(int Direction, float Value)
|
||||
{
|
||||
m_aAdjustSpeed[Direction] = Value;
|
||||
}
|
||||
|
||||
int64_t CSmoothTime::Get(int64_t Now)
|
||||
{
|
||||
int64_t c = m_Current + (Now - m_Snap);
|
||||
int64_t t = m_Target + (Now - m_Snap);
|
||||
|
||||
// it's faster to adjust upward instead of downward
|
||||
// we might need to adjust these abit
|
||||
|
||||
float AdjustSpeed = m_aAdjustSpeed[0];
|
||||
if(t > c)
|
||||
AdjustSpeed = m_aAdjustSpeed[1];
|
||||
|
||||
float a = ((Now - m_Snap) / (float)time_freq()) * AdjustSpeed;
|
||||
if(a > 1.0f)
|
||||
a = 1.0f;
|
||||
|
||||
int64_t r = c + (int64_t)((t - c) * a);
|
||||
|
||||
m_Graph.Add(a + 0.5f, 1, 1, 1);
|
||||
|
||||
return r + GetMargin(Now);
|
||||
}
|
||||
|
||||
void CSmoothTime::UpdateInt(int64_t Target)
|
||||
{
|
||||
int64_t Now = time_get();
|
||||
m_Current = Get(Now) - GetMargin(Now);
|
||||
m_Snap = Now;
|
||||
m_Target = Target - GetMargin(Now);
|
||||
}
|
||||
|
||||
void CSmoothTime::Update(CGraph *pGraph, int64_t Target, int TimeLeft, int AdjustDirection)
|
||||
{
|
||||
int UpdateTimer = 1;
|
||||
|
||||
if(TimeLeft < 0)
|
||||
{
|
||||
int IsSpike = 0;
|
||||
if(TimeLeft < -50)
|
||||
{
|
||||
IsSpike = 1;
|
||||
|
||||
m_SpikeCounter += 5;
|
||||
if(m_SpikeCounter > 50)
|
||||
m_SpikeCounter = 50;
|
||||
}
|
||||
|
||||
if(IsSpike && m_SpikeCounter < 15)
|
||||
{
|
||||
// ignore this ping spike
|
||||
UpdateTimer = 0;
|
||||
pGraph->Add(TimeLeft, 1, 1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
pGraph->Add(TimeLeft, 1, 0, 0);
|
||||
if(m_aAdjustSpeed[AdjustDirection] < 30.0f)
|
||||
m_aAdjustSpeed[AdjustDirection] *= 2.0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_SpikeCounter)
|
||||
m_SpikeCounter--;
|
||||
|
||||
pGraph->Add(TimeLeft, 0, 1, 0);
|
||||
|
||||
m_aAdjustSpeed[AdjustDirection] *= 0.95f;
|
||||
if(m_aAdjustSpeed[AdjustDirection] < 2.0f)
|
||||
m_aAdjustSpeed[AdjustDirection] = 2.0f;
|
||||
}
|
||||
|
||||
if(UpdateTimer)
|
||||
UpdateInt(Target);
|
||||
}
|
||||
|
||||
int64_t CSmoothTime::GetMargin(int64_t Now)
|
||||
{
|
||||
int64_t TimePassed = Now - m_SnapMargin;
|
||||
int64_t Diff = m_TargetMargin - m_CurrentMargin;
|
||||
|
||||
float a = clamp(TimePassed / (float)time_freq(), -1.f, 1.f);
|
||||
int64_t Lim = maximum((int64_t)(a * absolute(Diff)), 1 + TimePassed / 100);
|
||||
return m_CurrentMargin + (int64_t)clamp(Diff, -Lim, Lim);
|
||||
}
|
||||
|
||||
void CSmoothTime::UpdateMargin(int64_t TargetMargin)
|
||||
{
|
||||
int64_t Now = time_get();
|
||||
m_CurrentMargin = GetMargin(Now);
|
||||
m_SnapMargin = Now;
|
||||
m_TargetMargin = TargetMargin;
|
||||
}
|
||||
|
||||
CClient::CClient() :
|
||||
m_DemoPlayer(&m_SnapshotDelta, true, [&]() { UpdateDemoIntraTimers(); })
|
||||
{
|
||||
|
@ -1920,7 +1712,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
|
|||
}
|
||||
|
||||
if(Target)
|
||||
m_PredictedTime.Update(&m_InputtimeMarginGraph, Target, TimeLeft, 1);
|
||||
m_PredictedTime.Update(&m_InputtimeMarginGraph, Target, TimeLeft, CSmoothTime::ADJUSTDIRECTION_UP);
|
||||
}
|
||||
else if(Msg == NETMSG_SNAP || Msg == NETMSG_SNAPSINGLE || Msg == NETMSG_SNAPEMPTY)
|
||||
{
|
||||
|
@ -2109,7 +1901,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
|
|||
if(!Dummy)
|
||||
{
|
||||
m_PredictedTime.Init(GameTick * time_freq() / 50);
|
||||
m_PredictedTime.SetAdjustSpeed(1, 1000.0f);
|
||||
m_PredictedTime.SetAdjustSpeed(CSmoothTime::ADJUSTDIRECTION_UP, 1000.0f);
|
||||
m_PredictedTime.UpdateMargin(PredictionMargin() * time_freq() / 1000);
|
||||
}
|
||||
m_aGameTime[Conn].Init((GameTick - 1) * time_freq() / 50);
|
||||
|
@ -2136,7 +1928,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
|
|||
int64_t Now = m_aGameTime[Conn].Get(time_get());
|
||||
int64_t TickStart = GameTick * time_freq() / 50;
|
||||
int64_t TimeLeft = (TickStart - Now) * 1000 / time_freq();
|
||||
m_aGameTime[Conn].Update(&m_GametimeMarginGraph, (GameTick - 1) * time_freq() / 50, TimeLeft, 0);
|
||||
m_aGameTime[Conn].Update(&m_GametimeMarginGraph, (GameTick - 1) * time_freq() / 50, TimeLeft, CSmoothTime::ADJUSTDIRECTION_DOWN);
|
||||
}
|
||||
|
||||
if(m_aReceivedSnapshots[Conn] > 50 && !m_aCodeRunAfterJoin[Conn])
|
||||
|
@ -3225,7 +3017,7 @@ void CClient::Run()
|
|||
{
|
||||
// update frametime
|
||||
m_RenderFrameTime = (Now - m_LastRenderTime) / (float)time_freq();
|
||||
m_FpsGraph.Add(1.0f / m_RenderFrameTime, 1, 1, 1);
|
||||
m_FpsGraph.Add(1.0f / m_RenderFrameTime);
|
||||
|
||||
if(m_BenchmarkFile)
|
||||
{
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
#include <engine/shared/network.h>
|
||||
#include <engine/warning.h>
|
||||
|
||||
#include "graph.h"
|
||||
#include "smooth_time.h"
|
||||
|
||||
class CDemoEdit;
|
||||
class IDemoRecorder;
|
||||
class CMsgPacker;
|
||||
|
@ -40,60 +43,6 @@ class IUpdater;
|
|||
#define CONNECTLINK_DOUBLE_SLASH "ddnet://"
|
||||
#define CONNECTLINK_NO_SLASH "ddnet:"
|
||||
|
||||
class CGraph
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
MAX_VALUES = 128,
|
||||
};
|
||||
|
||||
private:
|
||||
float m_Min, m_Max;
|
||||
float m_MinRange, m_MaxRange;
|
||||
float m_aValues[MAX_VALUES];
|
||||
float m_aColors[MAX_VALUES][3];
|
||||
size_t m_Index;
|
||||
|
||||
public:
|
||||
void Init(float Min, float Max);
|
||||
void SetMin(float Min);
|
||||
void SetMax(float Max);
|
||||
|
||||
void Scale();
|
||||
void Add(float v, float r, float g, float b);
|
||||
void InsertAt(size_t Index, float v, float r, float g, float b);
|
||||
void Render(IGraphics *pGraphics, ITextRender *pTextRender, float x, float y, float w, float h, const char *pDescription);
|
||||
};
|
||||
|
||||
class CSmoothTime
|
||||
{
|
||||
int64_t m_Snap;
|
||||
int64_t m_Current;
|
||||
int64_t m_Target;
|
||||
|
||||
int64_t m_SnapMargin;
|
||||
int64_t m_CurrentMargin;
|
||||
int64_t m_TargetMargin;
|
||||
|
||||
CGraph m_Graph;
|
||||
|
||||
int m_SpikeCounter;
|
||||
|
||||
float m_aAdjustSpeed[2]; // 0 = down, 1 = up
|
||||
public:
|
||||
void Init(int64_t Target);
|
||||
void SetAdjustSpeed(int Direction, float Value);
|
||||
|
||||
int64_t Get(int64_t Now);
|
||||
|
||||
void UpdateInt(int64_t Target);
|
||||
void Update(CGraph *pGraph, int64_t Target, int TimeLeft, int AdjustDirection);
|
||||
|
||||
int64_t GetMargin(int64_t Now);
|
||||
void UpdateMargin(int64_t TargetMargin);
|
||||
};
|
||||
|
||||
class CServerCapabilities
|
||||
{
|
||||
public:
|
||||
|
|
105
src/engine/client/graph.cpp
Normal file
105
src/engine/client/graph.cpp
Normal file
|
@ -0,0 +1,105 @@
|
|||
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
||||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
||||
|
||||
#include <engine/graphics.h>
|
||||
#include <engine/textrender.h>
|
||||
|
||||
#include "graph.h"
|
||||
|
||||
void CGraph::Init(float Min, float Max)
|
||||
{
|
||||
SetMin(Min);
|
||||
SetMax(Max);
|
||||
m_Index = 0;
|
||||
for(auto &Entry : m_aEntries)
|
||||
Entry.m_Initialized = false;
|
||||
}
|
||||
|
||||
void CGraph::SetMin(float Min)
|
||||
{
|
||||
m_MinRange = m_Min = Min;
|
||||
}
|
||||
|
||||
void CGraph::SetMax(float Max)
|
||||
{
|
||||
m_MaxRange = m_Max = Max;
|
||||
}
|
||||
|
||||
void CGraph::Scale()
|
||||
{
|
||||
m_Min = m_MinRange;
|
||||
m_Max = m_MaxRange;
|
||||
for(auto &Entry : m_aEntries)
|
||||
{
|
||||
if(Entry.m_Value > m_Max)
|
||||
m_Max = Entry.m_Value;
|
||||
else if(Entry.m_Value < m_Min)
|
||||
m_Min = Entry.m_Value;
|
||||
}
|
||||
}
|
||||
|
||||
void CGraph::Add(float Value, ColorRGBA Color)
|
||||
{
|
||||
InsertAt(m_Index, Value, Color);
|
||||
m_Index = (m_Index + 1) % MAX_VALUES;
|
||||
}
|
||||
|
||||
void CGraph::InsertAt(size_t Index, float Value, ColorRGBA Color)
|
||||
{
|
||||
dbg_assert(Index < MAX_VALUES, "Index out of bounds");
|
||||
m_aEntries[Index].m_Initialized = true;
|
||||
m_aEntries[Index].m_Value = Value;
|
||||
m_aEntries[Index].m_Color = Color;
|
||||
}
|
||||
|
||||
void CGraph::Render(IGraphics *pGraphics, ITextRender *pTextRender, float x, float y, float w, float h, const char *pDescription) const
|
||||
{
|
||||
pGraphics->TextureClear();
|
||||
|
||||
pGraphics->QuadsBegin();
|
||||
pGraphics->SetColor(0.0f, 0.0f, 0.0f, 0.75f);
|
||||
IGraphics::CQuadItem QuadItem(x, y, w, h);
|
||||
pGraphics->QuadsDrawTL(&QuadItem, 1);
|
||||
pGraphics->QuadsEnd();
|
||||
|
||||
pGraphics->LinesBegin();
|
||||
pGraphics->SetColor(0.95f, 0.95f, 0.95f, 1.0f);
|
||||
IGraphics::CLineItem LineItem(x, y + h / 2, x + w, y + h / 2);
|
||||
pGraphics->LinesDraw(&LineItem, 1);
|
||||
pGraphics->SetColor(0.5f, 0.5f, 0.5f, 0.75f);
|
||||
IGraphics::CLineItem aLineItems[2] = {
|
||||
IGraphics::CLineItem(x, y + (h * 3) / 4, x + w, y + (h * 3) / 4),
|
||||
IGraphics::CLineItem(x, y + h / 4, x + w, y + h / 4)};
|
||||
pGraphics->LinesDraw(aLineItems, std::size(aLineItems));
|
||||
for(int i = 1; i < MAX_VALUES; i++)
|
||||
{
|
||||
const auto &Entry0 = m_aEntries[(m_Index + i - 1) % MAX_VALUES];
|
||||
const auto &Entry1 = m_aEntries[(m_Index + i) % MAX_VALUES];
|
||||
if(!Entry0.m_Initialized || !Entry1.m_Initialized)
|
||||
continue;
|
||||
float a0 = (i - 1) / (float)(MAX_VALUES - 1);
|
||||
float a1 = i / (float)(MAX_VALUES - 1);
|
||||
float v0 = (Entry0.m_Value - m_Min) / (m_Max - m_Min);
|
||||
float v1 = (Entry1.m_Value - m_Min) / (m_Max - m_Min);
|
||||
|
||||
IGraphics::CColorVertex aColorVertices[2] = {
|
||||
IGraphics::CColorVertex(0, Entry0.m_Color.r, Entry0.m_Color.g, Entry0.m_Color.b, Entry0.m_Color.a),
|
||||
IGraphics::CColorVertex(1, Entry1.m_Color.r, Entry1.m_Color.g, Entry1.m_Color.b, Entry1.m_Color.a)};
|
||||
pGraphics->SetColorVertex(aColorVertices, std::size(aColorVertices));
|
||||
IGraphics::CLineItem LineItem2(x + a0 * w, y + h - v0 * h, x + a1 * w, y + h - v1 * h);
|
||||
pGraphics->LinesDraw(&LineItem2, 1);
|
||||
}
|
||||
pGraphics->LinesEnd();
|
||||
|
||||
const float FontSize = 12.0f;
|
||||
const float Spacing = 2.0f;
|
||||
|
||||
pTextRender->Text(x + Spacing, y + h - FontSize - Spacing, FontSize, pDescription);
|
||||
|
||||
char aBuf[32];
|
||||
str_format(aBuf, sizeof(aBuf), "%.2f", m_Max);
|
||||
pTextRender->Text(x + w - pTextRender->TextWidth(FontSize, aBuf) - Spacing, y + Spacing, FontSize, aBuf);
|
||||
|
||||
str_format(aBuf, sizeof(aBuf), "%.2f", m_Min);
|
||||
pTextRender->Text(x + w - pTextRender->TextWidth(FontSize, aBuf) - Spacing, y + h - FontSize - Spacing, FontSize, aBuf);
|
||||
}
|
45
src/engine/client/graph.h
Normal file
45
src/engine/client/graph.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
||||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
||||
|
||||
#ifndef ENGINE_CLIENT_GRAPH_H
|
||||
#define ENGINE_CLIENT_GRAPH_H
|
||||
|
||||
#include <base/color.h>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
class IGraphics;
|
||||
class ITextRender;
|
||||
|
||||
class CGraph
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
MAX_VALUES = 128,
|
||||
};
|
||||
|
||||
private:
|
||||
struct SEntry
|
||||
{
|
||||
bool m_Initialized;
|
||||
float m_Value;
|
||||
ColorRGBA m_Color;
|
||||
};
|
||||
float m_Min, m_Max;
|
||||
float m_MinRange, m_MaxRange;
|
||||
SEntry m_aEntries[MAX_VALUES];
|
||||
size_t m_Index;
|
||||
|
||||
public:
|
||||
void Init(float Min, float Max);
|
||||
void SetMin(float Min);
|
||||
void SetMax(float Max);
|
||||
|
||||
void Scale();
|
||||
void Add(float Value, ColorRGBA Color = ColorRGBA(1.0f, 1.0f, 1.0f, 0.75f));
|
||||
void InsertAt(size_t Index, float Value, ColorRGBA Color = ColorRGBA(1.0f, 1.0f, 1.0f, 0.75f));
|
||||
void Render(IGraphics *pGraphics, ITextRender *pTextRender, float x, float y, float w, float h, const char *pDescription) const;
|
||||
};
|
||||
|
||||
#endif
|
116
src/engine/client/smooth_time.cpp
Normal file
116
src/engine/client/smooth_time.cpp
Normal file
|
@ -0,0 +1,116 @@
|
|||
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
||||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
||||
|
||||
#include <base/math.h>
|
||||
#include <base/system.h>
|
||||
|
||||
#include "graph.h"
|
||||
#include "smooth_time.h"
|
||||
|
||||
void CSmoothTime::Init(int64_t Target)
|
||||
{
|
||||
m_Snap = time_get();
|
||||
m_Current = Target;
|
||||
m_Target = Target;
|
||||
m_SnapMargin = m_Snap;
|
||||
m_CurrentMargin = 0;
|
||||
m_TargetMargin = 0;
|
||||
m_aAdjustSpeed[ADJUSTDIRECTION_DOWN] = 0.3f;
|
||||
m_aAdjustSpeed[ADJUSTDIRECTION_UP] = 0.3f;
|
||||
}
|
||||
|
||||
void CSmoothTime::SetAdjustSpeed(EAdjustDirection Direction, float Value)
|
||||
{
|
||||
m_aAdjustSpeed[Direction] = Value;
|
||||
}
|
||||
|
||||
int64_t CSmoothTime::Get(int64_t Now) const
|
||||
{
|
||||
int64_t c = m_Current + (Now - m_Snap);
|
||||
int64_t t = m_Target + (Now - m_Snap);
|
||||
|
||||
// it's faster to adjust upward instead of downward
|
||||
// we might need to adjust these abit
|
||||
|
||||
float AdjustSpeed = m_aAdjustSpeed[ADJUSTDIRECTION_DOWN];
|
||||
if(t > c)
|
||||
AdjustSpeed = m_aAdjustSpeed[ADJUSTDIRECTION_UP];
|
||||
|
||||
float a = ((Now - m_Snap) / (float)time_freq()) * AdjustSpeed;
|
||||
if(a > 1.0f)
|
||||
a = 1.0f;
|
||||
|
||||
int64_t r = c + (int64_t)((t - c) * a);
|
||||
return r + GetMargin(Now);
|
||||
}
|
||||
|
||||
void CSmoothTime::UpdateInt(int64_t Target)
|
||||
{
|
||||
int64_t Now = time_get();
|
||||
m_Current = Get(Now) - GetMargin(Now);
|
||||
m_Snap = Now;
|
||||
m_Target = Target - GetMargin(Now);
|
||||
}
|
||||
|
||||
void CSmoothTime::Update(CGraph *pGraph, int64_t Target, int TimeLeft, EAdjustDirection AdjustDirection)
|
||||
{
|
||||
bool UpdateTimer = true;
|
||||
|
||||
if(TimeLeft < 0)
|
||||
{
|
||||
bool IsSpike = false;
|
||||
if(TimeLeft < -50)
|
||||
{
|
||||
IsSpike = true;
|
||||
|
||||
m_SpikeCounter += 5;
|
||||
if(m_SpikeCounter > 50)
|
||||
m_SpikeCounter = 50;
|
||||
}
|
||||
|
||||
if(IsSpike && m_SpikeCounter < 15)
|
||||
{
|
||||
// ignore this ping spike
|
||||
UpdateTimer = false;
|
||||
pGraph->Add(TimeLeft, ColorRGBA(1.0f, 1.0f, 0.0f, 0.75f));
|
||||
}
|
||||
else
|
||||
{
|
||||
pGraph->Add(TimeLeft, ColorRGBA(1.0f, 0.0f, 0.0f, 0.75f));
|
||||
if(m_aAdjustSpeed[AdjustDirection] < 30.0f)
|
||||
m_aAdjustSpeed[AdjustDirection] *= 2.0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_SpikeCounter)
|
||||
m_SpikeCounter--;
|
||||
|
||||
pGraph->Add(TimeLeft, ColorRGBA(0.0f, 1.0f, 0.0f, 0.75f));
|
||||
|
||||
m_aAdjustSpeed[AdjustDirection] *= 0.95f;
|
||||
if(m_aAdjustSpeed[AdjustDirection] < 2.0f)
|
||||
m_aAdjustSpeed[AdjustDirection] = 2.0f;
|
||||
}
|
||||
|
||||
if(UpdateTimer)
|
||||
UpdateInt(Target);
|
||||
}
|
||||
|
||||
int64_t CSmoothTime::GetMargin(int64_t Now) const
|
||||
{
|
||||
int64_t TimePassed = Now - m_SnapMargin;
|
||||
int64_t Diff = m_TargetMargin - m_CurrentMargin;
|
||||
|
||||
float a = clamp(TimePassed / (float)time_freq(), -1.f, 1.f);
|
||||
int64_t Lim = maximum((int64_t)(a * absolute(Diff)), 1 + TimePassed / 100);
|
||||
return m_CurrentMargin + (int64_t)clamp(Diff, -Lim, Lim);
|
||||
}
|
||||
|
||||
void CSmoothTime::UpdateMargin(int64_t TargetMargin)
|
||||
{
|
||||
int64_t Now = time_get();
|
||||
m_CurrentMargin = GetMargin(Now);
|
||||
m_SnapMargin = Now;
|
||||
m_TargetMargin = TargetMargin;
|
||||
}
|
46
src/engine/client/smooth_time.h
Normal file
46
src/engine/client/smooth_time.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
||||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
||||
|
||||
#ifndef ENGINE_CLIENT_SMOOTH_TIME_H
|
||||
#define ENGINE_CLIENT_SMOOTH_TIME_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class CGraph;
|
||||
|
||||
class CSmoothTime
|
||||
{
|
||||
public:
|
||||
enum EAdjustDirection
|
||||
{
|
||||
ADJUSTDIRECTION_DOWN = 0,
|
||||
ADJUSTDIRECTION_UP,
|
||||
NUM_ADJUSTDIRECTIONS,
|
||||
};
|
||||
|
||||
private:
|
||||
int64_t m_Snap;
|
||||
int64_t m_Current;
|
||||
int64_t m_Target;
|
||||
|
||||
int64_t m_SnapMargin;
|
||||
int64_t m_CurrentMargin;
|
||||
int64_t m_TargetMargin;
|
||||
|
||||
int m_SpikeCounter;
|
||||
float m_aAdjustSpeed[NUM_ADJUSTDIRECTIONS];
|
||||
|
||||
public:
|
||||
void Init(int64_t Target);
|
||||
void SetAdjustSpeed(EAdjustDirection Direction, float Value);
|
||||
|
||||
int64_t Get(int64_t Now) const;
|
||||
|
||||
void UpdateInt(int64_t Target);
|
||||
void Update(CGraph *pGraph, int64_t Target, int TimeLeft, EAdjustDirection AdjustDirection);
|
||||
|
||||
int64_t GetMargin(int64_t Now) const;
|
||||
void UpdateMargin(int64_t TargetMargin);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -187,12 +187,12 @@ void CDebugHud::RenderTuning()
|
|||
const float RampedSpeed = Speed * Ramp;
|
||||
if(RampedSpeed >= PreviousRampedSpeed)
|
||||
{
|
||||
m_RampGraph.InsertAt(i, RampedSpeed / 32, 0, 1, 0);
|
||||
m_RampGraph.InsertAt(i, RampedSpeed / 32, ColorRGBA(0.0f, 1.0f, 0.0f, 0.75f));
|
||||
m_SpeedTurningPoint = Speed;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_RampGraph.InsertAt(i, RampedSpeed / 32, 1, 0, 0);
|
||||
m_RampGraph.InsertAt(i, RampedSpeed / 32, ColorRGBA(1.0f, 0.0f, 0.0f, 0.75f));
|
||||
}
|
||||
PreviousRampedSpeed = RampedSpeed;
|
||||
}
|
||||
|
@ -209,16 +209,16 @@ void CDebugHud::RenderTuning()
|
|||
const float RampedSpeed = Speed * Ramp;
|
||||
if(RampedSpeed >= PreviousRampedSpeed)
|
||||
{
|
||||
m_ZoomedInGraph.InsertAt(i, RampedSpeed / 32, 0, 1, 0);
|
||||
m_ZoomedInGraph.InsertAt(i, RampedSpeed / 32, ColorRGBA(0.0f, 1.0f, 0.0f, 0.75f));
|
||||
m_SpeedTurningPoint = Speed;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ZoomedInGraph.InsertAt(i, RampedSpeed / 32, 1, 0, 0);
|
||||
m_ZoomedInGraph.InsertAt(i, RampedSpeed / 32, ColorRGBA(1.0f, 0.0f, 0.0f, 0.75f));
|
||||
}
|
||||
if(i == 0)
|
||||
{
|
||||
m_ZoomedInGraph.SetMin(RampedSpeed);
|
||||
m_ZoomedInGraph.SetMin(RampedSpeed / 32);
|
||||
}
|
||||
PreviousRampedSpeed = RampedSpeed;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue