import pygame as pg from .. import constants as c from .. import setup class Powerup(pg.sprite.Sprite): """Base class for all powerup_group""" def __init__(self, x, y): super(Powerup, self).__init__() def setup_powerup(self, x, y, name, setup_frames): """This separate setup function allows me to pass a different setup_frames method depending on what the powerup is""" self.sprite_sheet = setup.GFX['item_objects'] self.frames = [] self.frame_index = 0 setup_frames() self.image = self.frames[self.frame_index] self.rect = self.image.get_rect() self.rect.centerx = x self.rect.y = y self.state = c.REVEAL self.y_vel = -1 self.x_vel = 0 self.direction = c.RIGHT self.box_height = y self.gravity = 1 self.max_y_vel = 8 self.animate_timer = 0 self.name = name def get_image(self, x, y, width, height): """Get the image frames from the sprite sheet""" image = pg.Surface([width, height]).convert() rect = image.get_rect() image.blit(self.sprite_sheet, (0, 0), (x, y, width, height)) image.set_colorkey(c.BLACK) image = pg.transform.scale(image, (int(rect.width*c.SIZE_MULTIPLIER), int(rect.height*c.SIZE_MULTIPLIER))) return image def update(self, game_info, *args): """Updates powerup behavior""" self.current_time = game_info[c.CURRENT_TIME] self.handle_state() def handle_state(self): pass def revealing(self, *args): """Action when powerup leaves the coin box or brick""" self.rect.y += self.y_vel if self.rect.bottom <= self.box_height: self.rect.bottom = self.box_height self.y_vel = 0 self.state = c.SLIDE def sliding(self): """Action for when powerup slides along the ground""" if self.direction == c.RIGHT: self.x_vel = 3 else: self.x_vel = -3 def falling(self): """When powerups fall of a ledge""" if self.y_vel < self.max_y_vel: self.y_vel += self.gravity class Mushroom(Powerup): """Powerup that makes Mario become bigger""" def __init__(self, x, y, name='mushroom'): super(Mushroom, self).__init__(x, y) self.setup_powerup(x, y, name, self.setup_frames) def setup_frames(self): """Sets up frame list""" self.frames.append(self.get_image(0, 0, 16, 16)) def handle_state(self): """Handles behavior based on state""" if self.state == c.REVEAL: self.revealing() elif self.state == c.SLIDE: self.sliding() elif self.state == c.FALL: self.falling() class LifeMushroom(Mushroom): """1up mushroom""" def __init__(self, x, y, name='1up_mushroom'): super(LifeMushroom, self).__init__(x, y) self.setup_powerup(x, y, name, self.setup_frames) def setup_frames(self): self.frames.append(self.get_image(16, 0, 16, 16)) class FireFlower(Powerup): """Powerup that allows Mario to throw fire balls""" def __init__(self, x, y, name=c.FIREFLOWER): super(FireFlower, self).__init__(x, y) self.setup_powerup(x, y, name, self.setup_frames) def setup_frames(self): """Sets up frame list""" self.frames.append( self.get_image(0, 32, 16, 16)) self.frames.append( self.get_image(16, 32, 16, 16)) self.frames.append( self.get_image(32, 32, 16, 16)) self.frames.append( self.get_image(48, 32, 16, 16)) def handle_state(self): """Handle behavior based on state""" if self.state == c.REVEAL: self.revealing() elif self.state == c.RESTING: self.resting() def revealing(self): """Animation of flower coming out of box""" self.rect.y += self.y_vel if self.rect.bottom <= self.box_height: self.rect.bottom = self.box_height self.state = c.RESTING self.animation() def resting(self): """Fire Flower staying still on opened box""" self.animation() def animation(self): """Method to make the Fire Flower blink""" if (self.current_time - self.animate_timer) > 30: if self.frame_index < 3: self.frame_index += 1 else: self.frame_index = 0 self.image = self.frames[self.frame_index] self.animate_timer = self.current_time class Star(Powerup): """A powerup that gives mario invincibility""" def __init__(self, x, y, name='star'): super(Star, self).__init__(x, y) self.setup_powerup(x, y, name, self.setup_frames) self.animate_timer = 0 self.rect.y += 1 #looks more centered offset one pixel self.gravity = .4 def setup_frames(self): """Creating the self.frames list where the images for the animation are stored""" self.frames.append(self.get_image(1, 48, 15, 16)) self.frames.append(self.get_image(17, 48, 15, 16)) self.frames.append(self.get_image(33, 48, 15, 16)) self.frames.append(self.get_image(49, 48, 15, 16)) def handle_state(self): """Handles behavior based on state""" if self.state == c.REVEAL: self.revealing() elif self.state == c.BOUNCE: self.bouncing() def revealing(self): """When the star comes out of the box""" self.rect.y += self.y_vel if self.rect.bottom <= self.box_height: self.rect.bottom = self.box_height self.start_bounce(-2) self.state = c.BOUNCE self.animation() def animation(self): """sets image for animation""" if (self.current_time - self.animate_timer) > 30: if self.frame_index < 3: self.frame_index += 1 else: self.frame_index = 0 self.animate_timer = self.current_time self.image = self.frames[self.frame_index] def start_bounce(self, vel): """Transitions into bouncing state""" self.y_vel = vel def bouncing(self): """Action when the star is bouncing around""" self.animation() if self.direction == c.LEFT: self.x_vel = -5 else: self.x_vel = 5 class FireBall(pg.sprite.Sprite): """Shot from Fire Mario""" def __init__(self, x, y, facing_right, name=c.FIREBALL): super(FireBall, self).__init__() self.sprite_sheet = setup.GFX['item_objects'] self.setup_frames() if facing_right: self.direction = c.RIGHT self.x_vel = 12 else: self.direction = c.LEFT self.x_vel = -12 self.y_vel = 10 self.gravity = .9 self.frame_index = 0 self.animation_timer = 0 self.state = c.FLYING self.image = self.frames[self.frame_index] self.rect = self.image.get_rect() self.rect.right = x self.rect.y = y self.name = name def setup_frames(self): """Sets up animation frames""" self.frames = [] self.frames.append( self.get_image(96, 144, 8, 8)) #Frame 1 of flying self.frames.append( self.get_image(104, 144, 8, 8)) #Frame 2 of Flying self.frames.append( self.get_image(96, 152, 8, 8)) #Frame 3 of Flying self.frames.append( self.get_image(104, 152, 8, 8)) #Frame 4 of flying self.frames.append( self.get_image(112, 144, 16, 16)) #frame 1 of exploding self.frames.append( self.get_image(112, 160, 16, 16)) #frame 2 of exploding self.frames.append( self.get_image(112, 176, 16, 16)) #frame 3 of exploding def get_image(self, x, y, width, height): """Get the image frames from the sprite sheet""" image = pg.Surface([width, height]).convert() rect = image.get_rect() image.blit(self.sprite_sheet, (0, 0), (x, y, width, height)) image.set_colorkey(c.BLACK) image = pg.transform.scale(image, (int(rect.width*c.SIZE_MULTIPLIER), int(rect.height*c.SIZE_MULTIPLIER))) return image def update(self, game_info, viewport): """Updates fireball behavior""" self.current_time = game_info[c.CURRENT_TIME] self.handle_state() self.check_if_off_screen(viewport) def handle_state(self): """Handles behavior based on state""" if self.state == c.FLYING: self.animation() elif self.state == c.BOUNCING: self.animation() elif self.state == c.EXPLODING: self.animation() def animation(self): """adjusts frame for animation""" if self.state == c.FLYING or self.state == c.BOUNCING: if (self.current_time - self.animation_timer) > 200: if self.frame_index < 3: self.frame_index += 1 else: self.frame_index = 0 self.animation_timer = self.current_time self.image = self.frames[self.frame_index] elif self.state == c.EXPLODING: if (self.current_time - self.animation_timer) > 50: if self.frame_index < 6: self.frame_index += 1 self.image = self.frames[self.frame_index] self.animation_timer = self.current_time else: self.kill() def explode_transition(self): """Transitions fireball to EXPLODING state""" self.frame_index = 4 centerx = self.rect.centerx self.image = self.frames[self.frame_index] self.rect.centerx = centerx self.state = c.EXPLODING def check_if_off_screen(self, viewport): """Removes from sprite group if off screen""" if (self.rect.x > viewport.right) or (self.rect.y > viewport.bottom) \ or (self.rect.right < viewport.x): self.kill()