Beispiel #1
0
class Player:
    def __init__(self, x, y, width, height, img, rotation):
        self.x = x
        self.y = y
        self.vel = 15
        self.width = width
        self.height = height
        self.img = img
        self.rotation = rotation

    def draw(self, win):
        # think it is wrong here
        img = pygame.image.load(self.img)
        img = pygame.transform.scale(img, (self.width, self.height))
        img = pygame.transform.rotate(img, self.rotation)
        win.blit(img, (self.x, self.y))

    # skal ikke have win
    def move(self, win):
        self.l = Laser(self.x, self.y)
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            self.x -= self.vel
        if keys[pygame.K_RIGHT]:
            self.x += self.vel
        if keys[pygame.K_SPACE]:
            print('presesd space')
            self.l.draw(win)
            # if keys[pygame.K_UP]:
            #     print('Key_UP')
            #     l.draw(win)
        self.update(win)

    def update(self, win):
        img = pygame.image.load(self.img)
        img = pygame.transform.scale(img, (self.width, self.height))
        img = pygame.transform.rotate(img, self.rotation)
        win.blit(img, (self.x, self.y))
Beispiel #2
0
class Ship():
    """The ship class encapsulates absolute coordinates (x, y) of the
    upper-left corner, image, bitmask for collision detection, vertical
    speed, moving and shooting status, ship status itself, laser and
    jets objects."""
    def __init__(self, scr, view_point, explosions):
        """Input parameters:
        scr - Surface for drawing;
        view_point - ViewPoint class instance;
        explosions - Explosions class instance for ship destroying."""
        self.scr = scr
        self.view_pt = view_point
        self.explosions = explosions
        self.image = pygame.image.load(f'img/{SHIP_FILE}')
        self.mask = pygame.mask.from_surface(self.image)
        self.rect = self.image.get_rect()
        self.x = -(self.rect.width / 2)
        self.y = self.rect.height
        self._update_rect()
        self.laser = Laser(self.scr, self.view_pt)
        self._update_laser_pos()
        self.jet_image = pygame.image.load(f'img/{JET_FILE}')
        self.jets = {
            'left':
            AnimatedSprite(self.jet_image,
                           self.scr,
                           self.view_pt,
                           JET_FRAME_COLS,
                           JET_FRAME_ROWS,
                           reverse=True),
            'right':
            AnimatedSprite(self.jet_image,
                           self.scr,
                           self.view_pt,
                           JET_FRAME_COLS,
                           JET_FRAME_ROWS,
                           reverse=True),
        }
        self._update_jets_pos()
        self.speed = 0
        self._reset_user_control()
        self.status = STATUS_NORMAL
        self._reset_progress()

    def _reset_user_control(self):
        self.moving_up = False
        self.moving_down = False
        self.moving_left = False
        self.moving_right = False
        self.shooting = False

    def _reset_progress(self):
        # Ship destructive explosion is continuous process which status
        # keeps self.progress attribute
        self.progress = 0
        # Keeps key points of the progress where explosions must be created
        self.key_frames = []

    def _update_laser_pos(self):
        self.laser.set_origin(self.x + (self.rect.width / 2) + LASER_OFFSET_X,
                              self.y - LASER_OFFSET_Y)

    def _update_rect(self):
        self.rect.x = self.view_pt.x_to_scr(self.x)
        self.rect.y = self.view_pt.y_to_scr(self.y)

    def get_center(self):
        """Returns point (x, y) with absolute ship center coordinates."""
        return (self.x + self.rect.width / 2, self.y - self.rect.height / 2)

    def update(self):
        """Call before any collision detection, drawing ship, etc."""
        full_speed = self.speed + self.acceleration * (self.y**1.2)

        if self.status in (STATUS_NORMAL, STATUS_RESTORING, STATUS_AUTO):
            self.y += full_speed

        if self.status == STATUS_NORMAL and self.shooting:
            self.laser.shoot()

        if self.status == STATUS_NORMAL or self.status == STATUS_RESTORING:
            if self.moving_left:
                self.x -= SHIP_MOVEMENT
            if self.moving_right:
                self.x += SHIP_MOVEMENT
            if self.acceleration == 0:
                # Don't move vertically if acceleration > 0
                if self.moving_up:
                    self.y += SHIP_MOVEMENT
                if self.moving_down:
                    self.y -= SHIP_MOVEMENT

        if self.status == STATUS_EXPLODING:
            self.progress += 1
            if self.progress in self.key_frames:
                self._add_explosion()
            if self.progress >= PROGRESS_MAX:
                self._add_explosion(
                    self.rect.center,
                    explosion_ind=explosions.DOUBLE_EXPLOSION_IND)
                self._reset_progress()
                self.status = STATUS_INACTIVE

        if self.status == STATUS_RESTORING:
            self.progress += 1
            if self.progress >= PROGRESS_MAX:
                self._reset_progress()
                self.status = STATUS_NORMAL

        self.view_pt.set_speed(full_speed)
        self.view_pt.set_trace_point(self.get_center())
        self._update_rect()
        self._update_laser_pos()
        self.laser.update()
        self._update_jets_pos()

    def set_speed(self, speed):
        self.speed = speed

    def set_acceleration(self, acceleration):
        self.acceleration = acceleration

    def _update_jets_pos(self):
        bottom = self.y - self.rect.height
        centerx = self.x + (self.rect.width - self.jets['left'].rect.width) / 2

        self.jets['left'].x = centerx - JET_OFFSET_X
        self.jets['right'].x = centerx + JET_OFFSET_X
        self.jets['left'].y = bottom - JET_OFFSET_Y
        self.jets['right'].y = bottom - JET_OFFSET_Y

        self.jets['left'].update()
        self.jets['right'].update()

    def is_visible(self):
        """This method helps with implementing 'blinking' effect."""
        if self.status == STATUS_INACTIVE:
            return False
        elif self.status == STATUS_EXPLODING:
            return (self.progress % int(self.progress / 10 + 1)) == 0
        elif self.status == STATUS_RESTORING:
            return ((self.progress // BLINKING_GAP) % 2) == 0
        else:
            #At this point self.status in [STATUS_NORMAL, STATUS_AUTO]
            return True

    def draw(self):
        if self.is_visible():
            self.laser.draw()
            for jet in self.jets.values():
                jet.draw()
                jet.next_frame()
            self.scr.blit(self.image, self.rect)

    def _add_explosion(self, point=None, explosion_ind=None):
        """If specified - point parameter contains screen coordinates
        of explosion."""
        if point:
            x = self.view_pt.scr_to_x(point[0])
            y = self.view_pt.scr_to_y(point[1])
        else:
            x = self.view_pt.scr_to_x(randint(self.rect.left, self.rect.right))
            y = self.view_pt.scr_to_y(randint(self.rect.top, self.rect.bottom))

        if explosion_ind:
            self.explosions.add(x, y, explosion_ind)
        else:
            self.explosions.add(x, y)

    def explode(self, collide_point=None):
        """Starts ship explosion process. If specified collide_point
        has absolute coordinates of destructive collision."""
        if self.status != STATUS_NORMAL:
            return False

        get_sound_box().play_multi_explosion()
        self.status = STATUS_EXPLODING
        self._reset_progress()
        self._add_explosion()
        if collide_point:
            self.explosions.add(collide_point[0], collide_point[1],
                                explosions.SMALL_EXPLOSION_IND)

        for i in range(EXPLOSIONS_MAX - 1):
            self.key_frames.append(randint(1, PROGRESS_MAX - 1))

        return True

    def set_autopilot(self):
        """Imperatively disables player control of the ship.
        The only way to return the control is to call restore()."""
        self.status = STATUS_AUTO

    def set_center(self, center_x, center_y):
        """Sets the absolute center coordinates of the ship."""
        self.x = center_x - (self.rect.width / 2)
        self.y = center_y + (self.rect.height / 2)
        self._update_rect()

    def restore(self, center_point=None, reset_control=False):
        """Restores ship after destruction or just assigning special
        'restoring' status (blinking and temporary invincibility).
        Input parameters:
        center_point - new absolute coordinates of the ship
        (no changing position if None);
        reset_control - if True then stops moving left/right/up/down
        and shooting; useful to avoid glitch when game level starts."""
        if self.status not in [STATUS_NORMAL, STATUS_INACTIVE, STATUS_AUTO]:
            return False

        self.status = STATUS_RESTORING
        self._reset_progress()
        if reset_control:
            self._reset_user_control()
        if center_point:
            self.set_center(center_point[0], center_point[1])

        return True
Beispiel #3
0
class RocketShip(Player):
    def __init__(self, FPS, x, y, sprite, spriteLaser):
        Player.__init__(self, x, y, sprite)
        
        self.soundLaser = pygame.mixer.Sound(os.path.join("sounds", "laser.ogg"))
        self.soundLaser.set_volume(0.5)
        
        self.leftCTRL_UP = False
        
        # the player can only have 1 laser active, so one 1 is every created. 
        self.laser = Laser(self.x, self.y - self.spriteCentre.height / 2, spriteLaser)
        
        self.score = 0
        # player will start game alive
        self.alive = True
        self.lives = 2
        
        # every time a screen is cleared this will be incremented. 
        # this effects how many galaxians can dive at once and the time delay between galaxians launching.
        self.level = 0
        
        # wait 4 seconds to reinitialise the player or decide the game is over
        self.waitTime = FPS * 4
        # this timer is only decremented once the player is NOT alive
        self.waitTimer = self.waitTime
        
        self.spriteLife = pygame.image.load(os.path.join("images", "rocketShipLife.png")).convert_alpha()
        self.spriteLifeRect = self.spriteLife.get_rect()
        
        
        
    def move(self, gal, screenWidth):
        # updates the sprite and hit rectangle
        Player.move(self)
        
        if self.alive:
            userInput = pygame.key.get_pressed()
            if userInput[pygame.K_LEFT] and self.alive:
                self.x -= 3
            if userInput[pygame.K_RIGHT] and self.alive:
                self.x += 3
            if userInput[pygame.K_LCTRL] and self.leftCTRL_UP and not self.laser.active:
                self.laser.active = True
                self.soundLaser.play()
            
            # stop the player moving off the screen
            self.x = limits(self.x, 0, screenWidth, self.spriteCentre.width / 2)
            
            # prevents auto fire
            self.leftCTRL_UP = not userInput[pygame.K_LCTRL]
            
            # update the laser, regardless if it is active or not
            self.laser.move(self.x, gal)
            
            # game is not over, return false
            return False
        
        else:
            self.sprite = self.spriteBlank
            
            if self.laser.active:
                self.laser.move(self.x, gal)
            else:
                # just keep it out of sight for now
                self.laser.sprite = self.laser.spriteBlank
            
            state = States()
            # wait until all galaxians are back in formation before setting the player back up
            for f in range(len(gal)):
                if not gal[f].state == state.FORMATION:
                    # the players lives might be < 0, but return false until all galaxians are back in formation
                    return False
            
            
            if self.waitTimer > 0:
                self.waitTimer -= 1
                
            
            if self.waitTimer == 0:
                self.lives -= 1
                if self.lives >= 0:
                    self.alive = True
                    self.x = screenWidth / 2
                    self.laser.x = self.x
                    self.waitTimer = self.waitTime
                    self.sprite = self.spriteStart
                    self.laser.sprite = self.laser.spriteStart
                    # player still has lives
                    return False
                else:
                    # game over now!
                    return True
                
    

    def draw(self, window, screenHeight):
        Player.draw(self, window)
        self.laser.draw(window)
        
        for f in range(self.lives):
            window.blit(self.spriteLife, (10 + f * (self.spriteLifeRect.width + 5), 
                                            screenHeight - self.spriteLifeRect.height))