diff --git a/pythonProject1/.idea/.gitignore b/pythonProject1/.idea/.gitignore new file mode 100644 index 0000000..359bb53 --- /dev/null +++ b/pythonProject1/.idea/.gitignore @@ -0,0 +1,3 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml diff --git a/pythonProject1/.idea/inspectionProfiles/profiles_settings.xml b/pythonProject1/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/pythonProject1/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/pythonProject1/.idea/misc.xml b/pythonProject1/.idea/misc.xml new file mode 100644 index 0000000..5e6072c --- /dev/null +++ b/pythonProject1/.idea/misc.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/pythonProject1/.idea/modules.xml b/pythonProject1/.idea/modules.xml new file mode 100644 index 0000000..fdd8fdf --- /dev/null +++ b/pythonProject1/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/pythonProject1/.idea/pythonProject1.iml b/pythonProject1/.idea/pythonProject1.iml new file mode 100644 index 0000000..2c80e12 --- /dev/null +++ b/pythonProject1/.idea/pythonProject1.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/pythonProject1/data/__pycache__/constants.cpython-311.pyc b/pythonProject1/data/__pycache__/constants.cpython-311.pyc new file mode 100644 index 0000000..61e6460 Binary files /dev/null and b/pythonProject1/data/__pycache__/constants.cpython-311.pyc differ diff --git a/pythonProject1/data/__pycache__/game_sound.cpython-311.pyc b/pythonProject1/data/__pycache__/game_sound.cpython-311.pyc new file mode 100644 index 0000000..6a46a3b Binary files /dev/null and b/pythonProject1/data/__pycache__/game_sound.cpython-311.pyc differ diff --git a/pythonProject1/data/__pycache__/main.cpython-311.pyc b/pythonProject1/data/__pycache__/main.cpython-311.pyc new file mode 100644 index 0000000..5960089 Binary files /dev/null and b/pythonProject1/data/__pycache__/main.cpython-311.pyc differ diff --git a/pythonProject1/data/__pycache__/setup.cpython-311.pyc b/pythonProject1/data/__pycache__/setup.cpython-311.pyc new file mode 100644 index 0000000..641b000 Binary files /dev/null and b/pythonProject1/data/__pycache__/setup.cpython-311.pyc differ diff --git a/pythonProject1/data/__pycache__/tools.cpython-311.pyc b/pythonProject1/data/__pycache__/tools.cpython-311.pyc new file mode 100644 index 0000000..5d6ec9f Binary files /dev/null and b/pythonProject1/data/__pycache__/tools.cpython-311.pyc differ diff --git a/pythonProject1/data/components/__pycache__/bricks.cpython-311.pyc b/pythonProject1/data/components/__pycache__/bricks.cpython-311.pyc new file mode 100644 index 0000000..723b217 Binary files /dev/null and b/pythonProject1/data/components/__pycache__/bricks.cpython-311.pyc differ diff --git a/pythonProject1/data/components/__pycache__/castle_flag.cpython-311.pyc b/pythonProject1/data/components/__pycache__/castle_flag.cpython-311.pyc new file mode 100644 index 0000000..eb0c36e Binary files /dev/null and b/pythonProject1/data/components/__pycache__/castle_flag.cpython-311.pyc differ diff --git a/pythonProject1/data/components/__pycache__/checkpoint.cpython-311.pyc b/pythonProject1/data/components/__pycache__/checkpoint.cpython-311.pyc new file mode 100644 index 0000000..98bc86c Binary files /dev/null and b/pythonProject1/data/components/__pycache__/checkpoint.cpython-311.pyc differ diff --git a/pythonProject1/data/components/__pycache__/coin.cpython-311.pyc b/pythonProject1/data/components/__pycache__/coin.cpython-311.pyc new file mode 100644 index 0000000..ab5652e Binary files /dev/null and b/pythonProject1/data/components/__pycache__/coin.cpython-311.pyc differ diff --git a/pythonProject1/data/components/__pycache__/coin_box.cpython-311.pyc b/pythonProject1/data/components/__pycache__/coin_box.cpython-311.pyc new file mode 100644 index 0000000..7e631f2 Binary files /dev/null and b/pythonProject1/data/components/__pycache__/coin_box.cpython-311.pyc differ diff --git a/pythonProject1/data/components/__pycache__/collider.cpython-311.pyc b/pythonProject1/data/components/__pycache__/collider.cpython-311.pyc new file mode 100644 index 0000000..ca9c98a Binary files /dev/null and b/pythonProject1/data/components/__pycache__/collider.cpython-311.pyc differ diff --git a/pythonProject1/data/components/__pycache__/enemies.cpython-311.pyc b/pythonProject1/data/components/__pycache__/enemies.cpython-311.pyc new file mode 100644 index 0000000..e1494b3 Binary files /dev/null and b/pythonProject1/data/components/__pycache__/enemies.cpython-311.pyc differ diff --git a/pythonProject1/data/components/__pycache__/flagpole.cpython-311.pyc b/pythonProject1/data/components/__pycache__/flagpole.cpython-311.pyc new file mode 100644 index 0000000..7cf47ef Binary files /dev/null and b/pythonProject1/data/components/__pycache__/flagpole.cpython-311.pyc differ diff --git a/pythonProject1/data/components/__pycache__/flashing_coin.cpython-311.pyc b/pythonProject1/data/components/__pycache__/flashing_coin.cpython-311.pyc new file mode 100644 index 0000000..ad4e6e8 Binary files /dev/null and b/pythonProject1/data/components/__pycache__/flashing_coin.cpython-311.pyc differ diff --git a/pythonProject1/data/components/__pycache__/info.cpython-311.pyc b/pythonProject1/data/components/__pycache__/info.cpython-311.pyc new file mode 100644 index 0000000..83f0546 Binary files /dev/null and b/pythonProject1/data/components/__pycache__/info.cpython-311.pyc differ diff --git a/pythonProject1/data/components/__pycache__/mario.cpython-311.pyc b/pythonProject1/data/components/__pycache__/mario.cpython-311.pyc new file mode 100644 index 0000000..0398b17 Binary files /dev/null and b/pythonProject1/data/components/__pycache__/mario.cpython-311.pyc differ diff --git a/pythonProject1/data/components/__pycache__/powerups.cpython-311.pyc b/pythonProject1/data/components/__pycache__/powerups.cpython-311.pyc new file mode 100644 index 0000000..5ce9158 Binary files /dev/null and b/pythonProject1/data/components/__pycache__/powerups.cpython-311.pyc differ diff --git a/pythonProject1/data/components/__pycache__/score.cpython-311.pyc b/pythonProject1/data/components/__pycache__/score.cpython-311.pyc new file mode 100644 index 0000000..c5437fe Binary files /dev/null and b/pythonProject1/data/components/__pycache__/score.cpython-311.pyc differ diff --git a/pythonProject1/data/components/bricks.py b/pythonProject1/data/components/bricks.py new file mode 100644 index 0000000..c4e421a --- /dev/null +++ b/pythonProject1/data/components/bricks.py @@ -0,0 +1,197 @@ + + +import pygame as pg +from .. import setup +from .. import constants as c +from . import powerups +from . import coin + + +class Brick(pg.sprite.Sprite): + """Bricks that can be destroyed""" + def __init__(self, x, y, contents=None, powerup_group=None, name='brick'): + """Initialize the object""" + pg.sprite.Sprite.__init__(self) + self.sprite_sheet = setup.GFX['tile_set'] + + self.frames = [] + self.frame_index = 0 + self.setup_frames() + self.image = self.frames[self.frame_index] + self.rect = self.image.get_rect() + self.rect.x = x + self.rect.y = y + self.mask = pg.mask.from_surface(self.image) + self.bumped_up = False + self.rest_height = y + self.state = c.RESTING + self.y_vel = 0 + self.gravity = 1.2 + self.name = name + self.contents = contents + self.setup_contents() + self.group = powerup_group + self.powerup_in_box = True + + + def get_image(self, x, y, width, height): + """Extracts the image 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.BRICK_SIZE_MULTIPLIER), + int(rect.height*c.BRICK_SIZE_MULTIPLIER))) + return image + + + def setup_frames(self): + """Set the frames to a list""" + self.frames.append(self.get_image(16, 0, 16, 16)) + self.frames.append(self.get_image(432, 0, 16, 16)) + + + def setup_contents(self): + """Put 6 coins in contents if needed""" + if self.contents == '6coins': + self.coin_total = 6 + else: + self.coin_total = 0 + + + def update(self): + """Updates the brick""" + self.handle_states() + + + def handle_states(self): + """Determines brick behavior based on state""" + if self.state == c.RESTING: + self.resting() + elif self.state == c.BUMPED: + self.bumped() + elif self.state == c.OPENED: + self.opened() + + + def resting(self): + """State when not moving""" + if self.contents == '6coins': + if self.coin_total == 0: + self.state == c.OPENED + + + def bumped(self): + """Action during a BUMPED state""" + self.rect.y += self.y_vel + self.y_vel += self.gravity + + if self.rect.y >= (self.rest_height + 5): + self.rect.y = self.rest_height + if self.contents == 'star': + self.state = c.OPENED + elif self.contents == '6coins': + if self.coin_total == 0: + self.state = c.OPENED + else: + self.state = c.RESTING + else: + self.state = c.RESTING + + + def start_bump(self, score_group): + """Transitions brick into BUMPED state""" + self.y_vel = -6 + + if self.contents == '6coins': + setup.SFX['coin'].play() + + if self.coin_total > 0: + self.group.add(coin.Coin(self.rect.centerx, self.rect.y, score_group)) + self.coin_total -= 1 + if self.coin_total == 0: + self.frame_index = 1 + self.image = self.frames[self.frame_index] + elif self.contents == 'star': + setup.SFX['powerup_appears'].play() + self.frame_index = 1 + self.image = self.frames[self.frame_index] + + self.state = c.BUMPED + + + def opened(self): + """Action during OPENED state""" + self.frame_index = 1 + self.image = self.frames[self.frame_index] + + if self.contents == 'star' and self.powerup_in_box: + self.group.add(powerups.Star(self.rect.centerx, self.rest_height)) + self.powerup_in_box = False + + +class BrickPiece(pg.sprite.Sprite): + """Pieces that appear when bricks are broken""" + def __init__(self, x, y, xvel, yvel): + super(BrickPiece, self).__init__() + self.sprite_sheet = setup.GFX['item_objects'] + self.setup_frames() + self.frame_index = 0 + self.image = self.frames[self.frame_index] + self.rect = self.image.get_rect() + self.rect.x = x + self.rect.y = y + self.x_vel = xvel + self.y_vel = yvel + self.gravity = .8 + + + def setup_frames(self): + """create the frame list""" + self.frames = [] + + image = self.get_image(68, 20, 8, 8) + reversed_image = pg.transform.flip(image, True, False) + + self.frames.append(image) + self.frames.append(reversed_image) + + + def get_image(self, x, y, width, height): + """Extract image from 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.BRICK_SIZE_MULTIPLIER), + int(rect.height*c.BRICK_SIZE_MULTIPLIER))) + return image + + + def update(self): + """Update brick piece""" + self.rect.x += self.x_vel + self.rect.y += self.y_vel + self.y_vel += self.gravity + self.check_if_off_screen() + + def check_if_off_screen(self): + """Remove from sprite groups if off screen""" + if self.rect.y > c.SCREEN_HEIGHT: + self.kill() + + + + + + + + + + + + diff --git a/pythonProject1/data/components/castle_flag.py b/pythonProject1/data/components/castle_flag.py new file mode 100644 index 0000000..4720e52 --- /dev/null +++ b/pythonProject1/data/components/castle_flag.py @@ -0,0 +1,50 @@ + + +import pygame as pg +from .. import setup +from .. import constants as c + + +class Flag(pg.sprite.Sprite): + """Flag on the castle""" + def __init__(self, x, y): + """Initialize object""" + super(Flag, self).__init__() + self.sprite_sheet = setup.GFX['item_objects'] + self.image = self.get_image(129, 2, 14, 14) + self.rect = self.image.get_rect() + self.rect.x = x + self.rect.y = y + self.state = 'rising' + self.y_vel = -2 + self.target_height = y + + + def get_image(self, x, y, width, height): + """Extracts image from sprite sheet""" + image = pg.Surface([width, height]) + 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, *args): + """Updates flag position""" + if self.state == 'rising': + self.rising() + elif self.state == 'resting': + self.resting() + + def rising(self): + """State when flag is rising to be on the castle""" + self.rect.y += self.y_vel + if self.rect.bottom <= self.target_height: + self.state = 'resting' + + def resting(self): + """State when the flag is stationary doing nothing""" + pass diff --git a/pythonProject1/data/components/checkpoint.py b/pythonProject1/data/components/checkpoint.py new file mode 100644 index 0000000..4d52086 --- /dev/null +++ b/pythonProject1/data/components/checkpoint.py @@ -0,0 +1,21 @@ + + +import pygame as pg +from .. import constants as c + + +class Checkpoint(pg.sprite.Sprite): + """Invisible sprite used to add enemies, special boxes + and trigger sliding down the flag pole""" + def __init__(self, x, name, y=0, width=10, height=600): + super(Checkpoint, self).__init__() + self.image = pg.Surface((width, height)) + self.image.fill(c.BLACK) + self.rect = self.image.get_rect() + self.rect.x = x + self.rect.y = y + self.name = name + + + + diff --git a/pythonProject1/data/components/coin.py b/pythonProject1/data/components/coin.py new file mode 100644 index 0000000..7d1017b --- /dev/null +++ b/pythonProject1/data/components/coin.py @@ -0,0 +1,84 @@ + + +import pygame as pg +from .. import setup +from .. import constants as c +from . import score + + +class Coin(pg.sprite.Sprite): + """Coins found in boxes and bricks""" + def __init__(self, x, y, score_group): + pg.sprite.Sprite.__init__(self) + self.sprite_sheet = setup.GFX['item_objects'] + self.frames = [] + self.frame_index = 0 + self.animation_timer = 0 + self.state = c.SPIN + self.setup_frames() + self.image = self.frames[self.frame_index] + self.rect = self.image.get_rect() + self.rect.centerx = x + self.rect.bottom = y - 5 + self.gravity = 1 + self.y_vel = -15 + self.initial_height = self.rect.bottom - 5 + self.score_group = score_group + + + 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 setup_frames(self): + """create the frame list""" + self.frames.append(self.get_image(52, 113, 8, 14)) + self.frames.append(self.get_image(4, 113, 8, 14)) + self.frames.append(self.get_image(20, 113, 8, 14)) + self.frames.append(self.get_image(36, 113, 8, 14)) + + + def update(self, game_info, viewport): + """Update the coin's behavior""" + self.current_time = game_info[c.CURRENT_TIME] + self.viewport = viewport + if self.state == c.SPIN: + self.spinning() + + + def spinning(self): + """Action when the coin is in the SPIN state""" + self.image = self.frames[self.frame_index] + self.rect.y += self.y_vel + self.y_vel += self.gravity + + if (self.current_time - self.animation_timer) > 80: + if self.frame_index < 3: + self.frame_index += 1 + else: + self.frame_index = 0 + + self.animation_timer = self.current_time + + if self.rect.bottom > self.initial_height: + self.kill() + self.score_group.append(score.Score(self.rect.centerx - self.viewport.x, + self.rect.y, + 200)) + + + + + + diff --git a/pythonProject1/data/components/coin_box.py b/pythonProject1/data/components/coin_box.py new file mode 100644 index 0000000..5755f87 --- /dev/null +++ b/pythonProject1/data/components/coin_box.py @@ -0,0 +1,149 @@ + +import pygame as pg +from .. import setup +from .. import constants as c +from . import powerups +from . import coin + + + +class Coin_box(pg.sprite.Sprite): + """Coin box sprite""" + def __init__(self, x, y, contents='coin', group=None): + pg.sprite.Sprite.__init__(self) + self.sprite_sheet = setup.GFX['tile_set'] + self.frames = [] + self.setup_frames() + self.frame_index = 0 + self.image = self.frames[self.frame_index] + self.rect = self.image.get_rect() + self.rect.x = x + self.rect.y = y + self.mask = pg.mask.from_surface(self.image) + self.animation_timer = 0 + self.first_half = True # First half of animation cycle + self.state = c.RESTING + self.rest_height = y + self.gravity = 1.2 + self.y_vel = 0 + self.contents = contents + self.group = group + + + def get_image(self, x, y, width, height): + """Extract image from 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.BRICK_SIZE_MULTIPLIER), + int(rect.height*c.BRICK_SIZE_MULTIPLIER))) + return image + + + def setup_frames(self): + """Create frame list""" + self.frames.append( + self.get_image(384, 0, 16, 16)) + self.frames.append( + self.get_image(400, 0, 16, 16)) + self.frames.append( + self.get_image(416, 0, 16, 16)) + self.frames.append( + self.get_image(432, 0, 16, 16)) + + + def update(self, game_info): + """Update coin box behavior""" + self.current_time = game_info[c.CURRENT_TIME] + self.handle_states() + + + def handle_states(self): + """Determine action based on RESTING, BUMPED or OPENED + state""" + if self.state == c.RESTING: + self.resting() + elif self.state == c.BUMPED: + self.bumped() + elif self.state == c.OPENED: + self.opened() + + + def resting(self): + """Action when in the RESTING state""" + if self.first_half: + if self.frame_index == 0: + if (self.current_time - self.animation_timer) > 375: + self.frame_index += 1 + self.animation_timer = self.current_time + elif self.frame_index < 2: + if (self.current_time - self.animation_timer) > 125: + self.frame_index += 1 + self.animation_timer = self.current_time + elif self.frame_index == 2: + if (self.current_time - self.animation_timer) > 125: + self.frame_index -= 1 + self.first_half = False + self.animation_timer = self.current_time + else: + if self.frame_index == 1: + if (self.current_time - self.animation_timer) > 125: + self.frame_index -= 1 + self.first_half = True + self.animation_timer = self.current_time + + self.image = self.frames[self.frame_index] + + + def bumped(self): + """Action after Mario has bumped the box from below""" + self.rect.y += self.y_vel + self.y_vel += self.gravity + + if self.rect.y > self.rest_height + 5: + self.rect.y = self.rest_height + self.state = c.OPENED + if self.contents == 'mushroom': + self.group.add(powerups.Mushroom(self.rect.centerx, self.rect.y)) + elif self.contents == 'fireflower': + self.group.add(powerups.FireFlower(self.rect.centerx, self.rect.y)) + elif self.contents == '1up_mushroom': + self.group.add(powerups.LifeMushroom(self.rect.centerx, self.rect.y)) + + + self.frame_index = 3 + self.image = self.frames[self.frame_index] + + + def start_bump(self, score_group): + """Transitions box into BUMPED state""" + self.y_vel = -6 + self.state = c.BUMPED + + if self.contents == 'coin': + self.group.add(coin.Coin(self.rect.centerx, + self.rect.y, + score_group)) + setup.SFX['coin'].play() + else: + setup.SFX['powerup_appears'].play() + + + def opened(self): + """Placeholder for OPENED state""" + pass + + + + + + + + + + + diff --git a/pythonProject1/data/components/collider.py b/pythonProject1/data/components/collider.py new file mode 100644 index 0000000..a07eaae --- /dev/null +++ b/pythonProject1/data/components/collider.py @@ -0,0 +1,16 @@ + +import pygame as pg +from .. import constants as c + +class Collider(pg.sprite.Sprite): + """Invisible sprites placed overtop background parts + that can be collided with (pipes, steps, ground, etc.""" + def __init__(self, x, y, width, height, name='collider'): + pg.sprite.Sprite.__init__(self) + self.image = pg.Surface((width, height)).convert() + #self.image.fill(c.RED) + self.rect = self.image.get_rect() + self.rect.x = x + self.rect.y = y + self.state = None + diff --git a/pythonProject1/data/components/enemies.py b/pythonProject1/data/components/enemies.py new file mode 100644 index 0000000..1432829 --- /dev/null +++ b/pythonProject1/data/components/enemies.py @@ -0,0 +1,215 @@ + + + +import pygame as pg +from .. import setup +from .. import constants as c + + +class Enemy(pg.sprite.Sprite): + """Base class for all enemies (Goombas, Koopas, etc.)""" + def __init__(self): + pg.sprite.Sprite.__init__(self) + + + def setup_enemy(self, x, y, direction, name, setup_frames): + """Sets up various values for enemy""" + self.sprite_sheet = setup.GFX['smb_enemies_sheet'] + self.frames = [] + self.frame_index = 0 + self.animate_timer = 0 + self.death_timer = 0 + self.gravity = 1.5 + self.state = c.WALK + + self.name = name + self.direction = direction + setup_frames() + + self.image = self.frames[self.frame_index] + self.rect = self.image.get_rect() + self.rect.x = x + self.rect.bottom = y + self.set_velocity() + + + def set_velocity(self): + """Sets velocity vector based on direction""" + if self.direction == c.LEFT: + self.x_vel = -2 + else: + self.x_vel = 2 + + self.y_vel = 0 + + + 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 handle_state(self): + """Enemy behavior based on state""" + if self.state == c.WALK: + self.walking() + elif self.state == c.FALL: + self.falling() + elif self.state == c.JUMPED_ON: + self.jumped_on() + elif self.state == c.SHELL_SLIDE: + self.shell_sliding() + elif self.state == c.DEATH_JUMP: + self.death_jumping() + + + def walking(self): + """Default state of moving sideways""" + if (self.current_time - self.animate_timer) > 125: + if self.frame_index == 0: + self.frame_index += 1 + elif self.frame_index == 1: + self.frame_index = 0 + + self.animate_timer = self.current_time + + + def falling(self): + """For when it falls off a ledge""" + if self.y_vel < 10: + self.y_vel += self.gravity + + + def jumped_on(self): + """Placeholder for when the enemy is stomped on""" + pass + + + def death_jumping(self): + """Death animation""" + self.rect.y += self.y_vel + self.rect.x += self.x_vel + self.y_vel += self.gravity + + if self.rect.y > 600: + self.kill() + + + def start_death_jump(self, direction): + """Transitions enemy into a DEATH JUMP state""" + self.y_vel = -8 + if direction == c.RIGHT: + self.x_vel = 2 + else: + self.x_vel = -2 + self.gravity = .5 + self.frame_index = 3 + self.image = self.frames[self.frame_index] + self.state = c.DEATH_JUMP + + + def animation(self): + """Basic animation, switching between two frames""" + self.image = self.frames[self.frame_index] + + + def update(self, game_info, *args): + """Updates enemy behavior""" + self.current_time = game_info[c.CURRENT_TIME] + self.handle_state() + self.animation() + + + + +class Goomba(Enemy): + + def __init__(self, y=c.GROUND_HEIGHT, x=0, direction=c.LEFT, name='goomba'): + Enemy.__init__(self) + self.setup_enemy(x, y, direction, name, self.setup_frames) + + + def setup_frames(self): + """Put the image frames in a list to be animated""" + + self.frames.append( + self.get_image(0, 4, 16, 16)) + self.frames.append( + self.get_image(30, 4, 16, 16)) + self.frames.append( + self.get_image(61, 0, 16, 16)) + self.frames.append(pg.transform.flip(self.frames[1], False, True)) + + + def jumped_on(self): + """When Mario squishes him""" + self.frame_index = 2 + + if (self.current_time - self.death_timer) > 500: + self.kill() + + + +class Koopa(Enemy): + + def __init__(self, y=c.GROUND_HEIGHT, x=0, direction=c.LEFT, name='koopa'): + Enemy.__init__(self) + self.setup_enemy(x, y, direction, name, self.setup_frames) + + + def setup_frames(self): + """Sets frame list""" + self.frames.append( + self.get_image(150, 0, 16, 24)) + self.frames.append( + self.get_image(180, 0, 16, 24)) + self.frames.append( + self.get_image(360, 5, 16, 15)) + self.frames.append(pg.transform.flip(self.frames[2], False, True)) + + + def jumped_on(self): + """When Mario jumps on the Koopa and puts him in his shell""" + self.x_vel = 0 + self.frame_index = 2 + shell_y = self.rect.bottom + shell_x = self.rect.x + self.rect = self.frames[self.frame_index].get_rect() + self.rect.x = shell_x + self.rect.bottom = shell_y + + + def shell_sliding(self): + """When the koopa is sliding along the ground in his shell""" + if self.direction == c.RIGHT: + self.x_vel = 10 + elif self.direction == c.LEFT: + self.x_vel = -10 + + + + + + + + + + + + + + + + + + + diff --git a/pythonProject1/data/components/flagpole.py b/pythonProject1/data/components/flagpole.py new file mode 100644 index 0000000..466ce4a --- /dev/null +++ b/pythonProject1/data/components/flagpole.py @@ -0,0 +1,139 @@ + +import pygame as pg +from .. import setup +from .. import constants as c + +class Flag(pg.sprite.Sprite): + """Flag on top of the flag pole at the end of the level""" + def __init__(self, x, y): + super(Flag, self).__init__() + self.sprite_sheet = setup.GFX['item_objects'] + self.setup_images() + self.image = self.frames[0] + self.rect = self.image.get_rect() + self.rect.right = x + self.rect.y = y + self.state = c.TOP_OF_POLE + + + def setup_images(self): + """Sets up a list of image frames""" + self.frames = [] + + self.frames.append( + self.get_image(128, 32, 16, 16)) + + + def get_image(self, x, y, width, height): + """Extracts image from sprite sheet""" + image = pg.Surface([width, height]) + 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.BRICK_SIZE_MULTIPLIER), + int(rect.height*c.BRICK_SIZE_MULTIPLIER))) + return image + + + def update(self, *args): + """Updates behavior""" + self.handle_state() + + + def handle_state(self): + """Determines behavior based on state""" + if self.state == c.TOP_OF_POLE: + self.image = self.frames[0] + elif self.state == c.SLIDE_DOWN: + self.sliding_down() + elif self.state == c.BOTTOM_OF_POLE: + self.image = self.frames[0] + + + def sliding_down(self): + """State when Mario reaches flag pole""" + self.y_vel = 5 + self.rect.y += self.y_vel + + if self.rect.bottom >= 485: + self.state = c.BOTTOM_OF_POLE + + +class Pole(pg.sprite.Sprite): + """Pole that the flag is on top of""" + def __init__(self, x, y): + super(Pole, self).__init__() + self.sprite_sheet = setup.GFX['tile_set'] + self.setup_frames() + self.image = self.frames[0] + self.rect = self.image.get_rect() + self.rect.x = x + self.rect.y = y + + + def setup_frames(self): + """Create the frame list""" + self.frames = [] + + self.frames.append( + self.get_image(263, 144, 2, 16)) + + + def get_image(self, x, y, width, height): + """Extracts image from sprite sheet""" + image = pg.Surface([width, height]) + 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.BRICK_SIZE_MULTIPLIER), + int(rect.height*c.BRICK_SIZE_MULTIPLIER))) + return image + + + def update(self, *args): + """Placeholder for update, since there is nothing to update""" + pass + + +class Finial(pg.sprite.Sprite): + """The top of the flag pole""" + def __init__(self, x, y): + super(Finial, self).__init__() + self.sprite_sheet = setup.GFX['tile_set'] + self.setup_frames() + self.image = self.frames[0] + self.rect = self.image.get_rect() + self.rect.centerx = x + self.rect.bottom = y + + + def setup_frames(self): + """Creates the self.frames list""" + self.frames = [] + + self.frames.append( + self.get_image(228, 120, 8, 8)) + + + def get_image(self, x, y, width, height): + """Extracts image from sprite sheet""" + image = pg.Surface([width, height]) + 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, *args): + pass + + + diff --git a/pythonProject1/data/components/flashing_coin.py b/pythonProject1/data/components/flashing_coin.py new file mode 100644 index 0000000..fa23fef --- /dev/null +++ b/pythonProject1/data/components/flashing_coin.py @@ -0,0 +1,68 @@ + +import pygame as pg +from .. import setup +from .. import constants as c + + +class Coin(pg.sprite.Sprite): + """Flashing coin next to coin total info""" + def __init__(self, x, y): + super(Coin, self).__init__() + self.sprite_sheet = setup.GFX['item_objects'] + self.create_frames() + self.image = self.frames[0] + self.rect = self.image.get_rect() + self.rect.x = x + self.rect.y = y + self.timer = 0 + self.first_half = True + self.frame_index = 0 + + + def create_frames(self): + """Extract coin images from sprite sheet and assign them to a list""" + self.frames = [] + self.frame_index = 0 + + self.frames.append(self.get_image(1, 160, 5, 8)) + self.frames.append(self.get_image(9, 160, 5, 8)) + self.frames.append(self.get_image(17, 160, 5, 8)) + + + def get_image(self, x, y, width, height): + """Extracts image from sprite sheet""" + image = pg.Surface([width, height]) + 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.BRICK_SIZE_MULTIPLIER), + int(rect.height*c.BRICK_SIZE_MULTIPLIER))) + return image + + + def update(self, current_time): + """Animates flashing coin""" + if self.first_half: + if self.frame_index == 0: + if (current_time - self.timer) > 375: + self.frame_index += 1 + self.timer = current_time + elif self.frame_index < 2: + if (current_time - self.timer) > 125: + self.frame_index += 1 + self.timer = current_time + elif self.frame_index == 2: + if (current_time - self.timer) > 125: + self.frame_index -= 1 + self.first_half = False + self.timer = current_time + else: + if self.frame_index == 1: + if (current_time - self.timer) > 125: + self.frame_index -= 1 + self.first_half = True + self.timer = current_time + + self.image = self.frames[self.frame_index] \ No newline at end of file diff --git a/pythonProject1/data/components/info.py b/pythonProject1/data/components/info.py new file mode 100644 index 0000000..a32a06e --- /dev/null +++ b/pythonProject1/data/components/info.py @@ -0,0 +1,462 @@ + +import pygame as pg +from .. import setup +from .. import constants as c +from . import flashing_coin + + +class Character(pg.sprite.Sprite): + """Parent class for all characters used for the overhead level info""" + def __init__(self, image): + super(Character, self).__init__() + self.image = image + self.rect = self.image.get_rect() + + +class OverheadInfo(object): + """Class for level information like score, coin total, + and time remaining""" + def __init__(self, game_info, state): + self.sprite_sheet = setup.GFX['text_images'] + self.coin_total = game_info[c.COIN_TOTAL] + self.time = 401 + self.current_time = 0 + self.total_lives = game_info[c.LIVES] + self.top_score = game_info[c.TOP_SCORE] + self.state = state + self.special_state = None + self.game_info = game_info + + self.create_image_dict() + self.create_score_group() + self.create_info_labels() + self.create_load_screen_labels() + self.create_countdown_clock() + self.create_coin_counter() + self.create_flashing_coin() + self.create_mario_image() + self.create_game_over_label() + self.create_time_out_label() + self.create_main_menu_labels() + + + def create_image_dict(self): + """Creates the initial images for the score""" + self.image_dict = {} + image_list = [] + + image_list.append(self.get_image(3, 230, 7, 7)) + image_list.append(self.get_image(12, 230, 7, 7)) + image_list.append(self.get_image(19, 230, 7, 7)) + image_list.append(self.get_image(27, 230, 7, 7)) + image_list.append(self.get_image(35, 230, 7, 7)) + image_list.append(self.get_image(43, 230, 7, 7)) + image_list.append(self.get_image(51, 230, 7, 7)) + image_list.append(self.get_image(59, 230, 7, 7)) + image_list.append(self.get_image(67, 230, 7, 7)) + image_list.append(self.get_image(75, 230, 7, 7)) + + image_list.append(self.get_image(83, 230, 7, 7)) + image_list.append(self.get_image(91, 230, 7, 7)) + image_list.append(self.get_image(99, 230, 7, 7)) + image_list.append(self.get_image(107, 230, 7, 7)) + image_list.append(self.get_image(115, 230, 7, 7)) + image_list.append(self.get_image(123, 230, 7, 7)) + image_list.append(self.get_image(3, 238, 7, 7)) + image_list.append(self.get_image(11, 238, 7, 7)) + image_list.append(self.get_image(20, 238, 7, 7)) + image_list.append(self.get_image(27, 238, 7, 7)) + image_list.append(self.get_image(35, 238, 7, 7)) + image_list.append(self.get_image(44, 238, 7, 7)) + image_list.append(self.get_image(51, 238, 7, 7)) + image_list.append(self.get_image(59, 238, 7, 7)) + image_list.append(self.get_image(67, 238, 7, 7)) + image_list.append(self.get_image(75, 238, 7, 7)) + image_list.append(self.get_image(83, 238, 7, 7)) + image_list.append(self.get_image(91, 238, 7, 7)) + image_list.append(self.get_image(99, 238, 7, 7)) + image_list.append(self.get_image(108, 238, 7, 7)) + image_list.append(self.get_image(115, 238, 7, 7)) + image_list.append(self.get_image(123, 238, 7, 7)) + image_list.append(self.get_image(3, 246, 7, 7)) + image_list.append(self.get_image(11, 246, 7, 7)) + image_list.append(self.get_image(20, 246, 7, 7)) + image_list.append(self.get_image(27, 246, 7, 7)) + image_list.append(self.get_image(48, 248, 7, 7)) + + image_list.append(self.get_image(68, 249, 6, 2)) + image_list.append(self.get_image(75, 247, 6, 6)) + + + + character_string = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ -*' + + for character, image in zip(character_string, image_list): + self.image_dict[character] = image + + + def get_image(self, x, y, width, height): + """Extracts image from sprite sheet""" + image = pg.Surface([width, height]) + rect = image.get_rect() + + image.blit(self.sprite_sheet, (0, 0), (x, y, width, height)) + image.set_colorkey((92, 148, 252)) + image = pg.transform.scale(image, + (int(rect.width*2.9), + int(rect.height*2.9))) + return image + + + def create_score_group(self): + """Creates the initial empty score (000000)""" + self.score_images = [] + self.create_label(self.score_images, '000000', 75, 55) + + + def create_info_labels(self): + """Creates the labels that describe each info""" + self.mario_label = [] + self.world_label = [] + self.time_label = [] + self.stage_label = [] + + + self.create_label(self.mario_label, 'MARIO', 75, 30) + self.create_label(self.world_label, 'WORLD', 450, 30) + self.create_label(self.time_label, 'TIME', 625, 30) + self.create_label(self.stage_label, '1-1', 472, 55) + + self.label_list = [self.mario_label, + self.world_label, + self.time_label, + self.stage_label] + + + def create_load_screen_labels(self): + """Creates labels for the center info of a load screen""" + world_label = [] + number_label = [] + + self.create_label(world_label, 'WORLD', 280, 200) + self.create_label(number_label, '1-1', 430, 200) + + self.center_labels = [world_label, number_label] + + + def create_countdown_clock(self): + """Creates the count down clock for the level""" + self.count_down_images = [] + self.create_label(self.count_down_images, str(self.time), 645, 55) + + + def create_label(self, label_list, string, x, y): + """Creates a label (WORLD, TIME, MARIO)""" + for letter in string: + label_list.append(Character(self.image_dict[letter])) + + self.set_label_rects(label_list, x, y) + + + def set_label_rects(self, label_list, x, y): + """Set the location of each individual character""" + for i, letter in enumerate(label_list): + letter.rect.x = x + ((letter.rect.width + 3) * i) + letter.rect.y = y + if letter.image == self.image_dict['-']: + letter.rect.y += 7 + letter.rect.x += 2 + + + def create_coin_counter(self): + """Creates the info that tracks the number of coins Mario collects""" + self.coin_count_images = [] + self.create_label(self.coin_count_images, '*00', 300, 55) + + + def create_flashing_coin(self): + """Creates the flashing coin next to the coin total""" + self.flashing_coin = flashing_coin.Coin(280, 53) + + + def create_mario_image(self): + """Get the mario image""" + self.life_times_image = self.get_image(75, 247, 6, 6) + self.life_times_rect = self.life_times_image.get_rect(center=(378, 295)) + self.life_total_label = [] + self.create_label(self.life_total_label, str(self.total_lives), + 450, 285) + + self.sprite_sheet = setup.GFX['mario_bros'] + self.mario_image = self.get_image(178, 32, 12, 16) + self.mario_rect = self.mario_image.get_rect(center=(320, 290)) + + + def create_game_over_label(self): + """Create the label for the GAME OVER screen""" + game_label = [] + over_label = [] + + self.create_label(game_label, 'GAME', 280, 300) + self.create_label(over_label, 'OVER', 400, 300) + + self.game_over_label = [game_label, over_label] + + + def create_time_out_label(self): + """Create the label for the time out screen""" + time_out_label = [] + + self.create_label(time_out_label, 'TIME OUT', 290, 310) + self.time_out_label = [time_out_label] + + + def create_main_menu_labels(self): + """Create labels for the MAIN MENU screen""" + player_one_game = [] + player_two_game = [] + top = [] + top_score = [] + + self.create_label(player_one_game, '1 PLAYER GAME', 272, 360) + self.create_label(player_two_game, '2 PLAYER GAME', 272, 405) + self.create_label(top, 'TOP - ', 290, 465) + self.create_label(top_score, '000000', 400, 465) + + self.main_menu_labels = [player_one_game, player_two_game, + top, top_score] + + + def update(self, level_info, mario=None): + """Updates all overhead info""" + self.mario = mario + self.handle_level_state(level_info) + + + def handle_level_state(self, level_info): + """Updates info based on what state the game is in""" + if self.state == c.MAIN_MENU: + self.score = level_info[c.SCORE] + self.update_score_images(self.score_images, self.score) + self.update_score_images(self.main_menu_labels[3], self.top_score) + self.update_coin_total(level_info) + self.flashing_coin.update(level_info[c.CURRENT_TIME]) + + elif self.state == c.LOAD_SCREEN: + self.score = level_info[c.SCORE] + self.update_score_images(self.score_images, self.score) + self.update_coin_total(level_info) + + elif self.state == c.LEVEL: + self.score = level_info[c.SCORE] + self.update_score_images(self.score_images, self.score) + if level_info[c.LEVEL_STATE] != c.FROZEN \ + and self.mario.state != c.WALKING_TO_CASTLE \ + and self.mario.state != c.END_OF_LEVEL_FALL \ + and not self.mario.dead: + self.update_count_down_clock(level_info) + self.update_coin_total(level_info) + self.flashing_coin.update(level_info[c.CURRENT_TIME]) + + elif self.state == c.TIME_OUT: + self.score = level_info[c.SCORE] + self.update_score_images(self.score_images, self.score) + self.update_coin_total(level_info) + + elif self.state == c.GAME_OVER: + self.score = level_info[c.SCORE] + self.update_score_images(self.score_images, self.score) + self.update_coin_total(level_info) + + elif self.state == c.FAST_COUNT_DOWN: + level_info[c.SCORE] += 50 + self.score = level_info[c.SCORE] + self.update_count_down_clock(level_info) + self.update_score_images(self.score_images, self.score) + self.update_coin_total(level_info) + self.flashing_coin.update(level_info[c.CURRENT_TIME]) + if self.time == 0: + self.state = c.END_OF_LEVEL + + elif self.state == c.END_OF_LEVEL: + self.flashing_coin.update(level_info[c.CURRENT_TIME]) + + + def update_score_images(self, images, score): + """Updates what numbers are to be blitted for the score""" + index = len(images) - 1 + + for digit in reversed(str(score)): + rect = images[index].rect + images[index] = Character(self.image_dict[digit]) + images[index].rect = rect + index -= 1 + + + def update_count_down_clock(self, level_info): + """Updates current time""" + if self.state == c.FAST_COUNT_DOWN: + self.time -= 1 + + elif (level_info[c.CURRENT_TIME] - self.current_time) > 400: + self.current_time = level_info[c.CURRENT_TIME] + self.time -= 1 + self.count_down_images = [] + self.create_label(self.count_down_images, str(self.time), 645, 55) + if len(self.count_down_images) < 2: + for i in range(2): + self.count_down_images.insert(0, Character(self.image_dict['0'])) + self.set_label_rects(self.count_down_images, 645, 55) + elif len(self.count_down_images) < 3: + self.count_down_images.insert(0, Character(self.image_dict['0'])) + self.set_label_rects(self.count_down_images, 645, 55) + + + def update_coin_total(self, level_info): + """Updates the coin total and adjusts label accordingly""" + self.coin_total = level_info[c.COIN_TOTAL] + + coin_string = str(self.coin_total) + if len(coin_string) < 2: + coin_string = '*0' + coin_string + elif len(coin_string) > 2: + coin_string = '*00' + else: + coin_string = '*' + coin_string + + x = self.coin_count_images[0].rect.x + y = self.coin_count_images[0].rect.y + + self.coin_count_images = [] + + self.create_label(self.coin_count_images, coin_string, x, y) + + + def draw(self, surface): + """Draws overhead info based on state""" + if self.state == c.MAIN_MENU: + self.draw_main_menu_info(surface) + elif self.state == c.LOAD_SCREEN: + self.draw_loading_screen_info(surface) + elif self.state == c.LEVEL: + self.draw_level_screen_info(surface) + elif self.state == c.GAME_OVER: + self.draw_game_over_screen_info(surface) + elif self.state == c.FAST_COUNT_DOWN: + self.draw_level_screen_info(surface) + elif self.state == c.END_OF_LEVEL: + self.draw_level_screen_info(surface) + elif self.state == c.TIME_OUT: + self.draw_time_out_screen_info(surface) + else: + pass + + + + def draw_main_menu_info(self, surface): + """Draws info for main menu""" + for info in self.score_images: + surface.blit(info.image, info.rect) + + for label in self.main_menu_labels: + for letter in label: + surface.blit(letter.image, letter.rect) + + for character in self.coin_count_images: + surface.blit(character.image, character.rect) + + for label in self.label_list: + for letter in label: + surface.blit(letter.image, letter.rect) + + surface.blit(self.flashing_coin.image, self.flashing_coin.rect) + + + def draw_loading_screen_info(self, surface): + """Draws info for loading screen""" + for info in self.score_images: + surface.blit(info.image, info.rect) + + for word in self.center_labels: + for letter in word: + surface.blit(letter.image, letter.rect) + + for word in self.life_total_label: + surface.blit(word.image, word.rect) + + surface.blit(self.mario_image, self.mario_rect) + surface.blit(self.life_times_image, self.life_times_rect) + + for character in self.coin_count_images: + surface.blit(character.image, character.rect) + + for label in self.label_list: + for letter in label: + surface.blit(letter.image, letter.rect) + + surface.blit(self.flashing_coin.image, self.flashing_coin.rect) + + + def draw_level_screen_info(self, surface): + """Draws info during regular game play""" + for info in self.score_images: + surface.blit(info.image, info.rect) + + for digit in self.count_down_images: + surface.blit(digit.image, digit.rect) + + for character in self.coin_count_images: + surface.blit(character.image, character.rect) + + for label in self.label_list: + for letter in label: + surface.blit(letter.image, letter.rect) + + surface.blit(self.flashing_coin.image, self.flashing_coin.rect) + + + def draw_game_over_screen_info(self, surface): + """Draws info when game over""" + for info in self.score_images: + surface.blit(info.image, info.rect) + + for word in self.game_over_label: + for letter in word: + surface.blit(letter.image, letter.rect) + + for character in self.coin_count_images: + surface.blit(character.image, character.rect) + + for label in self.label_list: + for letter in label: + surface.blit(letter.image, letter.rect) + + surface.blit(self.flashing_coin.image, self.flashing_coin.rect) + + + def draw_time_out_screen_info(self, surface): + """Draws info when on the time out screen""" + for info in self.score_images: + surface.blit(info.image, info.rect) + + for word in self.time_out_label: + for letter in word: + surface.blit(letter.image, letter.rect) + + for character in self.coin_count_images: + surface.blit(character.image, character.rect) + + for label in self.label_list: + for letter in label: + surface.blit(letter.image, letter.rect) + + surface.blit(self.flashing_coin.image, self.flashing_coin.rect) + + + + + + + + + diff --git a/pythonProject1/data/components/mario.py b/pythonProject1/data/components/mario.py new file mode 100644 index 0000000..f51610e --- /dev/null +++ b/pythonProject1/data/components/mario.py @@ -0,0 +1,1141 @@ + +import pygame as pg +from .. import setup, tools +from .. import constants as c +from . import powerups + + +class Mario(pg.sprite.Sprite): + def __init__(self): + pg.sprite.Sprite.__init__(self) + self.sprite_sheet = setup.GFX['mario_bros'] + + self.setup_timers() + self.setup_state_booleans() + self.setup_forces() + self.setup_counters() + self.load_images_from_sheet() + + self.state = c.WALK + self.image = self.right_frames[self.frame_index] + self.rect = self.image.get_rect() + self.mask = pg.mask.from_surface(self.image) + + self.key_timer = 0 + + + def setup_timers(self): + """Sets up timers for animations""" + self.walking_timer = 0 + self.invincible_animation_timer = 0 + self.invincible_start_timer = 0 + self.fire_transition_timer = 0 + self.death_timer = 0 + self.transition_timer = 0 + self.last_fireball_time = 0 + self.hurt_invisible_timer = 0 + self.hurt_invisible_timer2 = 0 + self.flag_pole_timer = 0 + + + def setup_state_booleans(self): + """Sets up booleans that affect Mario's behavior""" + self.facing_right = True + self.allow_jump = True + self.dead = False + self.invincible = False + self.big = False + self.fire = False + self.allow_fireball = True + self.in_transition_state = False + self.hurt_invincible = False + self.in_castle = False + self.crouching = False + self.losing_invincibility = False + + + def setup_forces(self): + """Sets up forces that affect Mario's velocity""" + self.x_vel = 0 + self.y_vel = 0 + self.max_x_vel = c.MAX_WALK_SPEED + self.max_y_vel = c.MAX_Y_VEL + self.x_accel = c.WALK_ACCEL + self.jump_vel = c.JUMP_VEL + self.gravity = c.GRAVITY + + + def setup_counters(self): + """These keep track of various total for important values""" + self.frame_index = 0 + self.invincible_index = 0 + self.fire_transition_index = 0 + self.fireball_count = 0 + self.flag_pole_right = 0 + + + def load_images_from_sheet(self): + """Extracts Mario images from his sprite sheet and assigns + them to appropriate lists""" + self.right_frames = [] + self.left_frames = [] + + self.right_small_normal_frames = [] + self.left_small_normal_frames = [] + self.right_small_green_frames = [] + self.left_small_green_frames = [] + self.right_small_red_frames = [] + self.left_small_red_frames = [] + self.right_small_black_frames = [] + self.left_small_black_frames = [] + + self.right_big_normal_frames = [] + self.left_big_normal_frames = [] + self.right_big_green_frames = [] + self.left_big_green_frames = [] + self.right_big_red_frames = [] + self.left_big_red_frames = [] + self.right_big_black_frames = [] + self.left_big_black_frames = [] + + self.right_fire_frames = [] + self.left_fire_frames = [] + + + #Images for normal small mario# + + self.right_small_normal_frames.append( + self.get_image(178, 32, 12, 16)) # Right [0] + self.right_small_normal_frames.append( + self.get_image(80, 32, 15, 16)) # Right walking 1 [1] + self.right_small_normal_frames.append( + self.get_image(96, 32, 16, 16)) # Right walking 2 [2] + self.right_small_normal_frames.append( + self.get_image(112, 32, 16, 16)) # Right walking 3 [3] + self.right_small_normal_frames.append( + self.get_image(144, 32, 16, 16)) # Right jump [4] + self.right_small_normal_frames.append( + self.get_image(130, 32, 14, 16)) # Right skid [5] + self.right_small_normal_frames.append( + self.get_image(160, 32, 15, 16)) # Death frame [6] + self.right_small_normal_frames.append( + self.get_image(320, 8, 16, 24)) # Transition small to big [7] + self.right_small_normal_frames.append( + self.get_image(241, 33, 16, 16)) # Transition big to small [8] + self.right_small_normal_frames.append( + self.get_image(194, 32, 12, 16)) # Frame 1 of flag pole Slide [9] + self.right_small_normal_frames.append( + self.get_image(210, 33, 12, 16)) # Frame 2 of flag pole slide [10] + + + #Images for small green mario (for invincible animation)# + + self.right_small_green_frames.append( + self.get_image(178, 224, 12, 16)) # Right standing [0] + self.right_small_green_frames.append( + self.get_image(80, 224, 15, 16)) # Right walking 1 [1] + self.right_small_green_frames.append( + self.get_image(96, 224, 16, 16)) # Right walking 2 [2] + self.right_small_green_frames.append( + self.get_image(112, 224, 15, 16)) # Right walking 3 [3] + self.right_small_green_frames.append( + self.get_image(144, 224, 16, 16)) # Right jump [4] + self.right_small_green_frames.append( + self.get_image(130, 224, 14, 16)) # Right skid [5] + + #Images for red mario (for invincible animation)# + + self.right_small_red_frames.append( + self.get_image(178, 272, 12, 16)) # Right standing [0] + self.right_small_red_frames.append( + self.get_image(80, 272, 15, 16)) # Right walking 1 [1] + self.right_small_red_frames.append( + self.get_image(96, 272, 16, 16)) # Right walking 2 [2] + self.right_small_red_frames.append( + self.get_image(112, 272, 15, 16)) # Right walking 3 [3] + self.right_small_red_frames.append( + self.get_image(144, 272, 16, 16)) # Right jump [4] + self.right_small_red_frames.append( + self.get_image(130, 272, 14, 16)) # Right skid [5] + + #Images for black mario (for invincible animation)# + + self.right_small_black_frames.append( + self.get_image(178, 176, 12, 16)) # Right standing [0] + self.right_small_black_frames.append( + self.get_image(80, 176, 15, 16)) # Right walking 1 [1] + self.right_small_black_frames.append( + self.get_image(96, 176, 16, 16)) # Right walking 2 [2] + self.right_small_black_frames.append( + self.get_image(112, 176, 15, 16)) # Right walking 3 [3] + self.right_small_black_frames.append( + self.get_image(144, 176, 16, 16)) # Right jump [4] + self.right_small_black_frames.append( + self.get_image(130, 176, 14, 16)) # Right skid [5] + + + #Images for normal big Mario + + self.right_big_normal_frames.append( + self.get_image(176, 0, 16, 32)) # Right standing [0] + self.right_big_normal_frames.append( + self.get_image(81, 0, 16, 32)) # Right walking 1 [1] + self.right_big_normal_frames.append( + self.get_image(97, 0, 15, 32)) # Right walking 2 [2] + self.right_big_normal_frames.append( + self.get_image(113, 0, 15, 32)) # Right walking 3 [3] + self.right_big_normal_frames.append( + self.get_image(144, 0, 16, 32)) # Right jump [4] + self.right_big_normal_frames.append( + self.get_image(128, 0, 16, 32)) # Right skid [5] + self.right_big_normal_frames.append( + self.get_image(336, 0, 16, 32)) # Right throwing [6] + self.right_big_normal_frames.append( + self.get_image(160, 10, 16, 22)) # Right crouching [7] + self.right_big_normal_frames.append( + self.get_image(272, 2, 16, 29)) # Transition big to small [8] + self.right_big_normal_frames.append( + self.get_image(193, 2, 16, 30)) # Frame 1 of flag pole slide [9] + self.right_big_normal_frames.append( + self.get_image(209, 2, 16, 29)) # Frame 2 of flag pole slide [10] + + #Images for green big Mario# + + self.right_big_green_frames.append( + self.get_image(176, 192, 16, 32)) # Right standing [0] + self.right_big_green_frames.append( + self.get_image(81, 192, 16, 32)) # Right walking 1 [1] + self.right_big_green_frames.append( + self.get_image(97, 192, 15, 32)) # Right walking 2 [2] + self.right_big_green_frames.append( + self.get_image(113, 192, 15, 32)) # Right walking 3 [3] + self.right_big_green_frames.append( + self.get_image(144, 192, 16, 32)) # Right jump [4] + self.right_big_green_frames.append( + self.get_image(128, 192, 16, 32)) # Right skid [5] + self.right_big_green_frames.append( + self.get_image(336, 192, 16, 32)) # Right throwing [6] + self.right_big_green_frames.append( + self.get_image(160, 202, 16, 22)) # Right Crouching [7] + + #Images for red big Mario# + + self.right_big_red_frames.append( + self.get_image(176, 240, 16, 32)) # Right standing [0] + self.right_big_red_frames.append( + self.get_image(81, 240, 16, 32)) # Right walking 1 [1] + self.right_big_red_frames.append( + self.get_image(97, 240, 15, 32)) # Right walking 2 [2] + self.right_big_red_frames.append( + self.get_image(113, 240, 15, 32)) # Right walking 3 [3] + self.right_big_red_frames.append( + self.get_image(144, 240, 16, 32)) # Right jump [4] + self.right_big_red_frames.append( + self.get_image(128, 240, 16, 32)) # Right skid [5] + self.right_big_red_frames.append( + self.get_image(336, 240, 16, 32)) # Right throwing [6] + self.right_big_red_frames.append( + self.get_image(160, 250, 16, 22)) # Right crouching [7] + + #Images for black big Mario# + + self.right_big_black_frames.append( + self.get_image(176, 144, 16, 32)) # Right standing [0] + self.right_big_black_frames.append( + self.get_image(81, 144, 16, 32)) # Right walking 1 [1] + self.right_big_black_frames.append( + self.get_image(97, 144, 15, 32)) # Right walking 2 [2] + self.right_big_black_frames.append( + self.get_image(113, 144, 15, 32)) # Right walking 3 [3] + self.right_big_black_frames.append( + self.get_image(144, 144, 16, 32)) # Right jump [4] + self.right_big_black_frames.append( + self.get_image(128, 144, 16, 32)) # Right skid [5] + self.right_big_black_frames.append( + self.get_image(336, 144, 16, 32)) # Right throwing [6] + self.right_big_black_frames.append( + self.get_image(160, 154, 16, 22)) # Right Crouching [7] + + + #Images for Fire Mario# + + self.right_fire_frames.append( + self.get_image(176, 48, 16, 32)) # Right standing [0] + self.right_fire_frames.append( + self.get_image(81, 48, 16, 32)) # Right walking 1 [1] + self.right_fire_frames.append( + self.get_image(97, 48, 15, 32)) # Right walking 2 [2] + self.right_fire_frames.append( + self.get_image(113, 48, 15, 32)) # Right walking 3 [3] + self.right_fire_frames.append( + self.get_image(144, 48, 16, 32)) # Right jump [4] + self.right_fire_frames.append( + self.get_image(128, 48, 16, 32)) # Right skid [5] + self.right_fire_frames.append( + self.get_image(336, 48, 16, 32)) # Right throwing [6] + self.right_fire_frames.append( + self.get_image(160, 58, 16, 22)) # Right crouching [7] + self.right_fire_frames.append( + self.get_image(0, 0, 0, 0)) # Place holder [8] + self.right_fire_frames.append( + self.get_image(193, 50, 16, 29)) # Frame 1 of flag pole slide [9] + self.right_fire_frames.append( + self.get_image(209, 50, 16, 29)) # Frame 2 of flag pole slide [10] + + + #The left image frames are numbered the same as the right + #frames but are simply reversed. + + for frame in self.right_small_normal_frames: + new_image = pg.transform.flip(frame, True, False) + self.left_small_normal_frames.append(new_image) + + for frame in self.right_small_green_frames: + new_image = pg.transform.flip(frame, True, False) + self.left_small_green_frames.append(new_image) + + for frame in self.right_small_red_frames: + new_image = pg.transform.flip(frame, True, False) + self.left_small_red_frames.append(new_image) + + for frame in self.right_small_black_frames: + new_image = pg.transform.flip(frame, True, False) + self.left_small_black_frames.append(new_image) + + for frame in self.right_big_normal_frames: + new_image = pg.transform.flip(frame, True, False) + self.left_big_normal_frames.append(new_image) + + for frame in self.right_big_green_frames: + new_image = pg.transform.flip(frame, True, False) + self.left_big_green_frames.append(new_image) + + for frame in self.right_big_red_frames: + new_image = pg.transform.flip(frame, True, False) + self.left_big_red_frames.append(new_image) + + for frame in self.right_big_black_frames: + new_image = pg.transform.flip(frame, True, False) + self.left_big_black_frames.append(new_image) + + for frame in self.right_fire_frames: + new_image = pg.transform.flip(frame, True, False) + self.left_fire_frames.append(new_image) + + + self.normal_small_frames = [self.right_small_normal_frames, + self.left_small_normal_frames] + + self.green_small_frames = [self.right_small_green_frames, + self.left_small_green_frames] + + self.red_small_frames = [self.right_small_red_frames, + self.left_small_red_frames] + + self.black_small_frames = [self.right_small_black_frames, + self.left_small_black_frames] + + self.invincible_small_frames_list = [self.normal_small_frames, + self.green_small_frames, + self.red_small_frames, + self.black_small_frames] + + self.normal_big_frames = [self.right_big_normal_frames, + self.left_big_normal_frames] + + self.green_big_frames = [self.right_big_green_frames, + self.left_big_green_frames] + + self.red_big_frames = [self.right_big_red_frames, + self.left_big_red_frames] + + self.black_big_frames = [self.right_big_black_frames, + self.left_big_black_frames] + + self.fire_frames = [self.right_fire_frames, + self.left_fire_frames] + + self.invincible_big_frames_list = [self.normal_big_frames, + self.green_big_frames, + self.red_big_frames, + self.black_big_frames] + + self.all_images = [self.right_big_normal_frames, + self.right_big_black_frames, + self.right_big_red_frames, + self.right_big_green_frames, + self.right_small_normal_frames, + self.right_small_green_frames, + self.right_small_red_frames, + self.right_small_black_frames, + self.left_big_normal_frames, + self.left_big_black_frames, + self.left_big_red_frames, + self.left_big_green_frames, + self.left_small_normal_frames, + self.left_small_red_frames, + self.left_small_green_frames, + self.left_small_black_frames] + + + self.right_frames = self.normal_small_frames[0] + self.left_frames = self.normal_small_frames[1] + + + def get_image(self, x, y, width, height): + """Extracts image from sprite sheet""" + image = pg.Surface([width, height]) + 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, keys, game_info, fire_group): + """Updates Mario's states and animations once per frame""" + self.current_time = game_info[c.CURRENT_TIME] + self.handle_state(keys, fire_group) + self.check_for_special_state() + self.animation() + + + def handle_state(self, keys, fire_group): + """Determines Mario's behavior based on his state""" + if self.state == c.STAND: + self.standing(keys, fire_group) + elif self.state == c.WALK: + self.walking(keys, fire_group) + elif self.state == c.JUMP: + self.jumping(keys, fire_group) + elif self.state == c.FALL: + self.falling(keys, fire_group) + elif self.state == c.DEATH_JUMP: + self.jumping_to_death() + elif self.state == c.SMALL_TO_BIG: + self.changing_to_big() + elif self.state == c.BIG_TO_FIRE: + self.changing_to_fire() + elif self.state == c.BIG_TO_SMALL: + self.changing_to_small() + elif self.state == c.FLAGPOLE: + self.flag_pole_sliding() + elif self.state == c.BOTTOM_OF_POLE: + self.sitting_at_bottom_of_pole() + elif self.state == c.WALKING_TO_CASTLE: + self.walking_to_castle() + elif self.state == c.END_OF_LEVEL_FALL: + self.falling_at_end_of_level() + + + def standing(self, keys, fire_group): + """This function is called if Mario is standing still""" + self.check_to_allow_jump(keys) + self.check_to_allow_fireball(keys) + + self.frame_index = 0 + self.x_vel = 0 + self.y_vel = 0 + + if keys[tools.keybinding['action']]: + if self.fire and self.allow_fireball: + self.shoot_fireball(fire_group) + + if keys[tools.keybinding['down']]: + self.crouching = True + + if keys[tools.keybinding['left']]: + self.facing_right = False + self.get_out_of_crouch() + self.state = c.WALK + elif keys[tools.keybinding['right']]: + self.facing_right = True + self.get_out_of_crouch() + self.state = c.WALK + elif keys[tools.keybinding['jump']]: + if self.allow_jump: + if self.big: + setup.SFX['big_jump'].play() + else: + setup.SFX['small_jump'].play() + self.state = c.JUMP + self.y_vel = c.JUMP_VEL + else: + self.state = c.STAND + + if not keys[tools.keybinding['down']]: + self.get_out_of_crouch() + + + def get_out_of_crouch(self): + """Get out of crouch""" + bottom = self.rect.bottom + left = self.rect.x + if self.facing_right: + self.image = self.right_frames[0] + else: + self.image = self.left_frames[0] + self.rect = self.image.get_rect() + self.rect.bottom = bottom + self.rect.x = left + self.crouching = False + + + def check_to_allow_jump(self, keys): + """Check to allow Mario to jump""" + if not keys[tools.keybinding['jump']]: + self.allow_jump = True + + + def check_to_allow_fireball(self, keys): + """Check to allow the shooting of a fireball""" + if not keys[tools.keybinding['action']]: + self.allow_fireball = True + + + def shoot_fireball(self, powerup_group): + """Shoots fireball, allowing no more than two to exist at once""" + setup.SFX['fireball'].play() + self.fireball_count = self.count_number_of_fireballs(powerup_group) + + if (self.current_time - self.last_fireball_time) > 200: + if self.fireball_count < 2: + self.allow_fireball = False + powerup_group.add( + powerups.FireBall(self.rect.right, self.rect.y, self.facing_right)) + self.last_fireball_time = self.current_time + + self.frame_index = 6 + if self.facing_right: + self.image = self.right_frames[self.frame_index] + else: + self.image = self.left_frames[self.frame_index] + + + def count_number_of_fireballs(self, powerup_group): + """Count number of fireballs that exist in the level""" + fireball_list = [] + + for powerup in powerup_group: + if powerup.name == c.FIREBALL: + fireball_list.append(powerup) + + return len(fireball_list) + + + def walking(self, keys, fire_group): + """This function is called when Mario is in a walking state + It changes the frame, checks for holding down the run button, + checks for a jump, then adjusts the state if necessary""" + + self.check_to_allow_jump(keys) + self.check_to_allow_fireball(keys) + + if self.frame_index == 0: + self.frame_index += 1 + self.walking_timer = self.current_time + else: + if (self.current_time - self.walking_timer > + self.calculate_animation_speed()): + if self.frame_index < 3: + self.frame_index += 1 + else: + self.frame_index = 1 + + self.walking_timer = self.current_time + + if keys[tools.keybinding['action']]: + self.max_x_vel = c.MAX_RUN_SPEED + self.x_accel = c.RUN_ACCEL + if self.fire and self.allow_fireball: + self.shoot_fireball(fire_group) + else: + self.max_x_vel = c.MAX_WALK_SPEED + self.x_accel = c.WALK_ACCEL + + if keys[tools.keybinding['jump']]: + if self.allow_jump: + if self.big: + setup.SFX['big_jump'].play() + else: + setup.SFX['small_jump'].play() + self.state = c.JUMP + if self.x_vel > 4.5 or self.x_vel < -4.5: + self.y_vel = c.JUMP_VEL - .5 + else: + self.y_vel = c.JUMP_VEL + + + if keys[tools.keybinding['left']]: + self.get_out_of_crouch() + self.facing_right = False + if self.x_vel > 0: + self.frame_index = 5 + self.x_accel = c.SMALL_TURNAROUND + else: + self.x_accel = c.WALK_ACCEL + + if self.x_vel > (self.max_x_vel * -1): + self.x_vel -= self.x_accel + if self.x_vel > -0.5: + self.x_vel = -0.5 + elif self.x_vel < (self.max_x_vel * -1): + self.x_vel += self.x_accel + + elif keys[tools.keybinding['right']]: + self.get_out_of_crouch() + self.facing_right = True + if self.x_vel < 0: + self.frame_index = 5 + self.x_accel = c.SMALL_TURNAROUND + else: + self.x_accel = c.WALK_ACCEL + + if self.x_vel < self.max_x_vel: + self.x_vel += self.x_accel + if self.x_vel < 0.5: + self.x_vel = 0.5 + elif self.x_vel > self.max_x_vel: + self.x_vel -= self.x_accel + + else: + if self.facing_right: + if self.x_vel > 0: + self.x_vel -= self.x_accel + else: + self.x_vel = 0 + self.state = c.STAND + else: + if self.x_vel < 0: + self.x_vel += self.x_accel + else: + self.x_vel = 0 + self.state = c.STAND + + + def calculate_animation_speed(self): + """Used to make walking animation speed be in relation to + Mario's x-vel""" + if self.x_vel == 0: + animation_speed = 130 + elif self.x_vel > 0: + animation_speed = 130 - (self.x_vel * (13)) + else: + animation_speed = 130 - (self.x_vel * (13) * -1) + + return animation_speed + + + def jumping(self, keys, fire_group): + """Called when Mario is in a JUMP state.""" + self.allow_jump = False + self.frame_index = 4 + self.gravity = c.JUMP_GRAVITY + self.y_vel += self.gravity + self.check_to_allow_fireball(keys) + + if self.y_vel >= 0 and self.y_vel < self.max_y_vel: + self.gravity = c.GRAVITY + self.state = c.FALL + + if keys[tools.keybinding['left']]: + if self.x_vel > (self.max_x_vel * - 1): + self.x_vel -= self.x_accel + + elif keys[tools.keybinding['right']]: + if self.x_vel < self.max_x_vel: + self.x_vel += self.x_accel + + if not keys[tools.keybinding['jump']]: + self.gravity = c.GRAVITY + self.state = c.FALL + + if keys[tools.keybinding['action']]: + if self.fire and self.allow_fireball: + self.shoot_fireball(fire_group) + + + def falling(self, keys, fire_group): + """Called when Mario is in a FALL state""" + self.check_to_allow_fireball(keys) + if self.y_vel < c.MAX_Y_VEL: + self.y_vel += self.gravity + + if keys[tools.keybinding['left']]: + if self.x_vel > (self.max_x_vel * - 1): + self.x_vel -= self.x_accel + + elif keys[tools.keybinding['right']]: + if self.x_vel < self.max_x_vel: + self.x_vel += self.x_accel + + if keys[tools.keybinding['action']]: + if self.fire and self.allow_fireball: + self.shoot_fireball(fire_group) + + + def jumping_to_death(self): + """Called when Mario is in a DEATH_JUMP state""" + if self.death_timer == 0: + self.death_timer = self.current_time + elif (self.current_time - self.death_timer) > 500: + self.rect.y += self.y_vel + self.y_vel += self.gravity + + + def start_death_jump(self, game_info): + """Used to put Mario in a DEATH_JUMP state""" + self.dead = True + game_info[c.MARIO_DEAD] = True + self.y_vel = -11 + self.gravity = .5 + self.frame_index = 6 + self.image = self.right_frames[self.frame_index] + self.state = c.DEATH_JUMP + self.in_transition_state = True + + + def changing_to_big(self): + """Changes Mario's image attribute based on time while + transitioning to big""" + self.in_transition_state = True + + if self.transition_timer == 0: + self.transition_timer = self.current_time + elif self.timer_between_these_two_times(135, 200): + self.set_mario_to_middle_image() + elif self.timer_between_these_two_times(200, 365): + self.set_mario_to_small_image() + elif self.timer_between_these_two_times(365, 430): + self.set_mario_to_middle_image() + elif self.timer_between_these_two_times(430, 495): + self.set_mario_to_small_image() + elif self.timer_between_these_two_times(495, 560): + self.set_mario_to_middle_image() + elif self.timer_between_these_two_times(560, 625): + self.set_mario_to_big_image() + elif self.timer_between_these_two_times(625, 690): + self.set_mario_to_small_image() + elif self.timer_between_these_two_times(690, 755): + self.set_mario_to_middle_image() + elif self.timer_between_these_two_times(755, 820): + self.set_mario_to_big_image() + elif self.timer_between_these_two_times(820, 885): + self.set_mario_to_small_image() + elif self.timer_between_these_two_times(885, 950): + self.set_mario_to_big_image() + self.state = c.WALK + self.in_transition_state = False + self.transition_timer = 0 + self.become_big() + + + def timer_between_these_two_times(self,start_time, end_time): + """Checks if the timer is at the right time for the action. Reduces + the ugly code.""" + if (self.current_time - self.transition_timer) >= start_time\ + and (self.current_time - self.transition_timer) < end_time: + return True + + + def set_mario_to_middle_image(self): + """During a change from small to big, sets mario's image to the + transition/middle size""" + if self.facing_right: + self.image = self.normal_small_frames[0][7] + else: + self.image = self.normal_small_frames[1][7] + bottom = self.rect.bottom + centerx = self.rect.centerx + self.rect = self.image.get_rect() + self.rect.bottom = bottom + self.rect.centerx = centerx + + + def set_mario_to_small_image(self): + """During a change from small to big, sets mario's image to small""" + if self.facing_right: + self.image = self.normal_small_frames[0][0] + else: + self.image = self.normal_small_frames[1][0] + bottom = self.rect.bottom + centerx = self.rect.centerx + self.rect = self.image.get_rect() + self.rect.bottom = bottom + self.rect.centerx = centerx + + + def set_mario_to_big_image(self): + """During a change from small to big, sets mario's image to big""" + if self.facing_right: + self.image = self.normal_big_frames[0][0] + else: + self.image = self.normal_big_frames[1][0] + bottom = self.rect.bottom + centerx = self.rect.centerx + self.rect = self.image.get_rect() + self.rect.bottom = bottom + self.rect.centerx = centerx + + + def become_big(self): + self.big = True + self.right_frames = self.right_big_normal_frames + self.left_frames = self.left_big_normal_frames + bottom = self.rect.bottom + left = self.rect.x + image = self.right_frames[0] + self.rect = image.get_rect() + self.rect.bottom = bottom + self.rect.x = left + + + def changing_to_fire(self): + """Called when Mario is in a BIG_TO_FIRE state (i.e. when + he obtains a fire flower""" + self.in_transition_state = True + + if self.facing_right: + frames = [self.right_fire_frames[3], + self.right_big_green_frames[3], + self.right_big_red_frames[3], + self.right_big_black_frames[3]] + else: + frames = [self.left_fire_frames[3], + self.left_big_green_frames[3], + self.left_big_red_frames[3], + self.left_big_black_frames[3]] + + if self.fire_transition_timer == 0: + self.fire_transition_timer = self.current_time + elif (self.current_time - self.fire_transition_timer) > 65 and (self.current_time - self.fire_transition_timer) < 130: + self.image = frames[0] + elif (self.current_time - self.fire_transition_timer) < 195: + self.image = frames[1] + elif (self.current_time - self.fire_transition_timer) < 260: + self.image = frames[2] + elif (self.current_time - self.fire_transition_timer) < 325: + self.image = frames[3] + elif (self.current_time - self.fire_transition_timer) < 390: + self.image = frames[0] + elif (self.current_time - self.fire_transition_timer) < 455: + self.image = frames[1] + elif (self.current_time - self.fire_transition_timer) < 520: + self.image = frames[2] + elif (self.current_time - self.fire_transition_timer) < 585: + self.image = frames[3] + elif (self.current_time - self.fire_transition_timer) < 650: + self.image = frames[0] + elif (self.current_time - self.fire_transition_timer) < 715: + self.image = frames[1] + elif (self.current_time - self.fire_transition_timer) < 780: + self.image = frames[2] + elif (self.current_time - self.fire_transition_timer) < 845: + self.image = frames[3] + elif (self.current_time - self.fire_transition_timer) < 910: + self.image = frames[0] + elif (self.current_time - self.fire_transition_timer) < 975: + self.image = frames[1] + elif (self.current_time - self.fire_transition_timer) < 1040: + self.image = frames[2] + self.fire = True + self.in_transition_state = False + self.state = c.WALK + self.transition_timer = 0 + + + def changing_to_small(self): + """Mario's state and animation when he shrinks from big to small + after colliding with an enemy""" + self.in_transition_state = True + self.hurt_invincible = True + self.state = c.BIG_TO_SMALL + + if self.facing_right: + frames = [self.right_big_normal_frames[4], + self.right_big_normal_frames[8], + self.right_small_normal_frames[8] + ] + else: + frames = [self.left_big_normal_frames[4], + self.left_big_normal_frames[8], + self.left_small_normal_frames[8] + ] + + if self.transition_timer == 0: + self.transition_timer = self.current_time + elif (self.current_time - self.transition_timer) < 265: + self.image = frames[0] + self.hurt_invincible_check() + self.adjust_rect() + elif (self.current_time - self.transition_timer) < 330: + self.image = frames[1] + self.hurt_invincible_check() + self.adjust_rect() + elif (self.current_time - self.transition_timer) < 395: + self.image = frames[2] + self.hurt_invincible_check() + self.adjust_rect() + elif (self.current_time - self.transition_timer) < 460: + self.image = frames[1] + self.hurt_invincible_check() + self.adjust_rect() + elif (self.current_time - self.transition_timer) < 525: + self.image = frames[2] + self.hurt_invincible_check() + self.adjust_rect() + elif (self.current_time - self.transition_timer) < 590: + self.image = frames[1] + self.hurt_invincible_check() + self.adjust_rect() + elif (self.current_time - self.transition_timer) < 655: + self.image = frames[2] + self.hurt_invincible_check() + self.adjust_rect() + elif (self.current_time - self.transition_timer) < 720: + self.image = frames[1] + self.hurt_invincible_check() + self.adjust_rect() + elif (self.current_time - self.transition_timer) < 785: + self.image = frames[2] + self.hurt_invincible_check() + self.adjust_rect() + elif (self.current_time - self.transition_timer) < 850: + self.image = frames[1] + self.hurt_invincible_check() + self.adjust_rect() + elif (self.current_time - self.transition_timer) < 915: + self.image = frames[2] + self.adjust_rect() + self.in_transition_state = False + self.state = c.WALK + self.big = False + self.transition_timer = 0 + self.hurt_invisible_timer = 0 + self.become_small() + + + def adjust_rect(self): + """Makes sure new Rect has the same bottom and left + location as previous Rect""" + x = self.rect.x + bottom = self.rect.bottom + self.rect = self.image.get_rect() + self.rect.x = x + self.rect.bottom = bottom + + + def become_small(self): + self.big = False + self.right_frames = self.right_small_normal_frames + self.left_frames = self.left_small_normal_frames + bottom = self.rect.bottom + left = self.rect.x + image = self.right_frames[0] + self.rect = image.get_rect() + self.rect.bottom = bottom + self.rect.x = left + + + def flag_pole_sliding(self): + """State where Mario is sliding down the flag pole""" + self.state = c.FLAGPOLE + self.in_transition_state = True + self.x_vel = 0 + self.y_vel = 0 + + if self.flag_pole_timer == 0: + self.flag_pole_timer = self.current_time + elif self.rect.bottom < 493: + if (self.current_time - self.flag_pole_timer) < 65: + self.image = self.right_frames[9] + elif (self.current_time - self.flag_pole_timer) < 130: + self.image = self.right_frames[10] + elif (self.current_time - self.flag_pole_timer) >= 130: + self.flag_pole_timer = self.current_time + + self.rect.right = self.flag_pole_right + self.y_vel = 5 + self.rect.y += self.y_vel + + if self.rect.bottom >= 488: + self.flag_pole_timer = self.current_time + + elif self.rect.bottom >= 493: + self.image = self.right_frames[10] + + + def sitting_at_bottom_of_pole(self): + """State when mario is at the bottom of the flag pole""" + if self.flag_pole_timer == 0: + self.flag_pole_timer = self.current_time + self.image = self.left_frames[10] + elif (self.current_time - self.flag_pole_timer) < 210: + self.image = self.left_frames[10] + else: + self.in_transition_state = False + if self.rect.bottom < 485: + self.state = c.END_OF_LEVEL_FALL + else: + self.state = c.WALKING_TO_CASTLE + + + def set_state_to_bottom_of_pole(self): + """Sets Mario to the BOTTOM_OF_POLE state""" + self.image = self.left_frames[9] + right = self.rect.right + #self.rect.bottom = 493 + self.rect.x = right + if self.big: + self.rect.x -= 10 + self.flag_pole_timer = 0 + self.state = c.BOTTOM_OF_POLE + + + def walking_to_castle(self): + """State when Mario walks to the castle to end the level""" + self.max_x_vel = 5 + self.x_accel = c.WALK_ACCEL + + if self.x_vel < self.max_x_vel: + self.x_vel += self.x_accel + + if (self.walking_timer == 0 or (self.current_time - self.walking_timer) > 200): + self.walking_timer = self.current_time + + elif (self.current_time - self.walking_timer) > \ + self.calculate_animation_speed(): + if self.frame_index < 3: + self.frame_index += 1 + else: + self.frame_index = 1 + self.walking_timer = self.current_time + + + def falling_at_end_of_level(self, *args): + """State when Mario is falling from the flag pole base""" + self.y_vel += c.GRAVITY + + + + def check_for_special_state(self): + """Determines if Mario is invincible, Fire Mario or recently hurt""" + self.check_if_invincible() + self.check_if_fire() + self.check_if_hurt_invincible() + self.check_if_crouching() + + + def check_if_invincible(self): + if self.invincible: + if ((self.current_time - self.invincible_start_timer) < 10000): + self.losing_invincibility = False + self.change_frame_list(30) + elif ((self.current_time - self.invincible_start_timer) < 12000): + self.losing_invincibility = True + self.change_frame_list(100) + else: + self.losing_invincibility = False + self.invincible = False + else: + if self.big: + self.right_frames = self.right_big_normal_frames + self.left_frames = self.left_big_normal_frames + else: + self.right_frames = self.invincible_small_frames_list[0][0] + self.left_frames = self.invincible_small_frames_list[0][1] + + + def change_frame_list(self, frame_switch_speed): + if (self.current_time - self.invincible_animation_timer) > frame_switch_speed: + if self.invincible_index < (len(self.invincible_small_frames_list) - 1): + self.invincible_index += 1 + else: + self.invincible_index = 0 + + if self.big: + frames = self.invincible_big_frames_list[self.invincible_index] + else: + frames = self.invincible_small_frames_list[self.invincible_index] + + self.right_frames = frames[0] + self.left_frames = frames[1] + + self.invincible_animation_timer = self.current_time + + + def check_if_fire(self): + if self.fire and self.invincible == False: + self.right_frames = self.fire_frames[0] + self.left_frames = self.fire_frames[1] + + + def check_if_hurt_invincible(self): + """Check if Mario is still temporarily invincible after getting hurt""" + if self.hurt_invincible and self.state != c.BIG_TO_SMALL: + if self.hurt_invisible_timer2 == 0: + self.hurt_invisible_timer2 = self.current_time + elif (self.current_time - self.hurt_invisible_timer2) < 2000: + self.hurt_invincible_check() + else: + self.hurt_invincible = False + self.hurt_invisible_timer = 0 + self.hurt_invisible_timer2 = 0 + for frames in self.all_images: + for image in frames: + image.set_alpha(255) + + + def hurt_invincible_check(self): + """Makes Mario invincible on a fixed interval""" + if self.hurt_invisible_timer == 0: + self.hurt_invisible_timer = self.current_time + elif (self.current_time - self.hurt_invisible_timer) < 35: + self.image.set_alpha(0) + elif (self.current_time - self.hurt_invisible_timer) < 70: + self.image.set_alpha(255) + self.hurt_invisible_timer = self.current_time + + + def check_if_crouching(self): + """Checks if mario is crouching""" + if self.crouching and self.big: + bottom = self.rect.bottom + left = self.rect.x + if self.facing_right: + self.image = self.right_frames[7] + else: + self.image = self.left_frames[7] + self.rect = self.image.get_rect() + self.rect.bottom = bottom + self.rect.x = left + + + def animation(self): + """Adjusts Mario's image for animation""" + if self.state == c.DEATH_JUMP \ + or self.state == c.SMALL_TO_BIG \ + or self.state == c.BIG_TO_FIRE \ + or self.state == c.BIG_TO_SMALL \ + or self.state == c.FLAGPOLE \ + or self.state == c.BOTTOM_OF_POLE \ + or self.crouching: + pass + elif self.facing_right: + self.image = self.right_frames[self.frame_index] + else: + self.image = self.left_frames[self.frame_index] + + + + + + + + + + + diff --git a/pythonProject1/data/components/powerups.py b/pythonProject1/data/components/powerups.py new file mode 100644 index 0000000..31608d5 --- /dev/null +++ b/pythonProject1/data/components/powerups.py @@ -0,0 +1,360 @@ + +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() + + + + + + + + + + diff --git a/pythonProject1/data/components/score.py b/pythonProject1/data/components/score.py new file mode 100644 index 0000000..09fcdf9 --- /dev/null +++ b/pythonProject1/data/components/score.py @@ -0,0 +1,125 @@ + +import pygame as pg +from .. import setup +from .. import constants as c + + +class Digit(pg.sprite.Sprite): + """Individual digit for score""" + def __init__(self, image): + super(Digit, self).__init__() + self.image = image + self.rect = image.get_rect() + + +class Score(object): + """Scores that appear, float up, and disappear""" + def __init__(self, x, y, score, flag_pole=False): + self.x = x + self.y = y + if flag_pole: + self.y_vel = -4 + else: + self.y_vel = -3 + self.sprite_sheet = setup.GFX['item_objects'] + self.create_image_dict() + self.score_string = str(score) + self.create_digit_list() + self.flag_pole_score = flag_pole + + + def create_image_dict(self): + """Creates the dictionary for all the number images needed""" + self.image_dict = {} + + image0 = self.get_image(1, 168, 3, 8) + image1 = self.get_image(5, 168, 3, 8) + image2 = self.get_image(8, 168, 4, 8) + image4 = self.get_image(12, 168, 4, 8) + image5 = self.get_image(16, 168, 5, 8) + image8 = self.get_image(20, 168, 4, 8) + image9 = self.get_image(32, 168, 5, 8) + image10 = self.get_image(37, 168, 6, 8) + image11 = self.get_image(43, 168, 5, 8) + + self.image_dict['0'] = image0 + self.image_dict['1'] = image1 + self.image_dict['2'] = image2 + self.image_dict['4'] = image4 + self.image_dict['5'] = image5 + self.image_dict['8'] = image8 + self.image_dict['3'] = image9 + self.image_dict['7'] = image10 + self.image_dict['9'] = image11 + + + def get_image(self, x, y, width, height): + """Extracts image from 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.BRICK_SIZE_MULTIPLIER), + int(rect.height*c.BRICK_SIZE_MULTIPLIER))) + return image + + + def create_digit_list(self): + """Creates the group of images based on score received""" + self.digit_list = [] + self.digit_group = pg.sprite.Group() + + for digit in self.score_string: + self.digit_list.append(Digit(self.image_dict[digit])) + + self.set_rects_for_images() + + + def set_rects_for_images(self): + """Set the rect attributes for each image in self.image_list""" + for i, digit in enumerate(self.digit_list): + digit.rect = digit.image.get_rect() + digit.rect.x = self.x + (i * 10) + digit.rect.y = self.y + + + def update(self, score_list, level_info): + """Updates score movement""" + for number in self.digit_list: + number.rect.y += self.y_vel + + if score_list: + self.check_to_delete_floating_scores(score_list, level_info) + + if self.flag_pole_score: + if self.digit_list[0].rect.y <= 120: + self.y_vel = 0 + + + def draw(self, screen): + """Draws score numbers onto screen""" + for digit in self.digit_list: + screen.blit(digit.image, digit.rect) + + + def check_to_delete_floating_scores(self, score_list, level_info): + """Check if scores need to be deleted""" + for i, score in enumerate(score_list): + if int(score.score_string) == 1000: + if (score.y - score.digit_list[0].rect.y) > 130: + score_list.pop(i) + + else: + if (score.y - score.digit_list[0].rect.y) > 75: + score_list.pop(i) + + + + + + + + + diff --git a/pythonProject1/data/constants.py b/pythonProject1/data/constants.py new file mode 100644 index 0000000..beea4a3 --- /dev/null +++ b/pythonProject1/data/constants.py @@ -0,0 +1,177 @@ + + +SCREEN_HEIGHT = 600 +SCREEN_WIDTH = 800 + +SCREEN_SIZE = (SCREEN_WIDTH,SCREEN_HEIGHT) + +ORIGINAL_CAPTION = "Super Mario Bros 1-1" + +## COLORS ## + +# R G B +GRAY = (100, 100, 100) +NAVYBLUE = ( 60, 60, 100) +WHITE = (255, 255, 255) +RED = (255, 0, 0) +GREEN = ( 0, 255, 0) +FOREST_GREEN = ( 31, 162, 35) +BLUE = ( 0, 0, 255) +SKY_BLUE = ( 39, 145, 251) +YELLOW = (255, 255, 0) +ORANGE = (255, 128, 0) +PURPLE = (255, 0, 255) +CYAN = ( 0, 255, 255) +BLACK = ( 0, 0, 0) +NEAR_BLACK = ( 19, 15, 48) +COMBLUE = (233, 232, 255) +GOLD = (255, 215, 0) + +BGCOLOR = WHITE + +SIZE_MULTIPLIER = 2.5 +BRICK_SIZE_MULTIPLIER = 2.69 +BACKGROUND_MULTIPLER = 2.679 +GROUND_HEIGHT = SCREEN_HEIGHT - 62 + +#MARIO FORCES +WALK_ACCEL = .15 +RUN_ACCEL = 20 +SMALL_TURNAROUND = .35 + +GRAVITY = 1.01 +JUMP_GRAVITY = .31 +JUMP_VEL = -10 +FAST_JUMP_VEL = -12.5 +MAX_Y_VEL = 11 + +MAX_RUN_SPEED = 800 +MAX_WALK_SPEED = 6 + + +#Mario States + +STAND = 'standing' +WALK = 'walk' +JUMP = 'jump' +FALL = 'fall' +SMALL_TO_BIG = 'small to big' +BIG_TO_FIRE = 'big to fire' +BIG_TO_SMALL = 'big to small' +FLAGPOLE = 'flag pole' +WALKING_TO_CASTLE = 'walking to castle' +END_OF_LEVEL_FALL = 'end of level fall' + + +#GOOMBA Stuff + +LEFT = 'left' +RIGHT = 'right' +JUMPED_ON = 'jumped on' +DEATH_JUMP = 'death jump' + +#KOOPA STUFF + +SHELL_SLIDE = 'shell slide' + +#BRICK STATES + +RESTING = 'resting' +BUMPED = 'bumped' + +#COIN STATES +OPENED = 'opened' + +#MUSHROOM STATES + +REVEAL = 'reveal' +SLIDE = 'slide' + +#COIN STATES + +SPIN = 'spin' + +#STAR STATES + +BOUNCE = 'bounce' + +#FIRE STATES + +FLYING = 'flying' +BOUNCING = 'bouncing' +EXPLODING = 'exploding' + +#Brick and coin box contents + +MUSHROOM = 'mushroom' +STAR = 'star' +FIREFLOWER = 'fireflower' +SIXCOINS = '6coins' +COIN = 'coin' +LIFE_MUSHROOM = '1up_mushroom' + +FIREBALL = 'fireball' + +#LIST of ENEMIES + +GOOMBA = 'goomba' +KOOPA = 'koopa' + +#LEVEL STATES + +FROZEN = 'frozen' +NOT_FROZEN = 'not frozen' +IN_CASTLE = 'in castle' +FLAG_AND_FIREWORKS = 'flag and fireworks' + +#FLAG STATE +TOP_OF_POLE = 'top of pole' +SLIDE_DOWN = 'slide down' +BOTTOM_OF_POLE = 'bottom of pole' + +#1UP score +ONEUP = '379' + +#MAIN MENU CURSOR STATES +PLAYER1 = '1 player' +PLAYER2 = '2 player' + +#OVERHEAD INFO STATES +MAIN_MENU = 'main menu' +LOAD_SCREEN = 'loading screen' +LEVEL = 'level' +GAME_OVER = 'game over' +FAST_COUNT_DOWN = 'fast count down' +END_OF_LEVEL = 'end of level' + + +#GAME INFO DICTIONARY KEYS +COIN_TOTAL = 'coin total' +SCORE = 'score' +TOP_SCORE = 'top score' +LIVES = 'lives' +CURRENT_TIME = 'current time' +LEVEL_STATE = 'level state' +CAMERA_START_X = 'camera start x' +MARIO_DEAD = 'mario dead' + +#STATES FOR ENTIRE GAME +MAIN_MENU = 'main menu' +LOAD_SCREEN = 'load screen' +TIME_OUT = 'time out' +GAME_OVER = 'game over' +LEVEL1 = 'level1' + +#SOUND STATEZ +NORMAL = 'normal' +STAGE_CLEAR = 'stage clear' +WORLD_CLEAR = 'world clear' +TIME_WARNING = 'time warning' +SPED_UP_NORMAL = 'sped up normal' +MARIO_INVINCIBLE = 'mario invincible' + + + + + + diff --git a/pythonProject1/data/game_sound.py b/pythonProject1/data/game_sound.py new file mode 100644 index 0000000..bba2e31 --- /dev/null +++ b/pythonProject1/data/game_sound.py @@ -0,0 +1,101 @@ + +import pygame as pg +from . import setup +from . import constants as c + +class Sound(object): + """Handles all sound for the game""" + def __init__(self, overhead_info): + """Initialize the class""" + self.sfx_dict = setup.SFX + self.music_dict = setup.MUSIC + self.overhead_info = overhead_info + self.game_info = overhead_info.game_info + self.set_music_mixer() + + + + def set_music_mixer(self): + """Sets music for level""" + if self.overhead_info.state == c.LEVEL: + pg.mixer.music.load(self.music_dict['main_theme']) + pg.mixer.music.play() + self.state = c.NORMAL + elif self.overhead_info.state == c.GAME_OVER: + pg.mixer.music.load(self.music_dict['game_over']) + pg.mixer.music.play() + self.state = c.GAME_OVER + + + def update(self, game_info, mario): + """Updates sound object with game info""" + self.game_info = game_info + self.mario = mario + self.handle_state() + + def handle_state(self): + """Handles the state of the soundn object""" + if self.state == c.NORMAL: + if self.mario.dead: + self.play_music('death', c.MARIO_DEAD) + elif self.mario.invincible \ + and self.mario.losing_invincibility == False: + self.play_music('invincible', c.MARIO_INVINCIBLE) + elif self.mario.state == c.FLAGPOLE: + self.play_music('flagpole', c.FLAGPOLE) + elif self.overhead_info.time == 100: + self.play_music('out_of_time', c.TIME_WARNING) + + + elif self.state == c.FLAGPOLE: + if self.mario.state == c.WALKING_TO_CASTLE: + self.play_music('stage_clear', c.STAGE_CLEAR) + + elif self.state == c.STAGE_CLEAR: + if self.mario.in_castle: + self.sfx_dict['count_down'].play() + self.state = c.FAST_COUNT_DOWN + + elif self.state == c.FAST_COUNT_DOWN: + if self.overhead_info.time == 0: + self.sfx_dict['count_down'].stop() + self.state = c.WORLD_CLEAR + + elif self.state == c. TIME_WARNING: + if pg.mixer.music.get_busy() == 0: + self.play_music('main_theme_sped_up', c.SPED_UP_NORMAL) + elif self.mario.dead: + self.play_music('death', c.MARIO_DEAD) + + elif self.state == c.SPED_UP_NORMAL: + if self.mario.dead: + self.play_music('death', c.MARIO_DEAD) + elif self.mario.state == c.FLAGPOLE: + self.play_music('flagpole', c.FLAGPOLE) + + elif self.state == c.MARIO_INVINCIBLE: + if (self.mario.current_time - self.mario.invincible_start_timer) > 11000: + self.play_music('main_theme', c.NORMAL) + elif self.mario.dead: + self.play_music('death', c.MARIO_DEAD) + + + elif self.state == c.WORLD_CLEAR: + pass + elif self.state == c.MARIO_DEAD: + pass + elif self.state == c.GAME_OVER: + pass + + def play_music(self, key, state): + """Plays new music""" + pg.mixer.music.load(self.music_dict[key]) + pg.mixer.music.play() + self.state = state + + def stop_music(self): + """Stops playback""" + pg.mixer.music.stop() + + + diff --git a/pythonProject1/data/main.py b/pythonProject1/data/main.py new file mode 100644 index 0000000..9917f79 --- /dev/null +++ b/pythonProject1/data/main.py @@ -0,0 +1,20 @@ + +from . import setup,tools +from .states import main_menu,load_screen,level1 +from . import constants as c + + +def main(): + """Add states to control here.""" + run_it = tools.Control(setup.ORIGINAL_CAPTION) + state_dict = {c.MAIN_MENU: main_menu.Menu(), + c.LOAD_SCREEN: load_screen.LoadScreen(), + c.TIME_OUT: load_screen.TimeOut(), + c.GAME_OVER: load_screen.GameOver(), + c.LEVEL1: level1.Level1()} + + run_it.setup_states(state_dict, c.MAIN_MENU) + run_it.main() + + + diff --git a/pythonProject1/data/setup.py b/pythonProject1/data/setup.py new file mode 100644 index 0000000..5267f26 --- /dev/null +++ b/pythonProject1/data/setup.py @@ -0,0 +1,27 @@ + +""" +This module initializes the display and creates dictionaries of resources. +""" + +import os +import pygame as pg +from . import tools +from .import constants as c + +ORIGINAL_CAPTION = c.ORIGINAL_CAPTION + + +os.environ['SDL_VIDEO_CENTERED'] = '1' +pg.init() +pg.event.set_allowed([pg.KEYDOWN, pg.KEYUP, pg.QUIT]) +pg.display.set_caption(c.ORIGINAL_CAPTION) +SCREEN = pg.display.set_mode(c.SCREEN_SIZE) +SCREEN_RECT = SCREEN.get_rect() + + +FONTS = tools.load_all_fonts(os.path.join("resources","fonts")) +MUSIC = tools.load_all_music(os.path.join("resources","music")) +GFX = tools.load_all_gfx(os.path.join("resources","graphics")) +SFX = tools.load_all_sfx(os.path.join("resources","sound")) + + diff --git a/pythonProject1/data/states/__pycache__/level1.cpython-311.pyc b/pythonProject1/data/states/__pycache__/level1.cpython-311.pyc new file mode 100644 index 0000000..9f6c391 Binary files /dev/null and b/pythonProject1/data/states/__pycache__/level1.cpython-311.pyc differ diff --git a/pythonProject1/data/states/__pycache__/load_screen.cpython-311.pyc b/pythonProject1/data/states/__pycache__/load_screen.cpython-311.pyc new file mode 100644 index 0000000..55ec8ed Binary files /dev/null and b/pythonProject1/data/states/__pycache__/load_screen.cpython-311.pyc differ diff --git a/pythonProject1/data/states/__pycache__/main_menu.cpython-311.pyc b/pythonProject1/data/states/__pycache__/main_menu.cpython-311.pyc new file mode 100644 index 0000000..c625036 Binary files /dev/null and b/pythonProject1/data/states/__pycache__/main_menu.cpython-311.pyc differ diff --git a/pythonProject1/data/states/level1.py b/pythonProject1/data/states/level1.py new file mode 100644 index 0000000..6e56a51 --- /dev/null +++ b/pythonProject1/data/states/level1.py @@ -0,0 +1,1434 @@ +from __future__ import division + + +import pygame as pg +from .. import setup, tools +from .. import constants as c +from .. import game_sound +from .. components import mario +from .. components import collider +from .. components import bricks +from .. components import coin_box +from .. components import enemies +from .. components import checkpoint +from .. components import flagpole +from .. components import info +from .. components import score +from .. components import castle_flag + + +class Level1(tools._State): + def __init__(self): + tools._State.__init__(self) + + def startup(self, current_time, persist): + """Called when the State object is created""" + self.game_info = persist + self.persist = self.game_info + self.game_info[c.CURRENT_TIME] = current_time + self.game_info[c.LEVEL_STATE] = c.NOT_FROZEN + self.game_info[c.MARIO_DEAD] = False + + self.state = c.NOT_FROZEN + self.death_timer = 0 + self.flag_timer = 0 + self.flag_score = None + self.flag_score_total = 0 + + self.moving_score_list = [] + self.overhead_info_display = info.OverheadInfo(self.game_info, c.LEVEL) + self.sound_manager = game_sound.Sound(self.overhead_info_display) + + self.setup_background() + self.setup_ground() + self.setup_pipes() + self.setup_steps() + self.setup_bricks() + self.setup_coin_boxes() + self.setup_flag_pole() + self.setup_enemies() + self.setup_mario() + self.setup_checkpoints() + self.setup_spritegroups() + + + def setup_background(self): + """Sets the background image, rect and scales it to the correct + proportions""" + self.background = setup.GFX['level_1'] + self.back_rect = self.background.get_rect() + self.background = pg.transform.scale(self.background, + (int(self.back_rect.width*c.BACKGROUND_MULTIPLER), + int(self.back_rect.height*c.BACKGROUND_MULTIPLER))) + self.back_rect = self.background.get_rect() + width = self.back_rect.width + height = self.back_rect.height + + self.level = pg.Surface((width, height)).convert() + self.level_rect = self.level.get_rect() + self.viewport = setup.SCREEN.get_rect(bottom=self.level_rect.bottom) + self.viewport.x = self.game_info[c.CAMERA_START_X] + + + def setup_ground(self): + """Creates collideable, invisible rectangles over top of the ground for + sprites to walk on""" + ground_rect1 = collider.Collider(0, c.GROUND_HEIGHT, 2953, 60) + ground_rect2 = collider.Collider(3048, c.GROUND_HEIGHT, 635, 60) + ground_rect3 = collider.Collider(3819, c.GROUND_HEIGHT, 2735, 60) + ground_rect4 = collider.Collider(6647, c.GROUND_HEIGHT, 2300, 60) + + self.ground_group = pg.sprite.Group(ground_rect1, + ground_rect2, + ground_rect3, + ground_rect4) + + + def setup_pipes(self): + """Create collideable rects for all the pipes""" + + pipe1 = collider.Collider(1202, 452, 83, 82) + pipe2 = collider.Collider(1631, 409, 83, 140) + pipe3 = collider.Collider(1973, 366, 83, 170) + pipe4 = collider.Collider(2445, 366, 83, 170) + pipe5 = collider.Collider(6989, 452, 83, 82) + pipe6 = collider.Collider(7675, 452, 83, 82) + + self.pipe_group = pg.sprite.Group(pipe1, pipe2, + pipe3, pipe4, + pipe5, pipe6) + + + def setup_steps(self): + """Create collideable rects for all the steps""" + step1 = collider.Collider(5745, 495, 40, 44) + step2 = collider.Collider(5788, 452, 40, 44) + step3 = collider.Collider(5831, 409, 40, 44) + step4 = collider.Collider(5874, 366, 40, 176) + + + step5 = collider.Collider(6001, 366, 40, 176) + step6 = collider.Collider(6044, 408, 40, 40) + step7 = collider.Collider(6087, 452, 40, 40) + step8 = collider.Collider(6130, 495, 40, 40) + + step9 = collider.Collider(6345, 495, 40, 40) + step10 = collider.Collider(6388, 452, 40, 40) + step11 = collider.Collider(6431, 409, 40, 40) + step12 = collider.Collider(6474, 366, 40, 40) + step13 = collider.Collider(6517, 366, 40, 176) + + step14 = collider.Collider(6644, 366, 40, 176) + step15 = collider.Collider(6687, 408, 40, 40) + step16 = collider.Collider(6728, 452, 40, 40) + step17 = collider.Collider(6771, 495, 40, 40) + + step18 = collider.Collider(7760, 495, 40, 40) + step19 = collider.Collider(7803, 452, 40, 40) + step20 = collider.Collider(7845, 409, 40, 40) + step21 = collider.Collider(7888, 366, 40, 40) + step22 = collider.Collider(7931, 323, 40, 40) + step23 = collider.Collider(7974, 280, 40, 40) + step24 = collider.Collider(8017, 237, 40, 40) + step25 = collider.Collider(8060, 194, 40, 40) + step26 = collider.Collider(8103, 194, 40, 360) + + step27 = collider.Collider(8488, 495, 40, 40) + + self.step_group = pg.sprite.Group(step1, step2, + step3, step4, + step5, step6, + step7, step8, + step9, step10, + step11, step12, + step13, step14, + step15, step16, + step17, step18, + step19, step20, + step21, step22, + step23, step24, + step25, step26, + step27) + + + def setup_bricks(self): + """Creates all the breakable bricks for the level. Coin and + powerup groups are created so they can be passed to bricks.""" + self.coin_group = pg.sprite.Group() + self.powerup_group = pg.sprite.Group() + self.brick_pieces_group = pg.sprite.Group() + + brick1 = bricks.Brick(858, 365) + brick2 = bricks.Brick(944, 365) + brick3 = bricks.Brick(1030, 365) + brick4 = bricks.Brick(3299, 365) + brick5 = bricks.Brick(3385, 365) + brick6 = bricks.Brick(3430, 193) + brick7 = bricks.Brick(3473, 193) + brick8 = bricks.Brick(3516, 193) + brick9 = bricks.Brick(3559, 193) + brick10 = bricks.Brick(3602, 193) + brick11 = bricks.Brick(3645, 193) + brick12 = bricks.Brick(3688, 193) + brick13 = bricks.Brick(3731, 193) + brick14 = bricks.Brick(3901, 193) + brick15 = bricks.Brick(3944, 193) + brick16 = bricks.Brick(3987, 193) + brick17 = bricks.Brick(4030, 365, c.SIXCOINS, self.coin_group) + brick18 = bricks.Brick(4287, 365) + brick19 = bricks.Brick(4330, 365, c.STAR, self.powerup_group) + brick20 = bricks.Brick(5058, 365) + brick21 = bricks.Brick(5187, 193) + brick22 = bricks.Brick(5230, 193) + brick23 = bricks.Brick(5273, 193) + brick24 = bricks.Brick(5488, 193) + brick25 = bricks.Brick(5574, 193) + brick26 = bricks.Brick(5617, 193) + brick27 = bricks.Brick(5531, 365) + brick28 = bricks.Brick(5574, 365) + brick29 = bricks.Brick(7202, 365) + brick30 = bricks.Brick(7245, 365) + brick31 = bricks.Brick(7331, 365) + + self.brick_group = pg.sprite.Group(brick1, brick2, + brick3, brick4, + brick5, brick6, + brick7, brick8, + brick9, brick10, + brick11, brick12, + brick13, brick14, + brick15, brick16, + brick17, brick18, + brick19, brick20, + brick21, brick22, + brick23, brick24, + brick25, brick26, + brick27, brick28, + brick29, brick30, + brick31) + + + def setup_coin_boxes(self): + """Creates all the coin boxes and puts them in a sprite group""" + coin_box1 = coin_box.Coin_box(685, 365, c.COIN, self.coin_group) + coin_box2 = coin_box.Coin_box(901, 365, c.MUSHROOM, self.powerup_group) + coin_box3 = coin_box.Coin_box(987, 365, c.COIN, self.coin_group) + coin_box4 = coin_box.Coin_box(943, 193, c.COIN, self.coin_group) + coin_box5 = coin_box.Coin_box(3342, 365, c.MUSHROOM, self.powerup_group) + coin_box6 = coin_box.Coin_box(4030, 193, c.COIN, self.coin_group) + coin_box7 = coin_box.Coin_box(4544, 365, c.COIN, self.coin_group) + coin_box8 = coin_box.Coin_box(4672, 365, c.COIN, self.coin_group) + coin_box9 = coin_box.Coin_box(4672, 193, c.MUSHROOM, self.powerup_group) + coin_box10 = coin_box.Coin_box(4800, 365, c.COIN, self.coin_group) + coin_box11 = coin_box.Coin_box(5531, 193, c.COIN, self.coin_group) + coin_box12 = coin_box.Coin_box(7288, 365, c.COIN, self.coin_group) + + self.coin_box_group = pg.sprite.Group(coin_box1, coin_box2, + coin_box3, coin_box4, + coin_box5, coin_box6, + coin_box7, coin_box8, + coin_box9, coin_box10, + coin_box11, coin_box12) + + + def setup_flag_pole(self): + """Creates the flag pole at the end of the level""" + self.flag = flagpole.Flag(8505, 100) + + pole0 = flagpole.Pole(8505, 97) + pole1 = flagpole.Pole(8505, 137) + pole2 = flagpole.Pole(8505, 177) + pole3 = flagpole.Pole(8505, 217) + pole4 = flagpole.Pole(8505, 257) + pole5 = flagpole.Pole(8505, 297) + pole6 = flagpole.Pole(8505, 337) + pole7 = flagpole.Pole(8505, 377) + pole8 = flagpole.Pole(8505, 417) + pole9 = flagpole.Pole(8505, 450) + + finial = flagpole.Finial(8507, 97) + + self.flag_pole_group = pg.sprite.Group(self.flag, + finial, + pole0, + pole1, + pole2, + pole3, + pole4, + pole5, + pole6, + pole7, + pole8, + pole9) + + + def setup_enemies(self): + """Creates all the enemies and stores them in a list of lists.""" + goomba0 = enemies.Goomba() + goomba1 = enemies.Goomba() + goomba2 = enemies.Goomba() + goomba3 = enemies.Goomba() + goomba4 = enemies.Goomba(193) + goomba5 = enemies.Goomba(193) + goomba6 = enemies.Goomba() + goomba7 = enemies.Goomba() + goomba8 = enemies.Goomba() + goomba9 = enemies.Goomba() + goomba10 = enemies.Goomba() + goomba11 = enemies.Goomba() + goomba12 = enemies.Goomba() + goomba13 = enemies.Goomba() + goomba14 = enemies.Goomba() + goomba15 = enemies.Goomba() + + koopa0 = enemies.Koopa() + + enemy_group1 = pg.sprite.Group(goomba0) + enemy_group2 = pg.sprite.Group(goomba1) + enemy_group3 = pg.sprite.Group(goomba2, goomba3) + enemy_group4 = pg.sprite.Group(goomba4, goomba5) + enemy_group5 = pg.sprite.Group(goomba6, goomba7) + enemy_group6 = pg.sprite.Group(koopa0) + enemy_group7 = pg.sprite.Group(goomba8, goomba9) + enemy_group8 = pg.sprite.Group(goomba10, goomba11) + enemy_group9 = pg.sprite.Group(goomba12, goomba13) + enemy_group10 = pg.sprite.Group(goomba14, goomba15) + + self.enemy_group_list = [enemy_group1, + enemy_group2, + enemy_group3, + enemy_group4, + enemy_group5, + enemy_group6, + enemy_group7, + enemy_group8, + enemy_group9, + enemy_group10] + + + def setup_mario(self): + """Places Mario at the beginning of the level""" + self.mario = mario.Mario() + self.mario.rect.x = self.viewport.x + 110 + self.mario.rect.bottom = c.GROUND_HEIGHT + + + def setup_checkpoints(self): + """Creates invisible checkpoints that when collided will trigger + the creation of enemies from the self.enemy_group_list""" + check1 = checkpoint.Checkpoint(510, "1") + check2 = checkpoint.Checkpoint(1400, '2') + check3 = checkpoint.Checkpoint(1740, '3') + check4 = checkpoint.Checkpoint(3080, '4') + check5 = checkpoint.Checkpoint(3750, '5') + check6 = checkpoint.Checkpoint(4150, '6') + check7 = checkpoint.Checkpoint(4470, '7') + check8 = checkpoint.Checkpoint(4950, '8') + check9 = checkpoint.Checkpoint(5100, '9') + check10 = checkpoint.Checkpoint(6800, '10') + check11 = checkpoint.Checkpoint(8504, '11', 5, 6) + check12 = checkpoint.Checkpoint(8775, '12') + check13 = checkpoint.Checkpoint(2740, 'secret_mushroom', 360, 40, 12) + + self.check_point_group = pg.sprite.Group(check1, check2, check3, + check4, check5, check6, + check7, check8, check9, + check10, check11, check12, + check13) + + + def setup_spritegroups(self): + """Sprite groups created for convenience""" + self.sprites_about_to_die_group = pg.sprite.Group() + self.shell_group = pg.sprite.Group() + self.enemy_group = pg.sprite.Group() + + self.ground_step_pipe_group = pg.sprite.Group(self.ground_group, + self.pipe_group, + self.step_group) + + self.mario_and_enemy_group = pg.sprite.Group(self.mario, + self.enemy_group) + + + def update(self, surface, keys, current_time): + """Updates Entire level using states. Called by the control object""" + self.game_info[c.CURRENT_TIME] = self.current_time = current_time + self.handle_states(keys) + self.check_if_time_out() + self.blit_everything(surface) + self.sound_manager.update(self.game_info, self.mario) + + + + def handle_states(self, keys): + """If the level is in a FROZEN state, only mario will update""" + if self.state == c.FROZEN: + self.update_during_transition_state(keys) + elif self.state == c.NOT_FROZEN: + self.update_all_sprites(keys) + elif self.state == c.IN_CASTLE: + self.update_while_in_castle() + elif self.state == c.FLAG_AND_FIREWORKS: + self.update_flag_and_fireworks() + + + def update_during_transition_state(self, keys): + """Updates mario in a transition state (like becoming big, small, + or dies). Checks if he leaves the transition state or dies to + change the level state back""" + self.mario.update(keys, self.game_info, self.powerup_group) + for score in self.moving_score_list: + score.update(self.moving_score_list, self.game_info) + if self.flag_score: + self.flag_score.update(None, self.game_info) + self.check_to_add_flag_score() + self.coin_box_group.update(self.game_info) + self.flag_pole_group.update(self.game_info) + self.check_if_mario_in_transition_state() + self.check_flag() + self.check_for_mario_death() + self.overhead_info_display.update(self.game_info, self.mario) + + + def check_if_mario_in_transition_state(self): + """If mario is in a transition state, the level will be in a FREEZE + state""" + if self.mario.in_transition_state: + self.game_info[c.LEVEL_STATE] = self.state = c.FROZEN + elif self.mario.in_transition_state == False: + if self.state == c.FROZEN: + self.game_info[c.LEVEL_STATE] = self.state = c.NOT_FROZEN + + + def update_all_sprites(self, keys): + """Updates the location of all sprites on the screen.""" + self.mario.update(keys, self.game_info, self.powerup_group) + for score in self.moving_score_list: + score.update(self.moving_score_list, self.game_info) + if self.flag_score: + self.flag_score.update(None, self.game_info) + self.check_to_add_flag_score() + self.flag_pole_group.update() + self.check_points_check() + self.enemy_group.update(self.game_info) + self.sprites_about_to_die_group.update(self.game_info, self.viewport) + self.shell_group.update(self.game_info) + self.brick_group.update() + self.coin_box_group.update(self.game_info) + self.powerup_group.update(self.game_info, self.viewport) + self.coin_group.update(self.game_info, self.viewport) + self.brick_pieces_group.update() + self.adjust_sprite_positions() + self.check_if_mario_in_transition_state() + self.check_for_mario_death() + self.update_viewport() + self.overhead_info_display.update(self.game_info, self.mario) + + + def check_points_check(self): + """Detect if checkpoint collision occurs, delete checkpoint, + add enemies to self.enemy_group""" + checkpoint = pg.sprite.spritecollideany(self.mario, + self.check_point_group) + if checkpoint: + checkpoint.kill() + + for i in range(1,11): + if checkpoint.name == str(i): + for index, enemy in enumerate(self.enemy_group_list[i -1]): + enemy.rect.x = self.viewport.right + (index * 60) + self.enemy_group.add(self.enemy_group_list[i-1]) + + if checkpoint.name == '11': + self.mario.state = c.FLAGPOLE + self.mario.invincible = False + self.mario.flag_pole_right = checkpoint.rect.right + if self.mario.rect.bottom < self.flag.rect.y: + self.mario.rect.bottom = self.flag.rect.y + self.flag.state = c.SLIDE_DOWN + self.create_flag_points() + + elif checkpoint.name == '12': + self.state = c.IN_CASTLE + self.mario.kill() + self.mario.state == c.STAND + self.mario.in_castle = True + self.overhead_info_display.state = c.FAST_COUNT_DOWN + + + elif checkpoint.name == 'secret_mushroom' and self.mario.y_vel < 0: + mushroom_box = coin_box.Coin_box(checkpoint.rect.x, + checkpoint.rect.bottom - 40, + '1up_mushroom', + self.powerup_group) + mushroom_box.start_bump(self.moving_score_list) + self.coin_box_group.add(mushroom_box) + + self.mario.y_vel = 7 + self.mario.rect.y = mushroom_box.rect.bottom + self.mario.state = c.FALL + + self.mario_and_enemy_group.add(self.enemy_group) + + + def create_flag_points(self): + """Creates the points that appear when Mario touches the + flag pole""" + x = 8518 + y = c.GROUND_HEIGHT - 60 + mario_bottom = self.mario.rect.bottom + + if mario_bottom > (c.GROUND_HEIGHT - 40 - 40): + self.flag_score = score.Score(x, y, 100, True) + self.flag_score_total = 100 + elif mario_bottom > (c.GROUND_HEIGHT - 40 - 160): + self.flag_score = score.Score(x, y, 400, True) + self.flag_score_total = 400 + elif mario_bottom > (c.GROUND_HEIGHT - 40 - 240): + self.flag_score = score.Score(x, y, 800, True) + self.flag_score_total = 800 + elif mario_bottom > (c.GROUND_HEIGHT - 40 - 360): + self.flag_score = score.Score(x, y, 2000, True) + self.flag_score_total = 2000 + else: + self.flag_score = score.Score(x, y, 5000, True) + self.flag_score_total = 5000 + + + def adjust_sprite_positions(self): + """Adjusts sprites by their x and y velocities and collisions""" + self.adjust_mario_position() + self.adjust_enemy_position() + self.adjust_shell_position() + self.adjust_powerup_position() + + + def adjust_mario_position(self): + """Adjusts Mario's position based on his x, y velocities and + potential collisions""" + self.last_x_position = self.mario.rect.right + self.mario.rect.x += round(self.mario.x_vel) + self.check_mario_x_collisions() + + if self.mario.in_transition_state == False: + self.mario.rect.y += round(self.mario.y_vel) + self.check_mario_y_collisions() + + if self.mario.rect.x < (self.viewport.x + 5): + self.mario.rect.x = (self.viewport.x + 5) + + + def check_mario_x_collisions(self): + """Check for collisions after Mario is moved on the x axis""" + collider = pg.sprite.spritecollideany(self.mario, self.ground_step_pipe_group) + coin_box = pg.sprite.spritecollideany(self.mario, self.coin_box_group) + brick = pg.sprite.spritecollideany(self.mario, self.brick_group) + enemy = pg.sprite.spritecollideany(self.mario, self.enemy_group) + shell = pg.sprite.spritecollideany(self.mario, self.shell_group) + powerup = pg.sprite.spritecollideany(self.mario, self.powerup_group) + + if coin_box: + self.adjust_mario_for_x_collisions(coin_box) + + elif brick: + self.adjust_mario_for_x_collisions(brick) + + elif collider: + self.adjust_mario_for_x_collisions(collider) + + elif enemy: + if self.mario.invincible: + setup.SFX['kick'].play() + self.game_info[c.SCORE] += 100 + self.moving_score_list.append( + score.Score(self.mario.rect.right - self.viewport.x, + self.mario.rect.y, 100)) + enemy.kill() + enemy.start_death_jump(c.RIGHT) + self.sprites_about_to_die_group.add(enemy) + elif self.mario.big: + setup.SFX['pipe'].play() + self.mario.fire = False + self.mario.y_vel = -1 + self.mario.state = c.BIG_TO_SMALL + self.convert_fireflowers_to_mushrooms() + elif self.mario.hurt_invincible: + pass + else: + self.mario.start_death_jump(self.game_info) + self.state = c.FROZEN + + elif shell: + self.adjust_mario_for_x_shell_collisions(shell) + + elif powerup: + if powerup.name == c.STAR: + self.game_info[c.SCORE] += 1000 + + self.moving_score_list.append( + score.Score(self.mario.rect.centerx - self.viewport.x, + self.mario.rect.y, 1000)) + self.mario.invincible = True + self.mario.invincible_start_timer = self.current_time + elif powerup.name == c.MUSHROOM: + setup.SFX['powerup'].play() + self.game_info[c.SCORE] += 1000 + self.moving_score_list.append( + score.Score(self.mario.rect.centerx - self.viewport.x, + self.mario.rect.y - 20, 1000)) + + self.mario.y_vel = -1 + self.mario.state = c.SMALL_TO_BIG + self.mario.in_transition_state = True + self.convert_mushrooms_to_fireflowers() + elif powerup.name == c.LIFE_MUSHROOM: + self.moving_score_list.append( + score.Score(powerup.rect.right - self.viewport.x, + powerup.rect.y, + c.ONEUP)) + + self.game_info[c.LIVES] += 1 + setup.SFX['one_up'].play() + elif powerup.name == c.FIREFLOWER: + setup.SFX['powerup'].play() + self.game_info[c.SCORE] += 1000 + self.moving_score_list.append( + score.Score(self.mario.rect.centerx - self.viewport.x, + self.mario.rect.y, 1000)) + + if self.mario.big and self.mario.fire == False: + self.mario.state = c.BIG_TO_FIRE + self.mario.in_transition_state = True + elif self.mario.big == False: + self.mario.state = c.SMALL_TO_BIG + self.mario.in_transition_state = True + self.convert_mushrooms_to_fireflowers() + + if powerup.name != c.FIREBALL: + powerup.kill() + + + def convert_mushrooms_to_fireflowers(self): + """When Mario becomees big, converts all fireflower powerups to + mushroom powerups""" + for brick in self.brick_group: + if brick.contents == c.MUSHROOM: + brick.contents = c.FIREFLOWER + for coin_box in self.coin_box_group: + if coin_box.contents == c.MUSHROOM: + coin_box.contents = c.FIREFLOWER + + + def convert_fireflowers_to_mushrooms(self): + """When Mario becomes small, converts all mushroom powerups to + fireflower powerups""" + for brick in self.brick_group: + if brick.contents == c.FIREFLOWER: + brick.contents = c.MUSHROOM + for coin_box in self.coin_box_group: + if coin_box.contents == c.FIREFLOWER: + coin_box.contents = c.MUSHROOM + + + def adjust_mario_for_x_collisions(self, collider): + """Puts Mario flush next to the collider after moving on the x axis""" + if self.mario.rect.x < collider.rect.x: + self.mario.rect.right = collider.rect.left + else: + self.mario.rect.left = collider.rect.right + + self.mario.x_vel = 0 + + + def adjust_mario_for_x_shell_collisions(self, shell): + """Deals with Mario if he hits a shell moving on the x axis""" + if shell.state == c.JUMPED_ON: + if self.mario.rect.x < shell.rect.x: + self.game_info[c.SCORE] += 400 + self.moving_score_list.append( + score.Score(shell.rect.centerx - self.viewport.x, + shell.rect.y, + 400)) + self.mario.rect.right = shell.rect.left + shell.direction = c.RIGHT + shell.x_vel = 5 + shell.rect.x += 5 + + else: + self.mario.rect.left = shell.rect.right + shell.direction = c.LEFT + shell.x_vel = -5 + shell.rect.x += -5 + + shell.state = c.SHELL_SLIDE + + elif shell.state == c.SHELL_SLIDE: + if self.mario.big and not self.mario.invincible: + self.mario.state = c.BIG_TO_SMALL + elif self.mario.invincible: + self.game_info[c.SCORE] += 200 + self.moving_score_list.append( + score.Score(shell.rect.right - self.viewport.x, + shell.rect.y, 200)) + shell.kill() + self.sprites_about_to_die_group.add(shell) + shell.start_death_jump(c.RIGHT) + else: + if not self.mario.hurt_invincible and not self.mario.invincible: + self.state = c.FROZEN + self.mario.start_death_jump(self.game_info) + + + def check_mario_y_collisions(self): + """Checks for collisions when Mario moves along the y-axis""" + ground_step_or_pipe = pg.sprite.spritecollideany(self.mario, self.ground_step_pipe_group) + enemy = pg.sprite.spritecollideany(self.mario, self.enemy_group) + shell = pg.sprite.spritecollideany(self.mario, self.shell_group) + brick = pg.sprite.spritecollideany(self.mario, self.brick_group) + coin_box = pg.sprite.spritecollideany(self.mario, self.coin_box_group) + powerup = pg.sprite.spritecollideany(self.mario, self.powerup_group) + + brick, coin_box = self.prevent_collision_conflict(brick, coin_box) + + if coin_box: + self.adjust_mario_for_y_coin_box_collisions(coin_box) + + elif brick: + self.adjust_mario_for_y_brick_collisions(brick) + + elif ground_step_or_pipe: + self.adjust_mario_for_y_ground_pipe_collisions(ground_step_or_pipe) + + elif enemy: + if self.mario.invincible: + setup.SFX['kick'].play() + enemy.kill() + self.sprites_about_to_die_group.add(enemy) + enemy.start_death_jump(c.RIGHT) + else: + self.adjust_mario_for_y_enemy_collisions(enemy) + + elif shell: + self.adjust_mario_for_y_shell_collisions(shell) + + elif powerup: + if powerup.name == c.STAR: + setup.SFX['powerup'].play() + powerup.kill() + self.mario.invincible = True + self.mario.invincible_start_timer = self.current_time + + self.test_if_mario_is_falling() + + + def prevent_collision_conflict(self, obstacle1, obstacle2): + """Allows collisions only for the item closest to marios centerx""" + if obstacle1 and obstacle2: + obstacle1_distance = self.mario.rect.centerx - obstacle1.rect.centerx + if obstacle1_distance < 0: + obstacle1_distance *= -1 + obstacle2_distance = self.mario.rect.centerx - obstacle2.rect.centerx + if obstacle2_distance < 0: + obstacle2_distance *= -1 + + if obstacle1_distance < obstacle2_distance: + obstacle2 = False + else: + obstacle1 = False + + return obstacle1, obstacle2 + + + def adjust_mario_for_y_coin_box_collisions(self, coin_box): + """Mario collisions with coin boxes on the y-axis""" + if self.mario.rect.y > coin_box.rect.y: + if coin_box.state == c.RESTING: + if coin_box.contents == c.COIN: + self.game_info[c.SCORE] += 200 + coin_box.start_bump(self.moving_score_list) + if coin_box.contents == c.COIN: + self.game_info[c.COIN_TOTAL] += 1 + else: + coin_box.start_bump(self.moving_score_list) + + elif coin_box.state == c.OPENED: + pass + setup.SFX['bump'].play() + self.mario.y_vel = 7 + self.mario.rect.y = coin_box.rect.bottom + self.mario.state = c.FALL + else: + self.mario.y_vel = 0 + self.mario.rect.bottom = coin_box.rect.top + self.mario.state = c.WALK + + + def adjust_mario_for_y_brick_collisions(self, brick): + """Mario collisions with bricks on the y-axis""" + if self.mario.rect.y > brick.rect.y: + if brick.state == c.RESTING: + if self.mario.big and brick.contents is None: + setup.SFX['brick_smash'].play() + self.check_if_enemy_on_brick(brick) + brick.kill() + self.brick_pieces_group.add( + bricks.BrickPiece(brick.rect.x, + brick.rect.y - (brick.rect.height/2), + -2, -12), + bricks.BrickPiece(brick.rect.right, + brick.rect.y - (brick.rect.height/2), + 2, -12), + bricks.BrickPiece(brick.rect.x, + brick.rect.y, + -2, -6), + bricks.BrickPiece(brick.rect.right, + brick.rect.y, + 2, -6)) + else: + setup.SFX['bump'].play() + if brick.coin_total > 0: + self.game_info[c.COIN_TOTAL] += 1 + self.game_info[c.SCORE] += 200 + self.check_if_enemy_on_brick(brick) + brick.start_bump(self.moving_score_list) + elif brick.state == c.OPENED: + setup.SFX['bump'].play() + self.mario.y_vel = 7 + self.mario.rect.y = brick.rect.bottom + self.mario.state = c.FALL + + else: + self.mario.y_vel = 0 + self.mario.rect.bottom = brick.rect.top + self.mario.state = c.WALK + + + def check_if_enemy_on_brick(self, brick): + """Kills enemy if on a bumped or broken brick""" + brick.rect.y -= 5 + + enemy = pg.sprite.spritecollideany(brick, self.enemy_group) + + if enemy: + setup.SFX['kick'].play() + self.game_info[c.SCORE] += 100 + self.moving_score_list.append( + score.Score(enemy.rect.centerx - self.viewport.x, + enemy.rect.y, + 100)) + enemy.kill() + self.sprites_about_to_die_group.add(enemy) + if self.mario.rect.centerx > brick.rect.centerx: + enemy.start_death_jump('right') + else: + enemy.start_death_jump('left') + + brick.rect.y += 5 + + + + def adjust_mario_for_y_ground_pipe_collisions(self, collider): + """Mario collisions with pipes on the y-axis""" + if collider.rect.bottom > self.mario.rect.bottom: + self.mario.y_vel = 0 + self.mario.rect.bottom = collider.rect.top + if self.mario.state == c.END_OF_LEVEL_FALL: + self.mario.state = c.WALKING_TO_CASTLE + else: + self.mario.state = c.WALK + elif collider.rect.top < self.mario.rect.top: + self.mario.y_vel = 7 + self.mario.rect.top = collider.rect.bottom + self.mario.state = c.FALL + + + def test_if_mario_is_falling(self): + """Changes Mario to a FALL state if more than a pixel above a pipe, + ground, step or box""" + self.mario.rect.y += 1 + test_collide_group = pg.sprite.Group(self.ground_step_pipe_group, + self.brick_group, + self.coin_box_group) + + + if pg.sprite.spritecollideany(self.mario, test_collide_group) is None: + if self.mario.state != c.JUMP \ + and self.mario.state != c.DEATH_JUMP \ + and self.mario.state != c.SMALL_TO_BIG \ + and self.mario.state != c.BIG_TO_FIRE \ + and self.mario.state != c.BIG_TO_SMALL \ + and self.mario.state != c.FLAGPOLE \ + and self.mario.state != c.WALKING_TO_CASTLE \ + and self.mario.state != c.END_OF_LEVEL_FALL: + self.mario.state = c.FALL + elif self.mario.state == c.WALKING_TO_CASTLE or \ + self.mario.state == c.END_OF_LEVEL_FALL: + self.mario.state = c.END_OF_LEVEL_FALL + + self.mario.rect.y -= 1 + + + def adjust_mario_for_y_enemy_collisions(self, enemy): + """Mario collisions with all enemies on the y-axis""" + if self.mario.y_vel > 0: + setup.SFX['stomp'].play() + self.game_info[c.SCORE] += 100 + self.moving_score_list.append( + score.Score(enemy.rect.centerx - self.viewport.x, + enemy.rect.y, 100)) + enemy.state = c.JUMPED_ON + enemy.kill() + if enemy.name == c.GOOMBA: + enemy.death_timer = self.current_time + self.sprites_about_to_die_group.add(enemy) + elif enemy.name == c.KOOPA: + self.shell_group.add(enemy) + + self.mario.rect.bottom = enemy.rect.top + self.mario.state = c.JUMP + self.mario.y_vel = -7 + + + + def adjust_mario_for_y_shell_collisions(self, shell): + """Mario collisions with Koopas in their shells on the y axis""" + if self.mario.y_vel > 0: + self.game_info[c.SCORE] += 400 + self.moving_score_list.append( + score.Score(self.mario.rect.centerx - self.viewport.x, + self.mario.rect.y, 400)) + if shell.state == c.JUMPED_ON: + setup.SFX['kick'].play() + shell.state = c.SHELL_SLIDE + if self.mario.rect.centerx < shell.rect.centerx: + shell.direction = c.RIGHT + shell.rect.left = self.mario.rect.right + 5 + else: + shell.direction = c.LEFT + shell.rect.right = self.mario.rect.left - 5 + else: + shell.state = c.JUMPED_ON + + + def adjust_enemy_position(self): + """Moves all enemies along the x, y axes and check for collisions""" + for enemy in self.enemy_group: + enemy.rect.x += enemy.x_vel + self.check_enemy_x_collisions(enemy) + + enemy.rect.y += enemy.y_vel + self.check_enemy_y_collisions(enemy) + self.delete_if_off_screen(enemy) + + + def check_enemy_x_collisions(self, enemy): + """Enemy collisions along the x axis. Removes enemy from enemy group + in order to check against all other enemies then adds it back.""" + enemy.kill() + + collider = pg.sprite.spritecollideany(enemy, self.ground_step_pipe_group) + enemy_collider = pg.sprite.spritecollideany(enemy, self.enemy_group) + + if collider: + if enemy.direction == c.RIGHT: + enemy.rect.right = collider.rect.left + enemy.direction = c.LEFT + enemy.x_vel = -2 + elif enemy.direction == c.LEFT: + enemy.rect.left = collider.rect.right + enemy.direction = c.RIGHT + enemy.x_vel = 2 + + + elif enemy_collider: + if enemy.direction == c.RIGHT: + enemy.rect.right = enemy_collider.rect.left + enemy.direction = c.LEFT + enemy_collider.direction = c.RIGHT + enemy.x_vel = -2 + enemy_collider.x_vel = 2 + elif enemy.direction == c.LEFT: + enemy.rect.left = enemy_collider.rect.right + enemy.direction = c.RIGHT + enemy_collider.direction = c.LEFT + enemy.x_vel = 2 + enemy_collider.x_vel = -2 + + self.enemy_group.add(enemy) + self.mario_and_enemy_group.add(self.enemy_group) + + + def check_enemy_y_collisions(self, enemy): + """Enemy collisions on the y axis""" + collider = pg.sprite.spritecollideany(enemy, self.ground_step_pipe_group) + brick = pg.sprite.spritecollideany(enemy, self.brick_group) + coin_box = pg.sprite.spritecollideany(enemy, self.coin_box_group) + + if collider: + if enemy.rect.bottom > collider.rect.bottom: + enemy.y_vel = 7 + enemy.rect.top = collider.rect.bottom + enemy.state = c.FALL + elif enemy.rect.bottom < collider.rect.bottom: + + enemy.y_vel = 0 + enemy.rect.bottom = collider.rect.top + enemy.state = c.WALK + + elif brick: + if brick.state == c.BUMPED: + enemy.kill() + self.sprites_about_to_die_group.add(enemy) + if self.mario.rect.centerx > brick.rect.centerx: + enemy.start_death_jump('right') + else: + enemy.start_death_jump('left') + + elif enemy.rect.x > brick.rect.x: + enemy.y_vel = 7 + enemy.rect.top = brick.rect.bottom + enemy.state = c.FALL + else: + enemy.y_vel = 0 + enemy.rect.bottom = brick.rect.top + enemy.state = c.WALK + + elif coin_box: + if coin_box.state == c.BUMPED: + self.game_info[c.SCORE] += 100 + self.moving_score_list.append( + score.Score(enemy.rect.centerx - self.viewport.x, + enemy.rect.y, 100)) + enemy.kill() + self.sprites_about_to_die_group.add(enemy) + if self.mario.rect.centerx > coin_box.rect.centerx: + enemy.start_death_jump('right') + else: + enemy.start_death_jump('left') + + elif enemy.rect.x > coin_box.rect.x: + enemy.y_vel = 7 + enemy.rect.top = coin_box.rect.bottom + enemy.state = c.FALL + else: + enemy.y_vel = 0 + enemy.rect.bottom = coin_box.rect.top + enemy.state = c.WALK + + + else: + enemy.rect.y += 1 + test_group = pg.sprite.Group(self.ground_step_pipe_group, + self.coin_box_group, + self.brick_group) + if pg.sprite.spritecollideany(enemy, test_group) is None: + if enemy.state != c.JUMP: + enemy.state = c.FALL + + enemy.rect.y -= 1 + + + def adjust_shell_position(self): + """Moves any koopa in a shell along the x, y axes and checks for + collisions""" + for shell in self.shell_group: + shell.rect.x += shell.x_vel + self.check_shell_x_collisions(shell) + + shell.rect.y += shell.y_vel + self.check_shell_y_collisions(shell) + self.delete_if_off_screen(shell) + + + def check_shell_x_collisions(self, shell): + """Shell collisions along the x axis""" + collider = pg.sprite.spritecollideany(shell, self.ground_step_pipe_group) + enemy = pg.sprite.spritecollideany(shell, self.enemy_group) + + if collider: + setup.SFX['bump'].play() + if shell.x_vel > 0: + shell.direction = c.LEFT + shell.rect.right = collider.rect.left + else: + shell.direction = c.RIGHT + shell.rect.left = collider.rect.right + + if enemy: + setup.SFX['kick'].play() + self.game_info[c.SCORE] += 100 + self.moving_score_list.append( + score.Score(enemy.rect.right - self.viewport.x, + enemy.rect.y, 100)) + enemy.kill() + self.sprites_about_to_die_group.add(enemy) + enemy.start_death_jump(shell.direction) + + + def check_shell_y_collisions(self, shell): + """Shell collisions along the y axis""" + collider = pg.sprite.spritecollideany(shell, self.ground_step_pipe_group) + + if collider: + shell.y_vel = 0 + shell.rect.bottom = collider.rect.top + shell.state = c.SHELL_SLIDE + + else: + shell.rect.y += 1 + if pg.sprite.spritecollideany(shell, self.ground_step_pipe_group) is None: + shell.state = c.FALL + shell.rect.y -= 1 + + + def adjust_powerup_position(self): + """Moves mushrooms, stars and fireballs along the x, y axes""" + for powerup in self.powerup_group: + if powerup.name == c.MUSHROOM: + self.adjust_mushroom_position(powerup) + elif powerup.name == c.STAR: + self.adjust_star_position(powerup) + elif powerup.name == c.FIREBALL: + self.adjust_fireball_position(powerup) + elif powerup.name == '1up_mushroom': + self.adjust_mushroom_position(powerup) + + + def adjust_mushroom_position(self, mushroom): + """Moves mushroom along the x, y axes.""" + if mushroom.state != c.REVEAL: + mushroom.rect.x += mushroom.x_vel + self.check_mushroom_x_collisions(mushroom) + + mushroom.rect.y += mushroom.y_vel + self.check_mushroom_y_collisions(mushroom) + self.delete_if_off_screen(mushroom) + + + def check_mushroom_x_collisions(self, mushroom): + """Mushroom collisions along the x axis""" + collider = pg.sprite.spritecollideany(mushroom, self.ground_step_pipe_group) + brick = pg.sprite.spritecollideany(mushroom, self.brick_group) + coin_box = pg.sprite.spritecollideany(mushroom, self.coin_box_group) + + if collider: + self.adjust_mushroom_for_collision_x(mushroom, collider) + + elif brick: + self.adjust_mushroom_for_collision_x(mushroom, brick) + + elif coin_box: + self.adjust_mushroom_for_collision_x(mushroom, coin_box) + + + def check_mushroom_y_collisions(self, mushroom): + """Mushroom collisions along the y axis""" + collider = pg.sprite.spritecollideany(mushroom, self.ground_step_pipe_group) + brick = pg.sprite.spritecollideany(mushroom, self.brick_group) + coin_box = pg.sprite.spritecollideany(mushroom, self.coin_box_group) + + if collider: + self.adjust_mushroom_for_collision_y(mushroom, collider) + elif brick: + self.adjust_mushroom_for_collision_y(mushroom, brick) + elif coin_box: + self.adjust_mushroom_for_collision_y(mushroom, coin_box) + else: + self.check_if_falling(mushroom, self.ground_step_pipe_group) + self.check_if_falling(mushroom, self.brick_group) + self.check_if_falling(mushroom, self.coin_box_group) + + + def adjust_mushroom_for_collision_x(self, item, collider): + """Changes mushroom direction if collision along x axis""" + if item.rect.x < collider.rect.x: + item.rect.right = collider.rect.x + item.direction = c.LEFT + else: + item.rect.x = collider.rect.right + item.direction = c.RIGHT + + + def adjust_mushroom_for_collision_y(self, item, collider): + """Changes mushroom state to SLIDE after hitting ground from fall""" + item.rect.bottom = collider.rect.y + item.state = c.SLIDE + item.y_vel = 0 + + + def adjust_star_position(self, star): + """Moves invincible star along x, y axes and checks for collisions""" + if star.state == c.BOUNCE: + star.rect.x += star.x_vel + self.check_mushroom_x_collisions(star) + star.rect.y += star.y_vel + self.check_star_y_collisions(star) + star.y_vel += star.gravity + self.delete_if_off_screen(star) + + + def check_star_y_collisions(self, star): + """Invincible star collisions along y axis""" + collider = pg.sprite.spritecollideany(star, self.ground_step_pipe_group) + brick = pg.sprite.spritecollideany(star, self.brick_group) + coin_box = pg.sprite.spritecollideany(star, self.coin_box_group) + + if collider: + self.adjust_star_for_collision_y(star, collider) + elif brick: + self.adjust_star_for_collision_y(star, brick) + elif coin_box: + self.adjust_star_for_collision_y(star, coin_box) + + + def adjust_star_for_collision_y(self, star, collider): + """Allows for a star bounce off the ground and on the bottom of a + box""" + if star.rect.y > collider.rect.y: + star.rect.y = collider.rect.bottom + star.y_vel = 0 + else: + star.rect.bottom = collider.rect.top + star.start_bounce(-8) + + + def adjust_fireball_position(self, fireball): + """Moves fireball along the x, y axes and checks for collisions""" + if fireball.state == c.FLYING: + fireball.rect.x += fireball.x_vel + self.check_fireball_x_collisions(fireball) + fireball.rect.y += fireball.y_vel + self.check_fireball_y_collisions(fireball) + elif fireball.state == c.BOUNCING: + fireball.rect.x += fireball.x_vel + self.check_fireball_x_collisions(fireball) + fireball.rect.y += fireball.y_vel + self.check_fireball_y_collisions(fireball) + fireball.y_vel += fireball.gravity + self.delete_if_off_screen(fireball) + + + def bounce_fireball(self, fireball): + """Simulates fireball bounce off ground""" + fireball.y_vel = -8 + if fireball.direction == c.RIGHT: + fireball.x_vel = 15 + else: + fireball.x_vel = -15 + + if fireball in self.powerup_group: + fireball.state = c.BOUNCING + + + def check_fireball_x_collisions(self, fireball): + """Fireball collisions along x axis""" + collide_group = pg.sprite.Group(self.ground_group, + self.pipe_group, + self.step_group, + self.coin_box_group, + self.brick_group) + + collider = pg.sprite.spritecollideany(fireball, collide_group) + + if collider: + fireball.kill() + self.sprites_about_to_die_group.add(fireball) + fireball.explode_transition() + + + + def check_fireball_y_collisions(self, fireball): + """Fireball collisions along y axis""" + collide_group = pg.sprite.Group(self.ground_group, + self.pipe_group, + self.step_group, + self.coin_box_group, + self.brick_group) + + collider = pg.sprite.spritecollideany(fireball, collide_group) + enemy = pg.sprite.spritecollideany(fireball, self.enemy_group) + shell = pg.sprite.spritecollideany(fireball, self.shell_group) + + if collider and (fireball in self.powerup_group): + fireball.rect.bottom = collider.rect.y + self.bounce_fireball(fireball) + + elif enemy: + self.fireball_kill(fireball, enemy) + + elif shell: + self.fireball_kill(fireball, shell) + + + def fireball_kill(self, fireball, enemy): + """Kills enemy if hit with fireball""" + setup.SFX['kick'].play() + self.game_info[c.SCORE] += 100 + self.moving_score_list.append( + score.Score(enemy.rect.centerx - self.viewport.x, + enemy.rect.y,100)) + fireball.kill() + enemy.kill() + self.sprites_about_to_die_group.add(enemy, fireball) + enemy.start_death_jump(fireball.direction) + fireball.explode_transition() + + + def check_if_falling(self, sprite, sprite_group): + """Checks if sprite should enter a falling state""" + sprite.rect.y += 1 + + if pg.sprite.spritecollideany(sprite, sprite_group) is None: + if sprite.state != c.JUMP: + sprite.state = c.FALL + + sprite.rect.y -= 1 + + + def delete_if_off_screen(self, enemy): + """Removes enemy from sprite groups if 500 pixels left off the screen, + underneath the bottom of the screen, or right of the screen if shell""" + if enemy.rect.x < (self.viewport.x - 300): + enemy.kill() + + elif enemy.rect.y > (self.viewport.bottom): + enemy.kill() + + elif enemy.state == c.SHELL_SLIDE: + if enemy.rect.x > (self.viewport.right + 500): + enemy.kill() + + + def check_flag(self): + """Adjusts mario's state when the flag is at the bottom""" + if (self.flag.state == c.BOTTOM_OF_POLE + and self.mario.state == c.FLAGPOLE): + self.mario.set_state_to_bottom_of_pole() + + + def check_to_add_flag_score(self): + """Adds flag score if at top""" + if self.flag_score.y_vel == 0: + self.game_info[c.SCORE] += self.flag_score_total + self.flag_score_total = 0 + + + def check_for_mario_death(self): + """Restarts the level if Mario is dead""" + if self.mario.rect.y > c.SCREEN_HEIGHT and not self.mario.in_castle: + self.mario.dead = True + self.mario.x_vel = 0 + self.state = c.FROZEN + self.game_info[c.MARIO_DEAD] = True + + if self.mario.dead: + self.play_death_song() + + + def play_death_song(self): + if self.death_timer == 0: + self.death_timer = self.current_time + elif (self.current_time - self.death_timer) > 3000: + self.set_game_info_values() + self.done = True + + + def set_game_info_values(self): + """sets the new game values after a player's death""" + if self.game_info[c.SCORE] > self.persist[c.TOP_SCORE]: + self.persist[c.TOP_SCORE] = self.game_info[c.SCORE] + if self.mario.dead: + self.persist[c.LIVES] -= 1 + + if self.persist[c.LIVES] == 0: + self.next = c.GAME_OVER + self.game_info[c.CAMERA_START_X] = 0 + elif self.mario.dead == False: + self.next = c.MAIN_MENU + self.game_info[c.CAMERA_START_X] = 0 + elif self.overhead_info_display.time == 0: + self.next = c.TIME_OUT + else: + if self.mario.rect.x > 3670 \ + and self.game_info[c.CAMERA_START_X] == 0: + self.game_info[c.CAMERA_START_X] = 3440 + self.next = c.LOAD_SCREEN + + + def check_if_time_out(self): + """Check if time has run down to 0""" + if self.overhead_info_display.time <= 0 \ + and not self.mario.dead \ + and not self.mario.in_castle: + self.state = c.FROZEN + self.mario.start_death_jump(self.game_info) + + + def update_viewport(self): + """Changes the view of the camera""" + third = self.viewport.x + self.viewport.w//3 + mario_center = self.mario.rect.centerx + mario_right = self.mario.rect.right + + if self.mario.x_vel > 0 and mario_center >= third: + mult = 0.5 if mario_right < self.viewport.centerx else 1 + new = self.viewport.x + mult * self.mario.x_vel + highest = self.level_rect.w - self.viewport.w + self.viewport.x = min(highest, new) + + + def update_while_in_castle(self): + """Updates while Mario is in castle at the end of the level""" + for score in self.moving_score_list: + score.update(self.moving_score_list, self.game_info) + self.overhead_info_display.update(self.game_info) + + if self.overhead_info_display.state == c.END_OF_LEVEL: + self.state = c.FLAG_AND_FIREWORKS + self.flag_pole_group.add(castle_flag.Flag(8745, 322)) + + + def update_flag_and_fireworks(self): + """Updates the level for the fireworks and castle flag""" + for score in self.moving_score_list: + score.update(self.moving_score_list, self.game_info) + self.overhead_info_display.update(self.game_info) + self.flag_pole_group.update() + + self.end_game() + + + def end_game(self): + """End the game""" + if self.flag_timer == 0: + self.flag_timer = self.current_time + elif (self.current_time - self.flag_timer) > 2000: + self.set_game_info_values() + self.next = c.GAME_OVER + self.sound_manager.stop_music() + self.done = True + + + def blit_everything(self, surface): + """Blit all sprites to the main surface""" + self.level.blit(self.background, self.viewport, self.viewport) + if self.flag_score: + self.flag_score.draw(self.level) + self.powerup_group.draw(self.level) + self.coin_group.draw(self.level) + self.brick_group.draw(self.level) + self.coin_box_group.draw(self.level) + self.sprites_about_to_die_group.draw(self.level) + self.shell_group.draw(self.level) + #self.check_point_group.draw(self.level) + self.brick_pieces_group.draw(self.level) + self.flag_pole_group.draw(self.level) + self.mario_and_enemy_group.draw(self.level) + + surface.blit(self.level, (0,0), self.viewport) + self.overhead_info_display.draw(surface) + for score in self.moving_score_list: + score.draw(surface) + + diff --git a/pythonProject1/data/states/load_screen.py b/pythonProject1/data/states/load_screen.py new file mode 100644 index 0000000..502b844 --- /dev/null +++ b/pythonProject1/data/states/load_screen.py @@ -0,0 +1,114 @@ + +from .. import setup, tools +from .. import constants as c +from .. import game_sound +from ..components import info + +class LoadScreen(tools._State): + def __init__(self): + tools._State.__init__(self) + + def startup(self, current_time, persist): + self.start_time = current_time + self.persist = persist + self.game_info = self.persist + self.next = self.set_next_state() + + info_state = self.set_overhead_info_state() + + self.overhead_info = info.OverheadInfo(self.game_info, info_state) + self.sound_manager = game_sound.Sound(self.overhead_info) + + + def set_next_state(self): + """Sets the next state""" + return c.LEVEL1 + + def set_overhead_info_state(self): + """sets the state to send to the overhead info object""" + return c.LOAD_SCREEN + + + def update(self, surface, keys, current_time): + """Updates the loading screen""" + if (current_time - self.start_time) < 2400: + surface.fill(c.BLACK) + self.overhead_info.update(self.game_info) + self.overhead_info.draw(surface) + + elif (current_time - self.start_time) < 2600: + surface.fill(c.BLACK) + + elif (current_time - self.start_time) < 2635: + surface.fill((106, 150, 252)) + + else: + self.done = True + + + + +class GameOver(LoadScreen): + """A loading screen with Game Over""" + def __init__(self): + super(GameOver, self).__init__() + + + def set_next_state(self): + """Sets next state""" + return c.MAIN_MENU + + def set_overhead_info_state(self): + """sets the state to send to the overhead info object""" + return c.GAME_OVER + + def update(self, surface, keys, current_time): + self.current_time = current_time + self.sound_manager.update(self.persist, None) + + if (self.current_time - self.start_time) < 7000: + surface.fill(c.BLACK) + self.overhead_info.update(self.game_info) + self.overhead_info.draw(surface) + elif (self.current_time - self.start_time) < 7200: + surface.fill(c.BLACK) + elif (self.current_time - self.start_time) < 7235: + surface.fill((106, 150, 252)) + else: + self.done = True + + +class TimeOut(LoadScreen): + """Loading Screen with Time Out""" + def __init__(self): + super(TimeOut, self).__init__() + + def set_next_state(self): + """Sets next state""" + if self.persist[c.LIVES] == 0: + return c.GAME_OVER + else: + return c.LOAD_SCREEN + + def set_overhead_info_state(self): + """Sets the state to send to the overhead info object""" + return c.TIME_OUT + + def update(self, surface, keys, current_time): + self.current_time = current_time + + if (self.current_time - self.start_time) < 2400: + surface.fill(c.BLACK) + self.overhead_info.update(self.game_info) + self.overhead_info.draw(surface) + else: + self.done = True + + + + + + + + + diff --git a/pythonProject1/data/states/main_menu.py b/pythonProject1/data/states/main_menu.py new file mode 100644 index 0000000..a03bd5f --- /dev/null +++ b/pythonProject1/data/states/main_menu.py @@ -0,0 +1,145 @@ + +import pygame as pg +from .. import setup, tools +from .. import constants as c +from .. components import info, mario +class Menu(tools._State): + def __init__(self): + """Initializes the state""" + tools._State.__init__(self) + persist = {c.COIN_TOTAL: 0, + c.SCORE: 0, + c.LIVES: 3, + c.TOP_SCORE: 0, + c.CURRENT_TIME: 0.0, + c.LEVEL_STATE: None, + c.CAMERA_START_X: 0, + c.MARIO_DEAD: False} + self.startup(0.0, persist) + + def startup(self, current_time, persist): + """Called every time the game's state becomes this one. Initializes + certain values""" + self.next = c.LOAD_SCREEN + self.persist = persist + self.game_info = persist + self.overhead_info = info.OverheadInfo(self.game_info, c.MAIN_MENU) + + self.sprite_sheet = setup.GFX['title_screen'] + self.setup_background() + self.setup_mario() + self.setup_cursor() + + + def setup_cursor(self): + """Creates the mushroom cursor to select 1 or 2 player game""" + self.cursor = pg.sprite.Sprite() + dest = (220, 358) + self.cursor.image, self.cursor.rect = self.get_image( + 24, 160, 8, 8, dest, setup.GFX['item_objects']) + self.cursor.state = c.PLAYER1 + + + def setup_mario(self): + """Places Mario at the beginning of the level""" + self.mario = mario.Mario() + self.mario.rect.x = 110 + self.mario.rect.bottom = c.GROUND_HEIGHT + + + def setup_background(self): + """Setup the background image to blit""" + self.background = setup.GFX['level_1'] + self.background_rect = self.background.get_rect() + self.background = pg.transform.scale(self.background, + (int(self.background_rect.width*c.BACKGROUND_MULTIPLER), + int(self.background_rect.height*c.BACKGROUND_MULTIPLER))) + self.viewport = setup.SCREEN.get_rect(bottom=setup.SCREEN_RECT.bottom) + + self.image_dict = {} + self.image_dict['GAME_NAME_BOX'] = self.get_image( + 1, 60, 176, 88, (170, 100), setup.GFX['title_screen']) + + + + def get_image(self, x, y, width, height, dest, sprite_sheet): + """Returns images and rects to blit onto the screen""" + image = pg.Surface([width, height]) + rect = image.get_rect() + + image.blit(sprite_sheet, (0, 0), (x, y, width, height)) + if sprite_sheet == setup.GFX['title_screen']: + image.set_colorkey((255, 0, 220)) + image = pg.transform.scale(image, + (int(rect.width*c.SIZE_MULTIPLIER), + int(rect.height*c.SIZE_MULTIPLIER))) + else: + image.set_colorkey(c.BLACK) + image = pg.transform.scale(image, + (int(rect.width*3), + int(rect.height*3))) + + rect = image.get_rect() + rect.x = dest[0] + rect.y = dest[1] + return (image, rect) + + + def update(self, surface, keys, current_time): + """Updates the state every refresh""" + self.current_time = current_time + self.game_info[c.CURRENT_TIME] = self.current_time + self.update_cursor(keys) + self.overhead_info.update(self.game_info) + + surface.blit(self.background, self.viewport, self.viewport) + surface.blit(self.image_dict['GAME_NAME_BOX'][0], + self.image_dict['GAME_NAME_BOX'][1]) + surface.blit(self.mario.image, self.mario.rect) + surface.blit(self.cursor.image, self.cursor.rect) + self.overhead_info.draw(surface) + + + def update_cursor(self, keys): + """Update the position of the cursor""" + input_list = [pg.K_RETURN, pg.K_a, pg.K_s] + + if self.cursor.state == c.PLAYER1: + self.cursor.rect.y = 358 + if keys[pg.K_DOWN]: + self.cursor.state = c.PLAYER2 + for input in input_list: + if keys[input]: + self.reset_game_info() + self.done = True + elif self.cursor.state == c.PLAYER2: + self.cursor.rect.y = 403 + if keys[pg.K_UP]: + self.cursor.state = c.PLAYER1 + + + def reset_game_info(self): + """Resets the game info in case of a Game Over and restart""" + self.game_info[c.COIN_TOTAL] = 0 + self.game_info[c.SCORE] = 0 + self.game_info[c.LIVES] = 3 + self.game_info[c.CURRENT_TIME] = 0.0 + self.game_info[c.LEVEL_STATE] = None + + self.persist = self.game_info + + + + + + + + + + + + + + + + diff --git a/pythonProject1/data/tools.py b/pythonProject1/data/tools.py new file mode 100644 index 0000000..429a69c --- /dev/null +++ b/pythonProject1/data/tools.py @@ -0,0 +1,155 @@ + + +import os +import pygame as pg + +keybinding = { + 'action':pg.K_s, + 'jump':pg.K_a, + 'left':pg.K_LEFT, + 'right':pg.K_RIGHT, + 'down':pg.K_DOWN +} + +class Control(object): + """Control class for entire project. Contains the game loop, and contains + the event_loop which passes events to States as needed. Logic for flipping + states is also found here.""" + def __init__(self, caption): + self.screen = pg.display.get_surface() + self.done = False + self.clock = pg.time.Clock() + self.caption = caption + self.fps = 60 + self.show_fps = False + self.current_time = 0.0 + self.keys = pg.key.get_pressed() + self.state_dict = {} + self.state_name = None + self.state = None + + def setup_states(self, state_dict, start_state): + self.state_dict = state_dict + self.state_name = start_state + self.state = self.state_dict[self.state_name] + + def update(self): + self.current_time = pg.time.get_ticks() + if self.state.quit: + self.done = True + elif self.state.done: + self.flip_state() + self.state.update(self.screen, self.keys, self.current_time) + + def flip_state(self): + previous, self.state_name = self.state_name, self.state.next + persist = self.state.cleanup() + self.state = self.state_dict[self.state_name] + self.state.startup(self.current_time, persist) + self.state.previous = previous + + + def event_loop(self): + for event in pg.event.get(): + if event.type == pg.QUIT: + self.done = True + elif event.type == pg.KEYDOWN: + self.keys = pg.key.get_pressed() + self.toggle_show_fps(event.key) + elif event.type == pg.KEYUP: + self.keys = pg.key.get_pressed() + self.state.get_event(event) + + + def toggle_show_fps(self, key): + if key == pg.K_F5: + self.show_fps = not self.show_fps + if not self.show_fps: + pg.display.set_caption(self.caption) + + + def main(self): + """Main loop for entire program""" + while not self.done: + self.event_loop() + self.update() + pg.display.update() + self.clock.tick(self.fps) + if self.show_fps: + fps = self.clock.get_fps() + with_fps = "{} - {:.2f} FPS".format(self.caption, fps) + pg.display.set_caption(with_fps) + + +class _State(object): + def __init__(self): + self.start_time = 0.0 + self.current_time = 0.0 + self.done = False + self.quit = False + self.next = None + self.previous = None + self.persist = {} + + def get_event(self, event): + pass + + def startup(self, current_time, persistant): + self.persist = persistant + self.start_time = current_time + + def cleanup(self): + self.done = False + return self.persist + + def update(self, surface, keys, current_time): + pass + + + +def load_all_gfx(directory, colorkey=(255,0,255), accept=('.png', 'jpg', 'bmp')): + graphics = {} + for pic in os.listdir(directory): + name, ext = os.path.splitext(pic) + if ext.lower() in accept: + img = pg.image.load(os.path.join(directory, pic)) + if img.get_alpha(): + img = img.convert_alpha() + else: + img = img.convert() + img.set_colorkey(colorkey) + graphics[name]=img + return graphics + + +def load_all_music(directory, accept=('.wav', '.mp3', '.ogg', '.mdi')): + songs = {} + for song in os.listdir(directory): + name,ext = os.path.splitext(song) + if ext.lower() in accept: + songs[name] = os.path.join(directory, song) + return songs + + +def load_all_fonts(directory, accept=('.ttf')): + return load_all_music(directory, accept) + + +def load_all_sfx(directory, accept=('.wav','.mpe','.ogg','.mdi')): + effects = {} + for fx in os.listdir(directory): + name, ext = os.path.splitext(fx) + if ext.lower() in accept: + effects[name] = pg.mixer.Sound(os.path.join(directory, fx)) + return effects + + + + + + + + + + + diff --git a/pythonProject1/mario_level_1.py b/pythonProject1/mario_level_1.py new file mode 100644 index 0000000..fd4893e --- /dev/null +++ b/pythonProject1/mario_level_1.py @@ -0,0 +1,8 @@ +import sys +import pygame as pg +from data.main import main + +if __name__=='__main__': + main() + pg.quit() + sys.exit() \ No newline at end of file diff --git a/pythonProject1/resources/fonts/Fixedsys500c.ttf b/pythonProject1/resources/fonts/Fixedsys500c.ttf new file mode 100644 index 0000000..7d6946d Binary files /dev/null and b/pythonProject1/resources/fonts/Fixedsys500c.ttf differ diff --git a/pythonProject1/resources/fonts/__init__.py b/pythonProject1/resources/fonts/__init__.py new file mode 100644 index 0000000..df77b7f --- /dev/null +++ b/pythonProject1/resources/fonts/__init__.py @@ -0,0 +1 @@ +__author__ = 'justinarmstrong' diff --git a/pythonProject1/resources/graphics/__init__.py b/pythonProject1/resources/graphics/__init__.py new file mode 100644 index 0000000..df77b7f --- /dev/null +++ b/pythonProject1/resources/graphics/__init__.py @@ -0,0 +1 @@ +__author__ = 'justinarmstrong' diff --git a/pythonProject1/resources/graphics/enemies.png b/pythonProject1/resources/graphics/enemies.png new file mode 100644 index 0000000..67ae770 Binary files /dev/null and b/pythonProject1/resources/graphics/enemies.png differ diff --git a/pythonProject1/resources/graphics/item_objects.png b/pythonProject1/resources/graphics/item_objects.png new file mode 100644 index 0000000..0247be4 Binary files /dev/null and b/pythonProject1/resources/graphics/item_objects.png differ diff --git a/pythonProject1/resources/graphics/level_1.png b/pythonProject1/resources/graphics/level_1.png new file mode 100644 index 0000000..14606fd Binary files /dev/null and b/pythonProject1/resources/graphics/level_1.png differ diff --git a/pythonProject1/resources/graphics/mario_bros.png b/pythonProject1/resources/graphics/mario_bros.png new file mode 100644 index 0000000..2325110 Binary files /dev/null and b/pythonProject1/resources/graphics/mario_bros.png differ diff --git a/pythonProject1/resources/graphics/smb_enemies_sheet.png b/pythonProject1/resources/graphics/smb_enemies_sheet.png new file mode 100644 index 0000000..fd52a5e Binary files /dev/null and b/pythonProject1/resources/graphics/smb_enemies_sheet.png differ diff --git a/pythonProject1/resources/graphics/text_images.png b/pythonProject1/resources/graphics/text_images.png new file mode 100644 index 0000000..cf0d28f Binary files /dev/null and b/pythonProject1/resources/graphics/text_images.png differ diff --git a/pythonProject1/resources/graphics/tile_set.png b/pythonProject1/resources/graphics/tile_set.png new file mode 100644 index 0000000..01df713 Binary files /dev/null and b/pythonProject1/resources/graphics/tile_set.png differ diff --git a/pythonProject1/resources/graphics/title_screen.png b/pythonProject1/resources/graphics/title_screen.png new file mode 100644 index 0000000..c2c7b5d Binary files /dev/null and b/pythonProject1/resources/graphics/title_screen.png differ diff --git a/pythonProject1/resources/music/__init__.py b/pythonProject1/resources/music/__init__.py new file mode 100644 index 0000000..df77b7f --- /dev/null +++ b/pythonProject1/resources/music/__init__.py @@ -0,0 +1 @@ +__author__ = 'justinarmstrong' diff --git a/pythonProject1/resources/music/death.wav b/pythonProject1/resources/music/death.wav new file mode 100644 index 0000000..bd3400f Binary files /dev/null and b/pythonProject1/resources/music/death.wav differ diff --git a/pythonProject1/resources/music/flagpole.wav b/pythonProject1/resources/music/flagpole.wav new file mode 100644 index 0000000..10640ac Binary files /dev/null and b/pythonProject1/resources/music/flagpole.wav differ diff --git a/pythonProject1/resources/music/game_over.ogg b/pythonProject1/resources/music/game_over.ogg new file mode 100644 index 0000000..ce2b750 Binary files /dev/null and b/pythonProject1/resources/music/game_over.ogg differ diff --git a/pythonProject1/resources/music/invincible.ogg b/pythonProject1/resources/music/invincible.ogg new file mode 100644 index 0000000..380c1cd Binary files /dev/null and b/pythonProject1/resources/music/invincible.ogg differ diff --git a/pythonProject1/resources/music/main_theme.ogg b/pythonProject1/resources/music/main_theme.ogg new file mode 100644 index 0000000..6c0f59d Binary files /dev/null and b/pythonProject1/resources/music/main_theme.ogg differ diff --git a/pythonProject1/resources/music/main_theme_sped_up.ogg b/pythonProject1/resources/music/main_theme_sped_up.ogg new file mode 100644 index 0000000..1dda943 Binary files /dev/null and b/pythonProject1/resources/music/main_theme_sped_up.ogg differ diff --git a/pythonProject1/resources/music/out_of_time.wav b/pythonProject1/resources/music/out_of_time.wav new file mode 100644 index 0000000..a5ca2c5 Binary files /dev/null and b/pythonProject1/resources/music/out_of_time.wav differ diff --git a/pythonProject1/resources/music/stage_clear.wav b/pythonProject1/resources/music/stage_clear.wav new file mode 100644 index 0000000..6c396de Binary files /dev/null and b/pythonProject1/resources/music/stage_clear.wav differ diff --git a/pythonProject1/resources/music/world_clear.wav b/pythonProject1/resources/music/world_clear.wav new file mode 100644 index 0000000..aad8d86 Binary files /dev/null and b/pythonProject1/resources/music/world_clear.wav differ diff --git a/pythonProject1/resources/sound/__init__.py b/pythonProject1/resources/sound/__init__.py new file mode 100644 index 0000000..df77b7f --- /dev/null +++ b/pythonProject1/resources/sound/__init__.py @@ -0,0 +1 @@ +__author__ = 'justinarmstrong' diff --git a/pythonProject1/resources/sound/big_jump.ogg b/pythonProject1/resources/sound/big_jump.ogg new file mode 100644 index 0000000..94cd13a Binary files /dev/null and b/pythonProject1/resources/sound/big_jump.ogg differ diff --git a/pythonProject1/resources/sound/brick_smash.ogg b/pythonProject1/resources/sound/brick_smash.ogg new file mode 100644 index 0000000..7e2bef3 Binary files /dev/null and b/pythonProject1/resources/sound/brick_smash.ogg differ diff --git a/pythonProject1/resources/sound/bump.ogg b/pythonProject1/resources/sound/bump.ogg new file mode 100644 index 0000000..4b6fe0f Binary files /dev/null and b/pythonProject1/resources/sound/bump.ogg differ diff --git a/pythonProject1/resources/sound/coin.ogg b/pythonProject1/resources/sound/coin.ogg new file mode 100644 index 0000000..d21eba4 Binary files /dev/null and b/pythonProject1/resources/sound/coin.ogg differ diff --git a/pythonProject1/resources/sound/count_down.ogg b/pythonProject1/resources/sound/count_down.ogg new file mode 100644 index 0000000..378ad6f Binary files /dev/null and b/pythonProject1/resources/sound/count_down.ogg differ diff --git a/pythonProject1/resources/sound/fireball.ogg b/pythonProject1/resources/sound/fireball.ogg new file mode 100644 index 0000000..d3a3cf2 Binary files /dev/null and b/pythonProject1/resources/sound/fireball.ogg differ diff --git a/pythonProject1/resources/sound/kick.ogg b/pythonProject1/resources/sound/kick.ogg new file mode 100644 index 0000000..17b9dca Binary files /dev/null and b/pythonProject1/resources/sound/kick.ogg differ diff --git a/pythonProject1/resources/sound/main_theme_sped_up.ogg b/pythonProject1/resources/sound/main_theme_sped_up.ogg new file mode 100644 index 0000000..4851ea3 Binary files /dev/null and b/pythonProject1/resources/sound/main_theme_sped_up.ogg differ diff --git a/pythonProject1/resources/sound/one_up.ogg b/pythonProject1/resources/sound/one_up.ogg new file mode 100644 index 0000000..50a7bcf Binary files /dev/null and b/pythonProject1/resources/sound/one_up.ogg differ diff --git a/pythonProject1/resources/sound/pipe.ogg b/pythonProject1/resources/sound/pipe.ogg new file mode 100644 index 0000000..ce40c80 Binary files /dev/null and b/pythonProject1/resources/sound/pipe.ogg differ diff --git a/pythonProject1/resources/sound/powerup.ogg b/pythonProject1/resources/sound/powerup.ogg new file mode 100644 index 0000000..38673bc Binary files /dev/null and b/pythonProject1/resources/sound/powerup.ogg differ diff --git a/pythonProject1/resources/sound/powerup_appears.ogg b/pythonProject1/resources/sound/powerup_appears.ogg new file mode 100644 index 0000000..df0ea2b Binary files /dev/null and b/pythonProject1/resources/sound/powerup_appears.ogg differ diff --git a/pythonProject1/resources/sound/small_jump.ogg b/pythonProject1/resources/sound/small_jump.ogg new file mode 100644 index 0000000..01f56f6 Binary files /dev/null and b/pythonProject1/resources/sound/small_jump.ogg differ diff --git a/pythonProject1/resources/sound/stomp.ogg b/pythonProject1/resources/sound/stomp.ogg new file mode 100644 index 0000000..a2e0e42 Binary files /dev/null and b/pythonProject1/resources/sound/stomp.ogg differ diff --git a/pythonProject1/screenshot.png b/pythonProject1/screenshot.png new file mode 100644 index 0000000..0362527 Binary files /dev/null and b/pythonProject1/screenshot.png differ