From 6cbc85f2292d5b8207f60ec375ae56e4d84309d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 5 May 2024 22:16:34 +0200 Subject: [PATCH] Fix smoke particles sometimes being stuck inside solid tiles Nudge the initial position for explosions' smoke particles slightly towards the edge of the closest non-solid tile, if it would otherwise be inside a solid tile, so the smoke particles do not get stuck inside solid tiles on explosion events happening at the edges of tiles but slightly inside them. The physical position of the explosion event is unchanged, so this does not affect physics. The explosion sprite is still rendered at the physical position of the explosion, to preserve the apprearance. --- src/game/client/components/effects.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/game/client/components/effects.cpp b/src/game/client/components/effects.cpp index 7f9d364d1..f3b38db8c 100644 --- a/src/game/client/components/effects.cpp +++ b/src/game/client/components/effects.cpp @@ -257,6 +257,28 @@ void CEffects::Explosion(vec2 Pos, float Alpha) p.m_StartAlpha = Alpha; m_pClient->m_Particles.Add(CParticles::GROUP_EXPLOSIONS, &p); + // Nudge position slightly to edge of closest tile so the + // smoke doesn't get stuck inside the tile. + if(Collision()->CheckPoint(Pos)) + { + const vec2 DistanceToTopLeft = Pos - vec2(round_truncate(Pos.x / 32), round_truncate(Pos.y / 32)) * 32; + + vec2 CheckOffset; + CheckOffset.x = (DistanceToTopLeft.x > 16 ? 32 : -1); + CheckOffset.y = (DistanceToTopLeft.y > 16 ? 32 : -1); + CheckOffset -= DistanceToTopLeft; + + for(vec2 Mask : {vec2(1.0f, 0.0f), vec2(0.0f, 1.0f), vec2(1.0f, 1.0f)}) + { + const vec2 NewPos = Pos + CheckOffset * Mask; + if(!Collision()->CheckPoint(NewPos)) + { + Pos = NewPos; + break; + } + } + } + // add the smoke for(int i = 0; i < 24; i++) {