Reputation: 59
The enemies spawn above the screen and try to follow the player in the middle of the screen but when it gets near the player the game crashes with a error instead of a game over.
How do I pass the player coordinates in enemies class update() method instead of 600,325 i.e. height, width respectively of the window.
I want to make enemies to follow the player and spawn the enemies around random place outside the player rather from only above the screen, also how to increase the enemies as score increases.
The error I get is:
dirvect.normalize()
ValueError: Can't normalize Vector of length Zero
The below code is of class enemy:
class Mob(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = pg.image.load('enemy.png').convert_alpha()
self.image = pg.transform.smoothscale(pg.image.load('enemy.png'), (33, 33))
self.image_orig = self.image.copy()
self.radius = int(29 * .80 / 2)
self.rect = self.image.get_rect()
self.rect.x = random.randrange(width - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.speed = 4
self.rot = 0
self.rot_speed = 5
self.last_update = pg.time.get_ticks()
def rotate(self):
now = pg.time.get_ticks()
if now - self.last_update > 50:
self.last_update = now
self.rot = (self.rot + self.rot_speed) % 360
new_image = pg.transform.rotozoom(self.image_orig, self.rot, 1)
old_center = self.rect.center
self.image = new_image
self.rect = self.image.get_rect()
self.rect.center = old_center
def update(self):
self.rotate()
dirvect = pg.math.Vector2(600 - self.rect.x,
325 - self.rect.y)
dirvect.normalize()
# Move along this normalized vector towards the player at current speed.
dirvect.scale_to_length(self.speed)
self.rect.move_ip(dirvect)
if self.rect.top > height + 10 or self.rect.left < -25 or self.rect.right > width + 20:
self.rect.x = random.randrange(width - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.speed = random.randrange(1, 4)
The below is for adding enemies:
for i in range(5):
m = Mob()
all_sprites.add(m)
mobs.add(m)
score = 0
If this helps the code of player class:
class Rotator(pg.sprite.Sprite):
def __init__(self, screen_rect):
pg.sprite.Sprite.__init__(self)
self.screen_rect = screen_rect
self.master_image = pg.image.load('spaceship.png').convert_alpha()
self.master_image = pg.transform.smoothscale(pg.image.load('spaceship.png'), (33, 33))
self.radius = 12
self.image = self.master_image.copy()
self.rect = self.image.get_rect(center=[width / 2, height / 2])
self.delay = 10
self.timer = 0.0
self.angle = 0
self.distance = 0
self.angle_offset = 0
def get_angle(self):
mouse = pg.mouse.get_pos()
offset = (self.rect.centerx - mouse[0], self.rect.centery - mouse[1])
self.angle = math.degrees(math.atan2(*offset)) - self.angle_offset
old_center = self.rect.center
self.image = pg.transform.rotozoom(self.master_image, self.angle, 1)
self.rect = self.image.get_rect(center=old_center)
self.distance = math.sqrt((offset[0] * offset[0]) + (offset[1] * offset[1]))
def update(self):
self.get_angle()
self.display = 'angle:{:.2f} distance:{:.2f}'.format(self.angle, self.distance)
self.dx = 1
self.dy = 1
self.rect.clamp_ip(self.screen_rect)
def draw(self, surf):
surf.blit(self.image, self.rect)
def shoot(self, mousepos):
dx = mousepos[0] - self.rect.centerx
dy = mousepos[1] - self.rect.centery
if abs(dx) > 0 or abs(dy) > 0:
bullet = Bullet(self.rect.centerx, self.rect.centery, dx, dy)
all_sprites.add(bullet)
bullets.add(bullet)
Upvotes: 1
Views: 352
Reputation: 211220
This error is cause, because the length of dirvect
is zero. Note, the length of a Unit vector is 1 and a unit vector is calculated by dividing the vector by its length.
Check the length of the vector before calculating the unit vector. Use length_squared()
to get the squared Euclidean length of the vector, this is faster then getting the length by lenght()
, because the expensive square root operation is omitted:
if vectdirvect.length_squared() > 0:
vectdirvect = vectdirvect.normalize()
Further note, that normalize()
calculates the unit vector, but it doesn't store the result to "itself", it returns the result by the return value.
A similar issue happens when you use scale_to_length()
, because scale_to_length()
has to calculate the unit vector first, before it can scale the vector to a given length:
if dirvect.length_squared() > 0:
dirvect.scale_to_length(self.speed)
Upvotes: 0