Commit 823d67c9 authored by talljosh's avatar talljosh
Browse files

Update.

parent e36ebb9e31ce
......@@ -5,7 +5,7 @@ PLAYERS_PER_TEAM = 10
class Tick:
def __init__(self, start):
self.starts = {'build buckets': start}
self.starts = {}
self.times = {}
self.check_collision_time = Averager()
self.send_message_time = Averager()
......@@ -55,13 +55,13 @@ with open(f'profile-data-{PLAYERS_PER_TEAM}v{PLAYERS_PER_TEAM}.bin', 'rb') as f:
ticks = []
current_tick = None
for now, enter, label in data:
if (enter, label) == (True, 'build buckets'):
if (enter, label) == (True, 'start-tick'):
current_tick = Tick(now)
ticks.append(current_tick)
else:
current_tick.note(now, enter, label)
current_tick.note(now, enter, label)
interesting = 'buckets+75', 'buckets+100', 'buckets+125', 'nothing'
times_by_shots = {}
for tick in ticks:
if tick.suspect:
......@@ -69,19 +69,13 @@ for tick in ticks:
continue
if tick.shot_count not in times_by_shots:
times_by_shots[tick.shot_count] = (
Averager(), Averager(), Averager(), Averager(), Averager(), Averager())
bb, bt, gt, nt, bct, gct = times_by_shots[tick.shot_count]
bb.note(tick.times['build buckets'])
bt.note(tick.times['build buckets'] + tick.times['apply buckets'])
bct.note(tick.times.get('apply buckets+check_collision', 0))
gt.note(tick.times['gradients'])
gct.note(tick.times.get('gradients+check_collision', 0))
nt.note(tick.times['nothing'])
times_by_shots[tick.shot_count] = tuple(Averager() for i in interesting)
for i, thing in enumerate(interesting):
times_by_shots[tick.shot_count][i].note(tick.times[thing])
with open('profile-data.csv', 'w') as f:
f.write('Active shots,Buckets,Gradients,Nothing,Build buckets,Buckets check,Gradients check\n')
for shot_count, (bb, bt, gt, nt, bct, gct) in times_by_shots.items():
f.write(f'{shot_count},{bt.get()},{gt.get()},{nt.get()},'
f'{bb.get()},{bct.get()},{gct.get()}\n')
f.write('Active shots,' + ','.join(str(bit) for bit in interesting) + '\n')
for shot_count, bits in times_by_shots.items():
f.write(f'{shot_count},' + ','.join(str(a.get()) for a in bits) + '\n')
......@@ -1553,7 +1553,7 @@ class ServerUniverse(Universe):
self.activeAchievementCategories = set()
self.jitterLogger = JitterLogger(20)
self.sentGraceTick = False
self.interaction_detector = InteractionDetector(self)
self.interaction_detectors = [InteractionDetector(self, r) for r in (75,100,125)]
if PROFILE_LONG_TICKS:
self.long_tick_profiler = LongTickProfiler()
else:
......@@ -1650,9 +1650,15 @@ class ServerUniverse(Universe):
def advanceEverything(self):
from trosnoth.main import profiler
super(ServerUniverse, self).advanceEverything()
self.interaction_detector.process_collisions()
with profiler.note('gradients'):
self.checkShotCollisions()
with profiler.note('start-tick'):
pass
for shot in list(self.shots):
with profiler.note('single shot'):
pass
for i in self.interaction_detectors:
i.process_collisions()
# with profiler.note('gradients'):
# self.checkShotCollisions()
with profiler.note('nothing'):
self.check_collisions_boring()
self.updateCollectableCoins()
......@@ -1710,55 +1716,54 @@ class ServerUniverse(Universe):
'''
from trosnoth.main import profiler
for shot in list(self.shots):
with profiler.note('single shot'):
delta = ((shot.oldPos[0] - shot.pos[0])**2 + (shot.oldPos[1] - shot.pos[1])**2)**0.5
radius = shot.gun_type.shot_radius
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.grace_players):
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.check_collision(p)]
delta = ((shot.oldPos[0] - shot.pos[0])**2 + (shot.oldPos[1] - shot.pos[1])**2)**0.5
radius = shot.gun_type.shot_radius
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.grace_players):
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.check_collision(p)]
def updateCollectableCoins(self):
try:
......@@ -1995,13 +2000,12 @@ class InteractionDetector:
from trosnoth.main import profiler
# Divide the live players into buckets so each unit only needs
# to consider nearby players.
with profiler.note('build buckets'):
with profiler.note(f'buckets+{self.resolution}'):
buckets = Buckets(self.resolution)
for player in self.world.players:
if not player.dead:
buckets.add(player.pos, player)
with profiler.note('apply buckets'):
for unit in self.get_interacting_units():
affects = [
p for p in buckets.get(unit.oldPos, unit.pos, buffer=50)
......@@ -2015,11 +2019,15 @@ class InteractionDetector:
class Buckets:
def __init__(self, resolution):
self.resolution = resolution
self.buckets = defaultdict(set)
self.buckets = {}
def add(self, pos, thing):
x, y = pos
self.buckets[x // self.resolution, y // self.resolution].add(thing)
key = x // self.resolution, y // self.resolution
if key in self.buckets:
self.buckets[key].add(thing)
else:
self.buckets[key] = {thing}
def get(self, *points, buffer=0):
'''
......@@ -2033,7 +2041,9 @@ class Buckets:
for i in range(int(min_x / self.resolution), int(max_x // self.resolution) + 1):
for j in range(int(min_y // self.resolution), int(max_y // self.resolution) + 1):
yield from self.buckets[i, j]
key = i, j
if key in self.buckets:
yield from self.buckets[key]
class Region(object):
......
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