You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
SuperMario/pythonProject1/data/components/powerups.py

361 lines
10 KiB

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()