mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
Refactor goto_tele
Fixes a bug of some teleporters being skipped. Improves performance by only iterating all teleporters instead of every tile in the map.
This commit is contained in:
parent
3887eea18d
commit
6f75087d9f
|
@ -3,7 +3,9 @@
|
|||
|
||||
#include <engine/shared/config.h>
|
||||
|
||||
#include <base/log.h>
|
||||
#include <base/math.h>
|
||||
#include <base/vmath.h>
|
||||
#include <game/client/gameclient.h>
|
||||
#include <game/collision.h>
|
||||
#include <game/mapitems.h>
|
||||
|
@ -304,54 +306,54 @@ void CCamera::GotoTele(int Number, int Offset)
|
|||
{
|
||||
if(Collision()->TeleLayer() == nullptr)
|
||||
return;
|
||||
Number--;
|
||||
|
||||
if(m_GotoTeleLastNumber != Number)
|
||||
m_GotoTeleLastPos = ivec2(-1, -1);
|
||||
|
||||
int Match = -1;
|
||||
ivec2 MatchPos = ivec2(-1, -1);
|
||||
const size_t NumTeles = Collision()->TeleAllSize(Number);
|
||||
if(!NumTeles)
|
||||
{
|
||||
log_error("camera", "No teleporter with number %d found.", Number + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
auto FindTile = [this, &Match, &MatchPos, &Number, &Offset]() {
|
||||
for(int x = 0; x < Collision()->GetWidth(); x++)
|
||||
if(Offset != -1 || m_GotoTeleLastPos == ivec2(-1, -1))
|
||||
{
|
||||
for(int y = 0; y < Collision()->GetHeight(); y++)
|
||||
{
|
||||
int i = y * Collision()->GetWidth() + x;
|
||||
int Tele = Collision()->TeleLayer()[i].m_Number;
|
||||
if(Number == Tele)
|
||||
{
|
||||
Match++;
|
||||
if(Offset != -1)
|
||||
{
|
||||
if(Match == Offset)
|
||||
{
|
||||
MatchPos = ivec2(x, y);
|
||||
m_GotoTeleOffset = Match;
|
||||
return;
|
||||
if((size_t)Offset >= NumTeles || Offset < 0)
|
||||
Offset = 0;
|
||||
MatchPos = ivec2(Collision()->TeleAllGet(Number, Offset).x / 32, Collision()->TeleAllGet(Number, Offset).y / 32);
|
||||
m_GotoTeleOffset = Offset;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
MatchPos = ivec2(x, y);
|
||||
if(m_GotoTeleLastPos != ivec2(-1, -1))
|
||||
else
|
||||
{
|
||||
if(distance(m_GotoTeleLastPos, MatchPos) < 10.0f)
|
||||
bool FullRound = false;
|
||||
do
|
||||
{
|
||||
MatchPos = ivec2(Collision()->TeleAllGet(Number, m_GotoTeleOffset).x / 32, Collision()->TeleAllGet(Number, m_GotoTeleOffset).y / 32);
|
||||
m_GotoTeleOffset++;
|
||||
continue;
|
||||
if((size_t)m_GotoTeleOffset >= NumTeles)
|
||||
{
|
||||
m_GotoTeleOffset = 0;
|
||||
if(FullRound)
|
||||
{
|
||||
MatchPos = m_GotoTeleLastPos;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
FullRound = true;
|
||||
}
|
||||
}
|
||||
m_GotoTeleLastPos = MatchPos;
|
||||
if(Match == m_GotoTeleOffset)
|
||||
return;
|
||||
} while(distance(m_GotoTeleLastPos, MatchPos) < 10.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
FindTile();
|
||||
|
||||
if(MatchPos == ivec2(-1, -1))
|
||||
return;
|
||||
if(Match < m_GotoTeleOffset)
|
||||
m_GotoTeleOffset = -1;
|
||||
m_GotoTeleLastPos = MatchPos;
|
||||
m_GotoTeleLastNumber = Number;
|
||||
SetView(MatchPos);
|
||||
m_GotoTeleOffset++;
|
||||
}
|
||||
|
||||
void CCamera::SetZoom(float Target, int Smoothness)
|
||||
|
|
|
@ -72,6 +72,7 @@ private:
|
|||
int m_GotoTeleOffset;
|
||||
ivec2 m_GotoSwitchLastPos;
|
||||
ivec2 m_GotoTeleLastPos;
|
||||
int m_GotoTeleLastNumber = -1;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -113,6 +113,54 @@ public:
|
|||
class CLayers *Layers() { return m_pLayers; }
|
||||
int m_HighestSwitchNumber;
|
||||
|
||||
// Index all teleporter types (in, out and checkpoints)
|
||||
// as one consecutive list
|
||||
//
|
||||
// @param Number is the teleporter number (one less than what is shown in game)
|
||||
// @param Offset picks the n'th occurence of that teleporter in the map
|
||||
//
|
||||
// @return The coordinates of the teleporter in the map
|
||||
// or (-1, -1) if not found
|
||||
vec2 TeleAllGet(int Number, size_t Offset)
|
||||
{
|
||||
if(m_TeleIns.count(Number) > 0)
|
||||
{
|
||||
if(m_TeleIns[Number].size() > Offset)
|
||||
return m_TeleIns[Number][Offset];
|
||||
else
|
||||
Offset -= m_TeleIns[Number].size();
|
||||
}
|
||||
if(m_TeleOuts.count(Number) > 0)
|
||||
{
|
||||
if(m_TeleOuts[Number].size() > Offset)
|
||||
return m_TeleOuts[Number][Offset];
|
||||
else
|
||||
Offset -= m_TeleOuts[Number].size();
|
||||
}
|
||||
if(m_TeleCheckOuts.count(Number) > 0)
|
||||
{
|
||||
if(m_TeleCheckOuts[Number].size() > Offset)
|
||||
return m_TeleCheckOuts[Number][Offset];
|
||||
else
|
||||
Offset -= m_TeleCheckOuts[Number].size();
|
||||
}
|
||||
return vec2(-1, -1);
|
||||
}
|
||||
|
||||
// @param Number is the teleporter number (one less than what is shown in game)
|
||||
// @return The amount of occurences of that teleporter across all types (in, out, checkpoint)
|
||||
size_t TeleAllSize(int Number)
|
||||
{
|
||||
size_t Total = 0;
|
||||
if(m_TeleIns.count(Number) > 0)
|
||||
Total += m_TeleIns[Number].size();
|
||||
if(m_TeleOuts.count(Number) > 0)
|
||||
Total += m_TeleOuts[Number].size();
|
||||
if(m_TeleCheckOuts.count(Number) > 0)
|
||||
Total += m_TeleCheckOuts[Number].size();
|
||||
return Total;
|
||||
}
|
||||
|
||||
const std::vector<vec2> &TeleIns(int Number) { return m_TeleIns[Number]; }
|
||||
const std::vector<vec2> &TeleOuts(int Number) { return m_TeleOuts[Number]; }
|
||||
const std::vector<vec2> &TeleCheckOuts(int Number) { return m_TeleCheckOuts[Number]; }
|
||||
|
|
Loading…
Reference in a new issue