Commit a7c3a57b authored by Phedg1Studios's avatar Phedg1Studios
Browse files

Refactored bucket code.

Before:
A shot would calculate its collision approximation rectangle.
A shot would then determine if the player could be hit (invulnerable, friends etc).
A shot would then determine if the player origin was inside a circle,
    centered on the shot start position with a radius of the shot movement delta + shot radius + player radius.
A shot would then determine if the player was inside the approximation rectangle.

After:
A shot would determine if a player could be hit (invulnerable, friends etc).
A shot would determine which player origins were inside a circle,
    centered between the shot start and end positions with a radius of the shot movement delta / 2 + shot radius + player radius.
If any players were inside the circle, the shot would then calculate its collision approximation rectangle.
A shot would then determine if any circle players were inside the approximation rectangle.

Goal:
By centering the shot nearness circle inbetween the shot start position and shot end position the area of that circle is greatly reduced.
By rearranging the order of operations many of those operations are no longer performed for every shot every frame.
parent d2be5d5f0958
......@@ -652,9 +652,6 @@ class CollisionEllipse(CollisionShape):
# If the point falls within the rectangle then a more accurate function will be used elsewhere to determine if there is an actual collision
def isNearPath(self, point, startPos, endPos, radius, delta, gradients, distanceBetween, offsetCoords, axis):
largestRadius = max(self.rx, self.ry)
# Could the distance between the start and end sufficient to have reached the fixed point
if ((startPos[0] - point[0])**2 + (startPos[1] - point[1])**2)**0.5 - radius - delta - largestRadius > 0:
return False
# Is the object still
if delta == 0:
return True
......
......@@ -1676,49 +1676,54 @@ class ServerUniverse(Universe):
'''
Performs collision checks of all shots with all nearby players.
'''
largestRadius = []
for p in self.players:
playerRadius = max(p.collision_shape.rx, p.collision_shape.ry)
if not playerRadius in largestRadius:
largestRadius.append(playerRadius)
for shot in list(self.shots):
delta = ((shot.oldPos[0] - shot.pos[0])**2 + (shot.oldPos[1] - shot.pos[1])**2)**0.5
radius = shot.gun_type.shot_radius
gradients = []
distanceBetween = {}
offsetCoords = {}
axis = []
if shot.oldPos[0] != shot.pos[0] and shot.oldPos[1] != shot.pos[1]:
gradientA = (shot.pos[1] - shot.oldPos[1]) / (shot.pos[0] - shot.oldPos[0])
gradientB = -1 / gradientA
gradients = [gradientA, gradientB]
slopeA = abs(gradientA) / gradientA
slopeB = abs(gradientB) / gradientB
minPos = shot.oldPos
maxPos = shot.pos
if shot.pos[1] < shot.oldPos[1]:
minPos = shot.pos
maxPos = shot.oldPos
for playerRadius in largestRadius:
multiplierA = (playerRadius + radius) / (1 + gradientA**2)**(1/2)
multiplierB = (playerRadius + radius) / (1 + gradientB**2)**(1/2)
distanceBetween[playerRadius] = (multiplierB**2 + (gradientB * multiplierB)**2)**(1/2) * 2
adjustedPos = [[maxPos[0] + slopeA * multiplierA, maxPos[1] + abs(gradientA) * multiplierA], [minPos[0] - slopeA * multiplierA, minPos[1] - abs(gradientA) * multiplierA]]
offsetCoords[playerRadius] = [[[adjustedPos[0][0] + multiplierB, adjustedPos[0][1] + gradientB * multiplierB], [adjustedPos[1][0] + multiplierB, adjustedPos[1][1] + gradientB * multiplierB]],
[[adjustedPos[0][0] - multiplierB, adjustedPos[0][1] - gradientB * multiplierB], [adjustedPos[1][0] - multiplierB, adjustedPos[1][1] - gradientB * multiplierB]]]
if shot.oldPos[0] != shot.pos[0] or shot.oldPos[1] != shot.pos[1]:
for a in range(2):
b = (a + 1) % 2
if shot.oldPos[a] == shot.pos[a] and shot.oldPos[b] != shot.pos[b]:
axis = [a, b]
hitPlayers = [
p for p in self.players
if not (p.dead or p.is_invulnerable() and not p.isFriendsWith(shot.originatingPlayer))
and not p in shot.gracePlayers
and p.collision_shape.isNearPath(p.pos, shot.oldPos, shot.pos, radius, delta, gradients, distanceBetween, offsetCoords, axis)
and shot.checkCollision(p)]
centrePos = [shot.oldPos[0] + (shot.pos[0] - shot.oldPos[0]) / 2, shot.oldPos[1] + (shot.pos[1] - shot.oldPos[1]) / 2]
largestRadius = []
circlePlayers = []
for player in self.players:
if not (player.dead or player.is_invulnerable() and not player.isFriendsWith(shot.originatingPlayer) and not player in shot.gracePlayers):
playerRadius = max(player.collision_shape.rx, player.collision_shape.ry)
if ((centrePos[0] - player.pos[0])**2 + (centrePos[1] - player.pos[1])**2)**(1/2) - delta / 2 - radius - playerRadius <= 0:
if not playerRadius in largestRadius:
largestRadius.append(playerRadius)
circlePlayers.append(player)
hitPlayers = []
if len(largestRadius) > 0:
gradients = []
distanceBetween = {}
offsetCoords = {}
axis = []
if shot.oldPos[0] != shot.pos[0] and shot.oldPos[1] != shot.pos[1]:
gradientA = (shot.pos[1] - shot.oldPos[1]) / (shot.pos[0] - shot.oldPos[0])
gradientB = -1 / gradientA
gradients = [gradientA, gradientB]
slopeA = abs(gradientA) / gradientA
slopeB = abs(gradientB) / gradientB
minPos = shot.oldPos
maxPos = shot.pos
if shot.pos[1] < shot.oldPos[1]:
minPos = shot.pos
maxPos = shot.oldPos
for playerRadius in largestRadius:
multiplierA = (playerRadius + radius) / (1 + gradientA**2)**(1/2)
multiplierB = (playerRadius + radius) / (1 + gradientB**2)**(1/2)
distanceBetween[playerRadius] = (multiplierB**2 + (gradientB * multiplierB)**2)**(1/2) * 2
adjustedPos = [[maxPos[0] + slopeA * multiplierA, maxPos[1] + abs(gradientA) * multiplierA], [minPos[0] - slopeA * multiplierA, minPos[1] - abs(gradientA) * multiplierA]]
offsetCoords[playerRadius] = [[[adjustedPos[0][0] + multiplierB, adjustedPos[0][1] + gradientB * multiplierB], [adjustedPos[1][0] + multiplierB, adjustedPos[1][1] + gradientB * multiplierB]],
[[adjustedPos[0][0] - multiplierB, adjustedPos[0][1] - gradientB * multiplierB], [adjustedPos[1][0] - multiplierB, adjustedPos[1][1] - gradientB * multiplierB]]]
if shot.oldPos[0] != shot.pos[0] or shot.oldPos[1] != shot.pos[1]:
for a in range(2):
b = (a + 1) % 2
if shot.oldPos[a] == shot.pos[a] and shot.oldPos[b] != shot.pos[b]:
axis = [a, b]
hitPlayers = [
p for p in circlePlayers
if p.collision_shape.isNearPath(p.pos, shot.oldPos, shot.pos, radius, delta, gradients, distanceBetween, offsetCoords, axis)
and shot.checkCollision(p)]
if hitPlayers:
# If multiple players are hit in the same tick, the server
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment