예제 #1
0
class Coin(Sprite):
    """Represents a coin with an associated point value"""
    def __init__(self, x, y, screen, points=100):
        super(Coin, self).__init__()
        images = [
            'map/Coin-1.png', 'map/Coin-2.png', 'map/Coin-3.png',
            'map/Coin-4.png'
        ]
        self.animator = Animator(images)
        self.image = self.animator.get_image()
        self.rect = self.image.get_rect()
        self.rect.left, self.rect.top = x, y
        self.screen = screen
        self.points = points

    def update(self):
        """Update the coin image"""
        self.image = self.animator.get_image()

    def blit(self):
        """Blit the coin to the screen"""
        self.screen.blit(self.image, self.rect)
예제 #2
0
class Koopa(Enemy):
    def __init__(self, screen, x, y, player, floor, block, goombas, koopas):
        self.name_1, self.name_2 = None, None
        self.name_1 = Enemy.img_file('KoopaWalkLeft_1', 25, 40)
        self.name_2 = Enemy.img_file('KoopaWalkLeft_2', 25, 40)
        self.left_images = [self.name_1, self.name_2]
        self.name_1 = Enemy.img_file('KoopaWalkRight_1', 25, 40)
        self.name_2 = Enemy.img_file('KoopaWalkRight_2', 25, 40)
        self.right_images = [self.name_1, self.name_2]
        self.name_1 = Enemy.img_file('KoopaShell', 35, 30)
        self.death_images = [self.name_1]
        self.name_1 = Enemy.img_file('KoopaShellUD', 35, 30)
        self.UD_death_images = [self.name_1]
        self.name_1 = Enemy.img_file('KoopaLegs', 35, 30)
        self.feet_images = [self.name_1]
        self.animator = Animator(self.left_images)
        image = self.animator.get_image()
        super().__init__(screen, image, x, y, player, floor, block, goombas,
                         koopas)
        self.collision_flag = False
        self.feet_frame = 0
        self.counter = 0

    def upside_down_death_animation(self):
        time = pygame.time.get_ticks()
        # Animate getting hit (Go up for two seconds)
        if self.death_animation_frame == 0:
            self.rect.y += (abs(self.ENEMY_DIRECTION) * self.ENEMY_SPEED)
        else:
            self.rect.y += (abs(self.ENEMY_DIRECTION) * self.ENEMY_SPEED * -1)
        # After two seconds fall down while upside down
        if self.death_animation_frame == 0 and abs(self.last_frame -
                                                   time) > 2000:
            self.animator = Animator(self.UD_death_images)
            self.death_animation_frame += 1
        """MIGHT BE REDUNDANT WITH CHECK BOUNDARY"""
        # Kill off after 10 seconds (Enough to be off screen)
        if abs(self.last_frame - time) > 10000:
            self.player.score += 100
            self.kill()

    def update(self):
        self.koopa_physics()
        self.image = self.animator.get_image()

    def check_player_shell_collision(self):
        # Check player collision when in shell
        if self.rect.colliderect(self.player.rect):
            return True

    def koopa_physics(self):
        """USE MARIO CURRENT POSITION TO GET LEFT OF SCREEN"""
        self.check_boundary()

        if not self.check_floor() and self.start_movement:
            self.rect.y += (abs(self.ENEMY_DIRECTION) * self.ENEMY_GRAVITY)
            self.rect.x = self.rect.x + (self.ENEMY_DIRECTION *
                                         (self.ENEMY_SPEED - 1))
        if self.check_floor() and self.start_movement:
            self.rect.x = self.rect.x + (self.ENEMY_DIRECTION *
                                         self.ENEMY_SPEED)

        # If collision
        if self.check_collisions():
            # Gets stomped on -> stop
            # Collides with player when in shell -> Movement
            if self.enemy_player_collide_flag and self.shell_mode:
                time = pygame.time.get_ticks()
                # Only put in shell if needed
                if self.death_animation_frame == 0:
                    self.animator = Animator(self.death_images)
                    self.image = self.animator.get_image()
                    tempx, tempy = self.rect.x, self.rect.y
                    self.rect = self.image.get_rect()
                    self.rect.x = tempx
                    self.rect.y = tempy
                    self.death_animation_frame += 1
                # Collide with player in shell mode causes movement
                if self.check_player_shell_collision():
                    self.shell_movement = True
                # Move shell depending on which side was hit
                if self.shell_movement:
                    if self.death_animation_frame == 1:
                        # Left side was hit
                        if self.rect.x >= self.player.rect.x:
                            self.ENEMY_DIRECTION = abs(self.ENEMY_DIRECTION)
                        # Right side hit
                        else:
                            self.ENEMY_DIRECTION = abs(
                                self.ENEMY_DIRECTION) * -1
                        self.death_animation_frame += 1
                    if self.check_block_collision():
                        pass
                    self.rect.x += (self.ENEMY_DIRECTION * self.ENEMY_SPEED)
                # Not being hit by player again makes koopa pop out of shell
                if not self.check_player_shell_collision() and abs(self.last_frame - time) > 8000 and not\
                        self.shell_movement:
                    if self.counter == 0:
                        self.animator = Animator(self.feet_images)
                        self.feet_frame = pygame.time.get_ticks()
                        self.counter += 1
                    if abs(self.feet_frame - time) > 3000:
                        self.counter = 0
                        self.ENEMY_DIRECTION = abs(self.ENEMY_DIRECTION) * -1
                        self.animator = Animator(self.left_images)
                        self.enemy_player_collide_flag = False
                        self.shell_mode = False
            # Collision with map or block
            elif self.enemy_block_collide_flag:
                # Killed by player hitting block
                if self.block_enemy_kill:
                    self.dead = True
                    self.upside_down_death_animation()
                # If colliding with map (i.e. Pipe) change direction
                else:
                    self.rect.x += (self.ENEMY_DIRECTION * self.ENEMY_SPEED)
                    self.enemy_block_collide_flag = False
            # If colliding with goomba change direction
            elif self.enemy_goomba_collide_flag:
                self.rect.x += (self.ENEMY_DIRECTION * self.ENEMY_SPEED)
                self.enemy_goomba_collide_flag = False
            elif self.enemy_koopa_collide_flag:
                # Colliding with koopa shell thats moving
                if self.shell_enemy_kill:
                    self.dead = True
                    self.upside_down_death_animation()
                # Colliding with koopa enemy or shell
                else:
                    self.rect.x += (self.ENEMY_DIRECTION * self.ENEMY_SPEED)
                    self.enemy_koopa_collide_flag = False
예제 #3
0
class Goomba(Enemy):
    def __init__(self, screen, x, y, player, floor, block, goombas, koopas):
        self.walk_images = [
            'images/enemies/goomba/GoombaLeftBoot.png',
            'images/enemies/goomba/GoombaRightBoot.png'
        ]
        self.upside_down_images = [
            'images/enemies/goomba/GoombaUD1.png',
            'images/enemies/goomba/GoombaUD2.png'
        ]
        self.crushed_images = ['images/enemies/goomba/GoombaCrushed.png']
        self.animator = Animator(self.walk_images)
        image = self.animator.get_image()
        super().__init__(screen, image, x, y, player, floor, block, goombas,
                         koopas)

    def crushed_death_animation(self):
        print('ENEMY CRUSHED')
        time = pygame.time.get_ticks()
        print(str(time))
        print(str(self.last_frame))
        # Animate and keep on screen for half a second before killing sprite
        self.animator = Animator(self.crushed_images)
        if abs(time - self.last_frame) > 1000:
            self.player.score += 100
            self.kill()

    def upside_down_death_animation(self):
        time = pygame.time.get_ticks()
        # Animate getting hit (Go up for two seconds)
        if self.death_animation_frame == 0:
            self.rect.y += (abs(self.ENEMY_DIRECTION) * self.ENEMY_SPEED)
        else:
            self.rect.y += (abs(self.ENEMY_DIRECTION) * self.ENEMY_SPEED * -1)
        # After two seconds fall down while upside down
        if self.death_animation_frame == 0 and abs(self.last_frame -
                                                   time) > 2000:
            self.animator = Animator(self.upside_down_images)
            self.death_animation_frame += 1
        """MIGHT BE REDUNDANT WITH CHECK BOUNDARY"""
        # Kill off after 10 seconds (Enough to be off screen)
        if abs(self.last_frame - time) > 10000:
            self.player.score += 100
            self.kill()

    def update(self):
        if not self.dead:
            self.goomba_physics()
        else:
            if self.player_enemy_kill is True:
                self.crushed_death_animation()
            elif self.block_enemy_kill is True:
                self.upside_down_death_animation()
            elif self.shell_enemy_kill is True:
                self.upside_down_death_animation()
        self.image = self.animator.get_image()

    def goomba_physics(self):
        self.check_boundary()
        # If no blocks are touching enemy -> Fall Down
        if not self.check_floor() and self.start_movement:
            self.rect.y += (abs(self.ENEMY_DIRECTION) * self.ENEMY_GRAVITY)
            self.rect.x = self.rect.x + (self.ENEMY_DIRECTION *
                                         (self.ENEMY_SPEED - 1))
        if self.check_floor() and self.start_movement:
            self.rect.x = self.rect.x + (self.ENEMY_DIRECTION *
                                         self.ENEMY_SPEED)

        # print('Player ' + str(self.check_player_collision()))
        # print('Block ' + str(self.check_block_collision()))
        # print('Enemy' + str(self.check_friendly_collision()))

        if self.check_collisions():
            # Collides with player
            if self.enemy_player_collide_flag:
                # Enemy dead
                if self.player_enemy_kill:
                    self.dead = True
                    self.last_frame = pygame.time.get_ticks()
                    self.crushed_death_animation()
                else:
                    self.enemy_player_collide_flag = False
            # Collision with map or block
            elif self.enemy_block_collide_flag:
                # Killed by player hitting block
                if self.block_enemy_kill:
                    self.dead = True
                    self.upside_down_death_animation()
                # If colliding with map (i.e. Pipe) change direction
                else:
                    self.rect.x += (self.ENEMY_DIRECTION * self.ENEMY_SPEED)
                    self.enemy_block_collide_flag = False
            # If colliding with goomba change direction
            elif self.enemy_goomba_collide_flag:
                self.rect.x += (self.ENEMY_DIRECTION * self.ENEMY_SPEED)
                self.enemy_goomba_collide_flag = False
            # If colliding with koopa
            elif self.enemy_koopa_collide_flag:
                # Colliding with koopa shell thats moving
                if self.shell_enemy_kill:
                    self.dead = True
                    self.upside_down_death_animation()
                # Colliding with koopa enemy or shell
                else:
                    self.rect.x += (self.ENEMY_DIRECTION * self.ENEMY_SPEED)
                    self.enemy_koopa_collide_flag = False
예제 #4
0
class Item(Sprite):
    """Represents a generic item object in the mario game"""
    MUSHROOM = 'mushroom'
    ONE_UP = '1-up'
    FIRE_FLOWER = 'fire-flower'
    STARMAN = 'starman'

    def __init__(self,
                 x,
                 y,
                 image,
                 speed,
                 obstacles,
                 floor,
                 item_type,
                 rise_from=None,
                 animated=False):
        super(Item, self).__init__()
        if animated:
            self.animator = Animator(image)
            self.image = self.animator.get_image()
        else:
            self.animator = None
            self.image = image
        self.item_type = item_type
        self.rect = self.image.get_rect()
        self.rect.left, self.rect.top = x, y
        self.speed = speed
        self.jump_speed = 0
        self.obstacles = obstacles  # objects that the item may collide with
        self.floor = floor  # rects for the floor
        self.rise_from = rise_from

    def rise(self):
        """Have the item rise up from another object"""
        if not self.rise_from:
            raise ValueError(
                'Cannot rise from an object when that object is None')
        if self.rect.bottom <= self.rise_from.rect.top:
            self.rise_from = None
        else:
            self.rect.bottom -= 2

    def jump(self):
        """Have the item jump into the air"""
        if self.speed >= 0:
            self.jump_speed = -(self.speed * 5)
        else:
            self.jump_speed = (self.speed * 5)

    def flip_direction(self):
        """Flip the direction the item is moving on the x-axis"""
        self.speed = -self.speed
        self.rect.left += self.speed

    def bounce_off_obstacles(self):
        """Check if the item has hit any obstacles which cause it to bounce the other direction"""
        for obs in self.obstacles:
            pts = [
                obs.rect.bottomleft, obs.rect.midleft, obs.rect.bottomright,
                obs.rect.midright
            ]
            for pt in pts:
                if self.rect.collidepoint(pt):
                    self.flip_direction()
                    return
        for rect in self.floor:
            pts = [
                rect.midleft, rect.midright, rect.bottomleft, rect.bottomright
            ]
            y_cap = rect.top
            for pt in pts:
                if self.rect.collidepoint(pt) or \
                        ((self.rect.left == rect.right or self.rect.right == rect.left) and self.rect.top > y_cap):
                    self.flip_direction()
                    return

    def fall(self):
        """If the item is not supported by any floor rects, then fall down"""
        falling = True
        for rect in self.floor:
            # check if bottom is at the top of the floor rect and that the x pos is within floor area
            if self.rect.bottom == rect.top and (
                    rect.left < self.rect.center[0] < rect.right):
                self.rect.bottom = rect.top
                falling = False
                break
        if falling:
            for obj in self.obstacles:
                pts = [obj.rect.topleft, obj.rect.midtop, obj.rect.topright]
                for pt in pts:
                    if self.rect.collidepoint(pt):
                        falling = False
                        break
                if not falling:
                    break
        if falling:
            self.rect.bottom += abs(self.speed)

    def update(self):
        """Update the item position based on its speed variables"""
        if self.animator:
            self.image = self.animator.get_image()
        if not self.rise_from:
            if abs(self.jump_speed) > 0:
                self.rect.top += self.jump_speed
                self.jump_speed += 1  # simulate gravity reducing speed
            self.rect.left += self.speed
            self.bounce_off_obstacles()
            self.fall()
        else:
            self.rise()
예제 #5
0
class FireBall(Sprite):
    """A fireball which can be thrown from Mario when he is in his fire flower state"""
    def __init__(self,
                 x,
                 y,
                 norm_images,
                 explode_images,
                 obstacles,
                 floor,
                 goomba,
                 koopa,
                 speed=5):
        self.norm_animator = Animator(norm_images)
        self.explode_animator = Animator(explode_images, repeat=False)
        self.image = self.norm_animator.get_image()
        self.rect = self.image.get_rect()
        self.rect.x, self.rect.y = x, y
        self.obstacles = obstacles
        self.floor = floor
        self.goomba, self.koopa = goomba, koopa
        self.speed_x = speed
        self.speed_y = speed
        self.active = True
        super(FireBall, self).__init__()

    def check_hit_wall(self):
        """Check if the fireball has hit any walls"""
        for obs in self.obstacles:
            pts = [
                obs.rect.midleft, obs.rect.midright, obs.rect.bottomleft,
                obs.rect.bottomright
            ]
            for pt in pts:
                if self.rect.collidepoint(pt):
                    self.active = False
                    return
        for flr_rect in self.floor:
            pts = [
                flr_rect.midleft, flr_rect.midright, flr_rect.bottomleft,
                flr_rect.bottomright
            ]
            for pt in pts:
                if self.rect.collidepoint(pt):
                    self.active = False
                    return

    def check_hit_enemies(self):
        """Check if the fireball has hit any enemies"""
        for g_enemy in self.goomba:
            if collide_rect(
                    self,
                    g_enemy):  # FIXME: change kill() when animation works
                g_enemy.kill()
                self.active = False
                return
        for k_enemy in self.koopa:
            if collide_rect(self, k_enemy):
                k_enemy.kill()
                self.active = False
                return

    def apply_gravity(self):
        """Apply gravity to the fireball, bounce off of horizontal side of surfaces"""
        bounce = False
        for obs in self.obstacles:
            pts = [obs.rect.topleft, obs.rect.midtop, obs.rect.topright]
            for pt in pts:
                if self.rect.collidepoint(pt):
                    bounce = True
                    break
            if bounce:
                break
        if not bounce:
            for flr_rect in self.floor:
                # check if bottom is at the top of the floor rect and that the x pos is within floor area
                if self.rect.bottom >= flr_rect.top and (
                        flr_rect.left < self.rect.center[0] < flr_rect.right):
                    bounce = True
                    break
        if bounce:
            self.speed_y = -abs(
                self.speed_y)  # ensure speed in y-direction is negative
        else:
            self.speed_y += 2  # apply gravity
        self.rect.y += self.speed_y

    def update(self):
        """Update the position of the fireball"""
        if self.active:
            self.rect.x += self.speed_x
            self.apply_gravity()
            self.image = self.norm_animator.get_image()
            self.check_hit_wall()
            self.check_hit_enemies()
        elif self.explode_animator.is_animation_done():
            self.kill()
        else:
            self.image = self.explode_animator.get_image()
예제 #6
0
class QuestionBlock(CoinBlock):
    """Represents a question block which can be hit to release an item"""
    MUSHROOM = 'mushroom'
    ONE_UP = '1-up'
    FIRE_FLOWER = 'fire-flower'
    STARMAN = 'starman'

    def __init__(self,
                 x,
                 y,
                 screen,
                 map_group,
                 game_objects,
                 item=MUSHROOM,
                 static_img=None):
        if not static_img:
            images = [
                'map/Question-Block-1.png', 'map/Question-Block-2.png',
                'map/Question-Block-3.png'
            ]
            self.animator = Animator(images)
            initial_image = self.animator.get_image()
        else:
            initial_image = static_img
            self.animator = None
        self.game_objects = game_objects
        if item in (QuestionBlock.MUSHROOM, QuestionBlock.FIRE_FLOWER,
                    QuestionBlock.STARMAN, QuestionBlock.ONE_UP):
            self.item = item  # TODO: items
            coins = None
        else:
            self.item = None
            coins = 1
        super(QuestionBlock, self).__init__(x,
                                            y,
                                            initial_image,
                                            screen,
                                            map_group,
                                            coins=coins if coins else 0)
        if self.item:
            self.sound = mixer.Sound('audio/Powerup-Appear.wav')
        self.blank_img = image.load(
            'map/super-mario-empty-block.png')  # force blank image
        self.state['blank'] = False

    @classmethod
    def q_block_from_tmx_obj(cls, obj, screen, map_group, game_objects):
        """Create a question block using tmx data"""
        item_type = obj.properties.get('item', None)
        if obj.properties.get('invisible', None):
            return cls(obj.x,
                       obj.y,
                       screen,
                       map_group,
                       game_objects,
                       item_type,
                       static_img=obj.image)
        return cls(obj.x, obj.y, screen, map_group, game_objects, item_type)

    def check_hit(self, other):
        points = super(QuestionBlock, self).check_hit(other)
        if self.item and self.state['meta'] == CoinBlock.HIT_STATE:
            obstacles, floor = self.game_objects[
                'collide_objs'], self.game_objects['floors']
            if self.item == QuestionBlock.MUSHROOM and not other.state_info[
                    'big']:
                n_item = Mushroom(self.rect.x,
                                  self.rect.y,
                                  obstacles,
                                  floor,
                                  rise_from=self)
            elif self.item == QuestionBlock.ONE_UP:
                n_item = OneUp(self.rect.x,
                               self.rect.y,
                               obstacles,
                               floor,
                               rise_from=self)
            elif self.item == QuestionBlock.FIRE_FLOWER or self.item == QuestionBlock.MUSHROOM:
                n_item = FireFlower(self.rect.x,
                                    self.rect.y,
                                    obstacles,
                                    floor,
                                    rise_from=self)
            else:
                n_item = StarMan(self.rect.x,
                                 self.rect.y,
                                 obstacles,
                                 floor,
                                 rise_from=self)
            self.game_objects['items'].add(n_item)
            self.map_group.add(n_item)
            self.item = None
            self.state['blank'] = True
            self.sound.play()
        elif points:
            return points

    def update(self):
        """Update the question block to its next animated image"""
        if not self.state['blank'] and self.animator:
            self.image = self.animator.get_image()
        elif self.state['blank']:
            self.image = self.blank_img
        super(QuestionBlock, self).update()