I am making a simple car game with Python and PyGame to experiment with neural nets and especially the NEAT algorithm. The player is supposed to drive the car through a track and must not touch the border. In order to make the neural nets "see", there are a couple of "sensors" which the net can use to get position information. They calculate the distances to the border, which is defined by a mask, in various degrees.
Works fine for a couple of cars but when 20 or more are on the track, things slow down a lot.
A part of cProfile output:
38382471 function calls in 52.762 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.001 0.001 52.762 52.762 <string>:1(<module>)
26435 0.158 0.000 1.086 0.000 cargame.py:113(draw)
26435 0.045 0.000 0.045 0.000 cargame.py:121(drawRadars)
26435 14.103 0.001 22.550 0.001 cargame.py:128(checkRadars)
26435 0.129 0.000 24.262 0.001 cargame.py:149(update)
26435 0.060 0.000 0.282 0.000 cargame.py:157(checkColliding)
273 0.001 0.000 0.011 0.000 cargame.py:169(drawOnMouse)
As far as I understand those lines, my checkRadars() is bottlenecking quite a bit. It gets called for every car (when they are updated, which happens every frame).
def checkRadars(self, mask):
xcenter, ycenter = self.rect.center
#self.radars.clear()
v = (180-180*self.blindspot)/(self.radarCount-1)
w = (90-90*self.blindspot)
# dont mind these weird calculations
for n in range(self.radarCount):
length = 1
x, y = xcenter, ycenter
rangle = v*n-w
rad = -math.radians(self.angle+rangle)
while isInBound(x, y) and not mask.get_at((x, y)) and length < 100:
length += 1
x = int(xcenter + math.sin(rad) * length)
y = int(ycenter - math.cos(rad) * length)
if length == 100:
length = length*10
I have optimized that method as far as I can, moving some calculations out of the loops, and so on, but it is still not fast enough. Lowering the length is not an option since it's already too low for my taste.