Ejemplo n.º 1
0
class Bullet(Entity):
    """Base bullet class which handles movement and removal of bullets.

    Arguments:
        groups (pygame.sprite.Group): All the groups this entity will be in.

    Attributes:
        dirty (int): Wether or not the sprite should be drawn.
    """
    explosion = Animation(SpriteSheet.animation(BULLET_COLLISION, 1), 0.3)

    def __init__(self, *groups):
        super().__init__(*groups)
        self.dirty = 2
        self._collision = copy(self.explosion)

    def update(self, seconds_elapsed):
        """Update the bullets position on the display."""
        super().update(seconds_elapsed)
        self.rect.y += int(self._seconds_elapsed * self._velocity.y)

    def take_damage(self, bullets, *groups):
        """Check to see if there are any bullets in contact with each other.
        If any are destroy them both and create a collision explosion.

        Arguments:
            bullets (pygame.sprite.Group): The group of bullets.
            groups (pygame.sprite.Group): The groups the explosion will be in.
        """
        for bullet in bullets:
            if bullet is not self and pygame.sprite.collide_mask(self, bullet):
                bullet.kill()
                self.kill()
                Explosion(self._collision,
                          (self.rect.x - BULLET_COLLISION.width / 2,
                           self.rect.y - BULLET_COLLISION.height / 2), *groups)
Ejemplo n.º 2
0
class Tank(Entity):
    """The tank which the user controls to destroy the oncoming alien horde.

    Arguments:
        groups (pygame.sprite.Group): All the groups this entity will be in.

    Attributes:
        tank (pygame.Surface): The default sprite for the tank.
        bullet (pygame.Surface): The tanks bullet sprite.
        explosion (pygame.Surface): The tanks explosion animation.
        image (pygame.Surface): The current image which represents the sprite.
        rect (pygame.Rect): The rect used for placing the sprite.
        mask (pygame.mask.Mask): The mast for the image.
        _velocity (pygame.math.Vector2): The x, y velocities for the sprite.
        _last_shot (float): The last time that the tank fired a shot.
        _reload_speed (float): The amount of time it takes to reload.
        _current_time (float): Time in seconds. (Used for time based actions)
    """
    tank = SpriteSheet.sprite(TANK)
    bullet = SpriteSheet.sprite(TANK_BULLET)
    explosion = Animation(SpriteSheet.animation(TANK_EXPLOSION, 1), 0.3)
    bullet_explosion = Animation(
        SpriteSheet.animation(TANK_BULLET_EXPLOSION, 1), 0.3)

    def __init__(self, position, *groups):
        super().__init__(*groups)
        self.image = copy(self.tank).convert_alpha()
        self.rect = self.image.get_rect()
        self.mask = pygame.mask.from_surface(self.image)
        self._velocity = pygame.math.Vector2(250, 0)
        self._last_shot = 0
        self._reload_speed = 0.5
        self._current_time = self._reload_speed

        self.rect.topleft = position

    def move(self, direction):
        """Move the tank according the users input.

        Arguments:
            The direction to move the tank. left < 0 > right.
        """
        velocity = int(self._seconds_elapsed * self._velocity.x)

        if direction != 0:
            self.dirty = 1
        if direction < 0 and self.rect.left > velocity:
            self.rect.x -= velocity
        elif direction > 0 and self.rect.right < DISPLAY.height - velocity:
            self.rect.x += velocity

    def shoot(self, *groups):
        """If the tank isn't reloading then fire a shot.

        Arguments:
            groups (pygame.sprite.Group): The groups the bullet will be in.
        """
        if abs(self._last_shot - self._current_time) >= self._reload_speed:
            TankBullet(self, *groups)
            self._last_shot = self._current_time

    def take_damage(self, bullets, *groups):
        """Tank damage from any of the bullets on the display.

        Arguments:
            bullets (pygame.sprite.Group): The bullet group.
            groups (pygame.sprite.Group): The groups the explosion will be in.
        """
        for bullet in bullets:
            if pygame.sprite.collide_mask(self, bullet):
                Explosion(copy(self.explosion), (self.rect.x - 4, self.rect.y),
                          *groups)

                bullet.kill()
                self.kill()
Ejemplo n.º 3
0
class Mystery(Entity):
    """The mystery ship which flys accross the screen.

    Arguments:
        direction (int): The direction the ship will move across the screen.
        groups (pygame.sprite.Group): All the groups this entity will be in.

    Attributes:
        ship (Ship): The default image for the ship.
        explosion (Animation): The explosion animation.
        dirty (int): Wether or not to draw the entity.
        image (pygame.Surface): The sprites image.
        rect (pygame.Rect): The rect used to place the sprite.
        _explosion (Animation): The explosion animation.
    """
    ship = SpriteSheet.sprite(MYSTERY)
    explosion = Animation(SpriteSheet.animation(MYSTERY_EXPLOSION, 1), 0.3)

    def __init__(self, direction, *groups):
        super().__init__(*groups)
        self.dirty = 2
        self.image = copy(self.ship).convert_alpha()
        self.rect = self.image.get_rect()
        self.mask = pygame.mask.from_surface(self.image)
        self._explosion = copy(self.explosion)

        self.rect.y = 0 + self.rect.height

        if direction:
            self._velocity = pygame.math.Vector2(250, 0)
            self.rect.x = 0
        else:
            self._velocity = pygame.math.Vector2(-250, 0)
            self.rect.x = DISPLAY.width

    def update(self, seconds_elapsed):
        """Update the entities time based variables and update the sprites
        position.

        Arguments:
            seconds_elapsed (float): The time since the last frame was drawn.
        """
        super().update(seconds_elapsed)
        self.rect.x += int(self._seconds_elapsed * self._velocity.x)

        if not self.rect.colliderect(DISPLAY):
            self.kill()

    def take_damage(self, bullets, *groups):
        """Take any damage from the bullets on the screen. Create an explosion
        animation when the entities died.

        bullets (pygame.sprite.Group): The group containing the bullet sprites.
        groups (pygame.sprite.Group): The groups the explosion will be in.
        """
        for bullet in bullets:
            if pygame.sprite.collide_mask(self, bullet):
                Explosion(self._explosion,
                          (self.rect.x + 6, self.rect.y),
                          *groups)
                bullet.kill()
                self.kill()
Ejemplo n.º 4
0
class Ship(Entity):
    """The different types of ships that the user has to fight against.

    Arguments:
        ship_type (int): Which type of ship to create.
        position (tuple {int, int}): The positon to place the ship.
        groups (pygame.sprite.Group): The groups the ship sprite will be in.

    Attributes:
        num_ships (int): The number of ship objects.
        type_one (dict): The images and animations for ship type one.
        type_two (dict): The images and animations for ship type two.
        type_three (dict): The images and animations for ship type three.
        _ship_type (int): The type of the ship sprite.
        _animation (Animation): The sprites default animation.
        _explosion (Animation): The sprites explosion animation.
        image (pygame.Surface): The image which represents the sprite.
        rect (pygame.Rect): The rect used to place the sprite.
        mask (pygame.mask.Mask): The mask used for collision detection.
        _last_frame (float): The last time the animation was updated.
        _last_shot (float): The last time a shot was fired.
    """
    num_ships = 0

    type_one = {
        'ship':
        Animation(SpriteSheet.animation(TYPE_ONE, 2), 1, loop=True),
        'bullet':
        Animation(SpriteSheet.animation(TYPE_ONE_BULLET, 2), 0.2, loop=True),
        'explosion':
        Animation(SpriteSheet.animation(TYPE_ONE_EXPLOSION, 1), 0.3),
        'bullet_explosion':
        Animation(SpriteSheet.animation(SHIP_BULLET_EXPLOSION, 1), 0.3)
    }

    type_two = {
        'ship':
        Animation(SpriteSheet.animation(TYPE_TWO, 2), 1, loop=True),
        'bullet':
        Animation(SpriteSheet.animation(TYPE_TWO_BULLET, 10), 0.05, loop=True),
        'explosion':
        Animation(SpriteSheet.animation(TYPE_TWO_EXPLOSION, 1), 0.3),
        'bullet_explosion':
        Animation(SpriteSheet.animation(SHIP_BULLET_EXPLOSION, 1), 0.3)
    }

    type_three = {
        'ship':
        Animation(SpriteSheet.animation(TYPE_THREE, 2), 1, loop=True),
        'bullet':
        Animation(SpriteSheet.animation(TYPE_THREE_BULLET, 7), 0.05,
                  loop=True),
        'explosion':
        Animation(SpriteSheet.animation(TYPE_THREE_EXPLOSION, 1), 0.3),
        'bullet_explosion':
        Animation(SpriteSheet.animation(SHIP_BULLET_EXPLOSION, 1), 0.3)
    }

    def __init__(self, ship_type, position, *groups):
        super().__init__(*groups)
        self.__class__.num_ships += 1
        self._ship_type = ship_type

        if self.type == 1:
            self._animation = copy(self.type_one['ship'])
            self._explosion = copy(self.type_one['explosion'])
        elif self.type == 2:
            self._animation = copy(self.type_two['ship'])
            self._explosion = copy(self.type_two['explosion'])
        elif self.type == 3:
            self._animation = copy(self.type_three['ship'])
            self._explosion = copy(self.type_three['explosion'])

        self.image = self._animation.next().convert_alpha()
        self.rect = self.image.get_rect()
        self.mask = pygame.mask.from_surface(self.image)
        self._last_frame = 0
        self._reload_speed = 5
        self._last_shot = -(self._reload_speed / 2)

        self.rect.topleft = position

    @property
    def type(self):
        """Get which ship type this sprite is."""
        return self._ship_type

    def update(self, seconds_elapsed):
        """Update the sprites time based variables and if the time is right
        update the sprites animation.

        Arguments:
            seconds_elapsed (float): The time in seconds since the last frame.
        """
        super().update(seconds_elapsed)

        if abs(self._last_frame - self._current_time) >= self._animation.delay:
            self.image = self._animation.next().convert_alpha()
            self.dirty = 1
            self._last_frame = self._current_time

    def shoot(self, tank, *groups):
        """If the ship is not reloading then fire a shot at the tank.

        Arguments:
            tank (Tank): The tank the ships are shooting at.
            groups (pygame.sprite.Group): The groups the bullet will be in.
        """
        if self.rect.x >= tank.rect.x - 50 and self.rect.x <= tank.rect.x + 50:
            if abs(self._last_shot - self._current_time) >= self._reload_speed:
                ShipBullet(self, *groups)
                self._last_shot = self._current_time

    def take_damage(self, bullets, *groups):
        """Check if the ship should be destroyed.

        Arguments:
            bullets (pygame.sprite.Group): The group of bullets.
            groups (pygame.sprite.Group): The groups the explosion will be in.
        """
        for bullet in bullets:
            if pygame.sprite.collide_mask(self, bullet):
                if self._ship_type == 1:
                    Explosion(self._explosion, (self.rect.x - 10, self.rect.y),
                              *groups)
                elif self._ship_type == 2:
                    Explosion(self._explosion, (self.rect.x - 4, self.rect.y),
                              *groups)
                elif self._ship_type == 3:
                    Explosion(self._explosion, (self.rect.x - 2, self.rect.y),
                              *groups)

                bullet.kill()
                self.kill()

    def kill(self):
        """Remove the sprite from all groups and decriment the ship counter."""
        super().kill()
        self.__class__.num_ships -= 1