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