Reputation: 1
Hello I am currently making a tower defence game in pygame and recently in my tower class i coded in a transparent circle which depicts the towers range in which this only shows up when the player left clicks on a placed tower. When testing it out I realised for some reason when i do left click on a tower the enemy which follows a set path slows down? And the amount it slows down increases with a towers range? I'm assuming this is occuring due to the transparent circle somehow blocking the waypoints the enemy follows through but I am not sure.
This is the code used to create the circle which is inside the tower class:
self.range is just a number i set for example 200
# creates circle range around tower
self.range_img = pg.Surface((self.range * 2,self.range *2 ))
self.range_img.fill((0,0,0))
self.range_img.set_colorkey((0,0,0))
pg.draw.circle(self.range_img, "grey100",(self.range,self.range),self.range )
self.range_img.set_alpha(100)
self.range_rect = self.range_img.get_rect()
self.range_rect.center = self.rect.center
I output this then in a draw function where if a variable (which only turns true when the player left clicks on the tower) is true it does surface.blit(self.range_img,self.range_rect)
The enemies move along a set of waypoints via the move function inside the enemies own class
This uses a couple of variables being:
self.waypoints = waypoints #list containing waypoints
self.pos = Vector2(self.waypoints[0])
self.target_waypoint = 1
self.speed = 0.1
Then these values are used in the move function :
def move(self):
#define a target waypoint
if self.target_waypoint < len(self.waypoints):
self.target = Vector2(self.waypoints[self.target_waypoint])
self.movement = self.target - self.pos
else:
#enemy destoyed when reaching end
self.kill()
# distance to target
distance = self.movement.length()
# check for if the speed is more than distance need to cover
if distance >= self.speed:
self.pos += self.movement.normalize() * self.speed
print(distance)
else:
if distance != 0:
self.pos += self.movement.normalize() * distance
self.target_waypoint += 1
I then call this function through update() which i call during my main game loop
Is there anything in creating the transparent circle and displaying it that causes something to change in my move() function causing the enemies to slow down?
I tried to debug and understand what was occuring by printing the distance,speed,self.movement, self.movement.normaliza() but these values dont seem to change suddenly when i do select a tower even though the enemy does slow down still
Upvotes: -1
Views: 65
Reputation: 62
you set a range to 200, means so you creating a surface of 400x400, and set alpha to it. tranpsparent circles can be costly if you use alot of them, or if you use large sizes. and 400x400 is quite large- i realized that from a certain size, it is more efficient to create a new surface than setting alpha to a existing surface. Another thing you could consider using lru_cache or a custom made cache. so if the range does not change, why then recalculate the (huge) surface every frame? something like this:
images = {}
def get_image(range, color, alpha):
if not key in images:
# if you load it from the disk
#image = pygame.image.load(image_name).convert_alpha()
# here do costly calculations like scaling, flip,
# rotating AND set_alpha, which is quite costly
img = pg.Surface((self.range * 2,range *2 ))
img.fill((0,0,0))
img.set_colorkey((0,0,0))
pg.draw.circle(self.img, color, (range,range),range )
img.set_alpha(alpha)
# generate the key to store it:
key = (range, color, alpha)
# store to dict
images[key] = image
# finally return the generated surface
return images[key]
#and then instead of calculating all the thing be done ever frame, call:
image = get_image((range, "grey100“, 100)
if your code is not creating the surface every frame, then it is probably the blitting process. i have experienced exactly the same with transparent circles.
Means that the drawing of the tranparent circle(s) is slowing down your frame_rate, so your enemies will move slower aswell. to avoid this behaviour, you will need to implement delta_time. means that the calculation of the speed of you enemies is doen by time, not by frame. using delta_time(the time passed since the last update) the enemies will move always at the same speed, independent of the frame rate
Upvotes: -1