diff --git a/__pycache__/main.cpython-313.pyc b/__pycache__/main.cpython-313.pyc new file mode 100644 index 0000000..8a9f8a6 Binary files /dev/null and b/__pycache__/main.cpython-313.pyc differ diff --git a/__pycache__/settings.cpython-313.pyc b/__pycache__/settings.cpython-313.pyc new file mode 100644 index 0000000..43a06e3 Binary files /dev/null and b/__pycache__/settings.cpython-313.pyc differ diff --git a/main.py b/main.py index 987268a..23a7534 100644 --- a/main.py +++ b/main.py @@ -24,6 +24,8 @@ def __init__(self): self.playing = False self.pause = False self.current_level = None + self.lost = False + self.quit_level = False self.time = 0 self.command_pressed = False self.current_path = os.path.dirname(__file__) @@ -136,6 +138,8 @@ def level_screen(self): def new(self): self.background_music.stop() self.background_music.play(-1) + self.lost = False + self.quit_level = False self.current_column_number = 0 self.current_shift = 0 @@ -227,6 +231,7 @@ def update(self): self.player.rect.y = -200 else: self.playing = False + self.lost = True self.die_sound.play() if self.player.rect.x < 0: @@ -237,6 +242,7 @@ def update(self): if pygame.mouse.get_pressed()[0] == 1: if WIDTH - 200 < pos[0] < WIDTH - 200 + 180 and 20 < pos[1] < 20 + 60: self.playing = False + self.quit_level = True self.button_sound.play() def events(self): @@ -298,6 +304,28 @@ def wait(self, wait_functions): if function() is True: return i + def lose_screen(self): + if self.running is False: + return + + self.screen.fill(BLACK) + self.create_text("GAME OVER", 60, RED, WIDTH / 2, 150) + self.create_text("Score: " + str(self.score), 40, COIN_COLOR, WIDTH / 2, 250) + + retry_button = MenuButton(self, WIDTH / 2 - 150, HEIGHT / 2 + 50, self.startbutton_image) + menu_button = MenuButton(self, WIDTH / 2 + 150, HEIGHT / 2 + 50, self.menubutton_image) + + self.create_text("RETRY", 30, WHITE, WIDTH / 2 - 150, HEIGHT / 2 + 120) + self.create_text("MENU", 30, WHITE, WIDTH / 2 + 150, HEIGHT / 2 + 120) + + pygame.display.flip() + choice = self.wait([retry_button.check_click, menu_button.check_click]) + + if choice == 0: + return "retry" + elif choice == 1: + return "menu" + def end_screen(self): if self.running is False: return @@ -321,9 +349,35 @@ def end_screen(self): if __name__ == "__main__": game = Game() game.start_screen() + while game.running: - game.new() - game.run() - game.end_screen() + if game.current_level is None: + game.level_screen() + if not game.running: + break + + while True: + game.new() + game.run() + + if game.quit_level: + game.current_level = None + break + + elif game.lost: + choice = game.lose_screen() + + if choice == "retry": + continue + + elif choice == "menu": + game.current_level = None + break + + else: + game.end_screen() + game.current_level = None + break + game.save_highscore() pygame.quit() diff --git a/segway_jump_sprites/__pycache__/__init__.cpython-313.pyc b/segway_jump_sprites/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..dae8a1c Binary files /dev/null and b/segway_jump_sprites/__pycache__/__init__.cpython-313.pyc differ diff --git a/segway_jump_sprites/__pycache__/background.cpython-313.pyc b/segway_jump_sprites/__pycache__/background.cpython-313.pyc new file mode 100644 index 0000000..3e2df66 Binary files /dev/null and b/segway_jump_sprites/__pycache__/background.cpython-313.pyc differ diff --git a/segway_jump_sprites/__pycache__/coin.cpython-313.pyc b/segway_jump_sprites/__pycache__/coin.cpython-313.pyc new file mode 100644 index 0000000..994a635 Binary files /dev/null and b/segway_jump_sprites/__pycache__/coin.cpython-313.pyc differ diff --git a/segway_jump_sprites/__pycache__/items.cpython-313.pyc b/segway_jump_sprites/__pycache__/items.cpython-313.pyc new file mode 100644 index 0000000..84a8a05 Binary files /dev/null and b/segway_jump_sprites/__pycache__/items.cpython-313.pyc differ diff --git a/segway_jump_sprites/__pycache__/menubutton.cpython-313.pyc b/segway_jump_sprites/__pycache__/menubutton.cpython-313.pyc new file mode 100644 index 0000000..43c05a7 Binary files /dev/null and b/segway_jump_sprites/__pycache__/menubutton.cpython-313.pyc differ diff --git a/segway_jump_sprites/__pycache__/platforms.cpython-313.pyc b/segway_jump_sprites/__pycache__/platforms.cpython-313.pyc new file mode 100644 index 0000000..f1c9a95 Binary files /dev/null and b/segway_jump_sprites/__pycache__/platforms.cpython-313.pyc differ diff --git a/segway_jump_sprites/__pycache__/player.cpython-313.pyc b/segway_jump_sprites/__pycache__/player.cpython-313.pyc new file mode 100644 index 0000000..46d403b Binary files /dev/null and b/segway_jump_sprites/__pycache__/player.cpython-313.pyc differ diff --git a/test_game_flow.py b/test_game_flow.py new file mode 100644 index 0000000..e15e7aa --- /dev/null +++ b/test_game_flow.py @@ -0,0 +1,90 @@ +import unittest +import sys +import os + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +from unittest.mock import MagicMock, patch, call + + +class TestGameFlow(unittest.TestCase): + + @patch('pygame.init') + @patch('pygame.font.init') + @patch('pygame.mixer.init') + @patch('pygame.display.set_icon') + @patch('pygame.display.set_caption') + @patch('pygame.display.set_mode') + @patch('pygame.time.Clock') + @patch('pygame.image.load') + @patch('pygame.mixer.Sound') + def setUp(self, mock_sound, mock_image_load, mock_clock, + mock_set_mode, mock_set_caption, mock_set_icon, + mock_mixer_init, mock_font_init, mock_pygame_init): + mock_image_load.return_value = MagicMock() + mock_sound.return_value = MagicMock() + + with patch('main.Game.load_levels'): + with patch('main.Game.load_highscores'): + from main import Game + self.Game = Game + + game = object.__new__(Game) + game.levels = [{"name": "Level 1", "maxcoins": 10, "array": []}] + game.highscores = [0] + game.running = True + self.game_instance = game + + def test_new_method_resets_all_states(self): + game = self.game_instance + + game.background_music = MagicMock() + + game.lost = True + game.quit_level = True + game.current_column_number = 100 + game.current_shift = 500 + game.score = 50 + game.last_background_x_pos = 1000 + + with patch('main.Player') as mock_player: + mock_player.return_value = MagicMock() + with patch('pygame.sprite.Group') as mock_group: + mock_group.return_value = MagicMock() + + self.Game.new(game) + + self.assertFalse(game.lost) + self.assertFalse(game.quit_level) + self.assertEqual(game.current_column_number, 0) + self.assertEqual(game.current_shift, 0) + self.assertEqual(game.score, 0) + self.assertEqual(game.last_background_x_pos, 100) + + def test_player_initialization_resets_state(self): + with patch('settings.GRAVITY', 1.2): + from segway_jump_sprites.player import Player + + mock_game = MagicMock() + mock_game.character_left_walking_1_image = MagicMock() + mock_game.character_left_walking_2_image = MagicMock() + mock_game.character_left_walking_3_image = MagicMock() + mock_game.character_jump_1_image = MagicMock() + mock_game.character_jump_2_image = MagicMock() + + with patch('pygame.mask.from_surface', return_value=MagicMock()): + with patch('pygame.transform.flip', return_value=MagicMock()): + player = Player(mock_game) + + self.assertEqual(player.jumpboost, 0) + self.assertEqual(player.jumpbooston, 0) + self.assertEqual(player.speeddrop, 0) + self.assertEqual(player.speeddropon, 0) + self.assertEqual(player.rect.x, 120) + self.assertEqual(player.rect.y, -120) + self.assertEqual(player.speed.x, 0) + self.assertEqual(player.speed.y, 0) + + +if __name__ == '__main__': + unittest.main(verbosity=2)