Akhil Anand Sirra
Akhil Anand Sirra

Reputation: 59

Enemies follows the player in middle

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

Answers (1)

Rabbid76
Rabbid76

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

Related Questions