Advertisement
Luca8

Untitled

Sep 27th, 2023
763
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 17.94 KB | Gaming | 0 0
  1. import arcade
  2. import arcade.gui
  3. import json
  4. from arcade import SpriteSolidColor
  5. import random
  6. from pathlib import Path
  7.  
  8. working_directory = Path(__file__).absolute().parent
  9.  
  10.  
  11. WINDOW_WIDTH = 1000        # Set our game's window properties.
  12. WINDOW_HEIGHT = 1000
  13. WINDOW_TITLE = "Reflex"
  14.  
  15. player_radius = 15         # Player character properties.    
  16. player_speed = 3
  17.  
  18. enemy_radius = 26          # Enemy properties.
  19. enemy_speed = 4
  20.  
  21.  
  22. class Player(arcade.Sprite):
  23.     def __init__(self):
  24.         super().__init__()
  25.  
  26.         self.texture = arcade.make_circle_texture(player_radius, arcade.color.BLUE)
  27.  
  28.     def update(self):      # Updates the state of the player sprite.
  29.  
  30.         self.center_x += self.change_x           # Player movement.
  31.         self.center_y += self.change_y
  32.  
  33.         if self.left < 0:                        # The player can t go outside the screen.
  34.             self.left = 0
  35.         elif self.right >= WINDOW_WIDTH:
  36.             self.right = WINDOW_WIDTH - 1
  37.         if self.bottom < 0:
  38.             self.bottom = 0
  39.         elif self.top >= WINDOW_HEIGHT:
  40.             self.top = WINDOW_HEIGHT - 1
  41.  
  42.  
  43.  
  44. class Enemies(arcade.Sprite):
  45.     def __init__(self):
  46.         super().__init__()
  47.        
  48.         self.texture = arcade.make_soft_square_texture(enemy_radius,
  49.                                                        arcade.color.RED_VIOLET,
  50.                                                        outer_alpha=255)
  51.        
  52.    
  53.     def update(self):
  54.  
  55.         self.center_y -= enemy_speed   # Updates the player movement by the enemy speed.
  56.  
  57.  
  58.  
  59. class MainMenuView(arcade.View):
  60.     def __init__(self, gameview_reference):
  61.         super().__init__()  
  62.  
  63.         self.gameview_reference = gameview_reference
  64.  
  65.         self.manager = arcade.gui.UIManager()
  66.         self.manager.enable()
  67.        
  68.         self.v_box = arcade.gui.UIBoxLayout(150, 700, space_between=20) # Creates a vertical BoxGroup to align buttons.
  69.  
  70.         self.leveling_buttons_style = {"font_name": ("calibri", "arial"),
  71.             "font_size": 15,
  72.             "font_color": arcade.color.WHITE,
  73.             "border_width": 2,
  74.             "border_color": None,
  75.             "bg_color": (21, 19, 21),
  76.             # Used if buttons are pressed
  77.             "bg_color_pressed": arcade.color.WHITE,
  78.             "border_color_pressed": arcade.color.WHITE,  # Also used when hovered
  79.             "font_color_pressed": arcade.color.BLACK
  80.             }
  81.        
  82.         button_time = arcade.gui.UIFlatButton(text="TIME", width=200,
  83.                                                    style=self.leveling_buttons_style)
  84.         button_obstacles = arcade.gui.UIFlatButton(text="OBSTACLES", width=200,
  85.                                                         style=self.leveling_buttons_style)
  86.         button_score = arcade.gui.UIFlatButton(text="SCORE", width=200,
  87.                                                     style=self.leveling_buttons_style)
  88.        
  89.         button_time.on_click = self.go_play
  90.         button_obstacles.on_click = self.go_play
  91.         button_score.on_click = self.go_play
  92.        
  93.         self.v_box.add(button_time)
  94.         self.v_box.add(button_obstacles)
  95.         self.v_box.add(button_score)
  96.  
  97.         self.manager.add(self.v_box) # Adds a widget to hold the v_box widget, that will center the buttons
  98.  
  99.    
  100.     def go_play(self, event):
  101.  
  102.         self.window.show_view(self.gameview_reference)
  103.  
  104.  
  105.     def on_draw(self):
  106.        
  107.         arcade.start_render()
  108.  
  109.         self.texture = arcade.set_background_color(arcade.color.BATTLESHIP_GREY)
  110.  
  111.         arcade.draw_text("LEVELING SYSTEM", start_x=100, start_y=750,
  112.                          color=arcade.color.BARN_RED, font_size=24, bold=True)
  113.  
  114.         self.manager.draw()
  115.    
  116.  
  117.  
  118. class PauseView(arcade.View):
  119.     def __init__(self, gameview_instance, leaderboard_list):
  120.         super().__init__()
  121.  
  122.         self.gameview_instance = gameview_instance
  123.  
  124.         self.leaderboard_list = leaderboard_list
  125.         self.leaderboard_multiline = '\n'.join([f"{name}:{score}" for placement in self.leaderboard_list
  126.                                                                 for name, score in placement.items()])
  127.         self.leaderboard_center_y = 650
  128.         self.leaderboard_placement = 1
  129.  
  130.    
  131.     def on_draw(self):
  132.        
  133.         arcade.start_render()
  134.        
  135.         self.texture = arcade.set_background_color(arcade.color.GREEN_YELLOW)
  136.  
  137.         self.leaderboard_backround = arcade.draw_rectangle_filled(200, 500,
  138.                                                                   350, 500,
  139.                                                                   arcade.color.WHITE_SMOKE)
  140.        
  141.         self.leaderboard_text = arcade.draw_text("TOP 10 LEADERBOARD",
  142.                                                  30, 725,
  143.                                                  arcade.color.RED_DEVIL, font_size=22, width=150)
  144.        
  145.         for placement in self.leaderboard_list:
  146.             name = list(placement.keys())[0]
  147.             points = list(placement.values())[0]
  148.             self.leaderboard = arcade.draw_text(f"{name}: {points}",
  149.                             40, self.leaderboard_center_y,
  150.                             arcade.color.BLACK, font_size=20)
  151.             self.leaderboard_center_y -= 30
  152.  
  153.         self.leaderboard_center_y = 650
  154.  
  155.     def on_key_press(self, key, modifier):
  156.  
  157.         if key == arcade.key.ESCAPE:
  158.             self.window.show_view(self.gameview_instance)
  159.  
  160.            
  161.  
  162. class GameOverView(arcade.View):
  163.     def __init__(self, gameview_instance, score):
  164.         super().__init__()
  165.  
  166.         self.gameview_instance = gameview_instance      # The instance of GameView used to go back to the game screen.
  167.  
  168.         self.score = score
  169.  
  170.         self.manager = arcade.gui.UIManager()     # The UI Manager. The class to which all UI elemets must be added to.
  171.         self.manager.enable()
  172.  
  173.         self.name_input = arcade.gui.UIInputText(WINDOW_WIDTH/2 - 100, WINDOW_HEIGHT/2,  # Ask for the name of the player.
  174.                                                  200, 50,
  175.                                                  "name:", font_size=20, )
  176.        
  177.         self.manager.add(self.name_input)  # Add the widget to the Manager.
  178.        
  179.    
  180.     def on_show_view(self):
  181.        
  182.         arcade.set_viewport(0, WINDOW_WIDTH, 0, WINDOW_HEIGHT)
  183.  
  184.     def on_draw(self):
  185.  
  186.         self.clear()
  187.        
  188.         arcade.set_background_color(arcade.color.BLACK_OLIVE)
  189.  
  190.         arcade.draw_lrtb_rectangle_filled(self.name_input.center_x - self.name_input.width/2,
  191.                                           self.name_input.center_x + self.name_input.width/2,
  192.                                           self.name_input.center_y + self.name_input.height/2,
  193.                                           self.name_input.center_y - self.name_input.height/4,
  194.                                           arcade.color.FLORAL_WHITE)
  195.  
  196.         self.manager.draw()
  197.  
  198.         arcade.draw_text("GAME OVER",
  199.                          WINDOW_WIDTH/2, WINDOW_HEIGHT - 250,
  200.                          arcade.color.BLACK, 60,
  201.                          anchor_x="center")
  202.         arcade.draw_text(f"your score: {self.score}", WINDOW_WIDTH/2,
  203.                           WINDOW_HEIGHT - 350,
  204.                           arcade.color.ALABAMA_CRIMSON, 40,
  205.                           anchor_x="center")
  206.         arcade.draw_text("SPACE BAR to restart",
  207.                          WINDOW_WIDTH/2, WINDOW_HEIGHT - 800,
  208.                          arcade.color.BLACK, 40,
  209.                          anchor_x="center")
  210.    
  211.     def on_key_press(self, key, modifier):
  212.        
  213.         if key == arcade.key.ENTER and self.name_input.text:         # If you press eneter and you ve written (name of the player) in the input box
  214.             player_name = self.name_input.text
  215.             self.gameview_instance.leaderboard_update(player_name, self.score)              # the function to update the leaderboard is called.
  216.  
  217.         if key == arcade.key.SPACE:
  218.             self.gameview_instance.setup()
  219.             self.window.show_view(self.gameview_instance)  # Go back to the game.
  220.            
  221.  
  222.                  
  223. class GameView(arcade.View):                   # Child class for the game of the parent class View.
  224.     def __init__(self):    # Set the parameters for the new class.
  225.         super().__init__()   # With super we pair the parameters of the new class with the View class.
  226.                                                             # Create sprites and sprite lists here.
  227.         self.player_sprite = None
  228.  
  229.         self.enemy_sprite = None                
  230.         self.enemy_sprite_list1 = None
  231.         self.enemy_sprite_list2 = None
  232.         self.enemy_collision_list = None
  233.  
  234.         self.score = None
  235.         self.score_text = None
  236.         self.score_updated = None              
  237.  
  238.         self.current_keys = None               # The list of key that are currently being pressed.
  239.  
  240.                  
  241.         self.leaderboard_list = list()         # Top scores leaderboard list holding the json file data.
  242.         try:
  243.             with open(working_directory / 'leaderboard.json', "r") as file:
  244.                 self.leaderboard_list = json.load(file)
  245.         except:
  246.             print("leaderboard.json load ERROR")
  247.  
  248.        
  249.     def setup(self):                            # Set up the game variables. Call to re-start the game.
  250.                                                 # Set you sprites and sprite lists properties here.
  251.         self.player_sprite = Player()
  252.         self.player_sprite.center_x = WINDOW_WIDTH/2 - player_radius/2  # To position the player sprite
  253.         self.player_sprite.center_y = WINDOW_HEIGHT/2 - player_radius/2 # (in this case at the center of the screen).
  254.  
  255.         self.enemy_sprite_list1 = arcade.SpriteList()
  256.         self.enemy_sprite_list2 = arcade.SpriteList()
  257.         self.enemy_collision_list = [self.enemy_sprite_list1, self.enemy_sprite_list2]
  258.  
  259.         self.score = 0
  260.         self.score_text = arcade.Text(f"SCORE: {self.score}",
  261.                                       5, WINDOW_HEIGHT - 15,
  262.                                       arcade.color.BROWN, 9, bold=True)
  263.         self.score_updated = False              # Score shouldn t update untill the player passe the obstacle
  264.         self.current_keys = set()
  265.        
  266.  
  267.     def on_update(self, delta_time):            # Event handler. Updates the state on the game objects.
  268.  
  269.             self.player_sprite.update()             # Calling the update function of the player class to update its state.
  270.            
  271.             self.enemy_sprite_list1.update()
  272.             self.enemy_sprite_list2.update()
  273.  
  274.             self.enemy_spawns()
  275.            
  276.             self.collisions()
  277.  
  278.             self.scoring()
  279.  
  280.  
  281.     def on_draw(self):                          # Method responsible for rendering (drawing) on the screen.
  282.  
  283.         self.clear()
  284.  
  285.         arcade.set_background_color(arcade.color.AMAZON)
  286.  
  287.         self.player_sprite.draw()               # Draws the player sprite on the screen.
  288.         self.enemy_sprite_list1.draw()
  289.         self.enemy_sprite_list2.draw()
  290.         self.score_text.draw()
  291.    
  292.  
  293.     def on_key_press(self, key, modifier):                   # Reads key presses.
  294.  
  295.         self.current_keys.add(key)
  296.  
  297.         if key == arcade.key.ESCAPE:
  298.             self.window.show_view(PauseView(self, self.leaderboard_list))
  299.        
  300.         if key == arcade.key.A:                              # Setting ASDW directional keys for player movement.
  301.             self.player_sprite.change_x = -player_speed
  302.         if key == arcade.key.D:
  303.             self.player_sprite.change_x = player_speed
  304.         if key == arcade.key.S:
  305.             self.player_sprite.change_y = -player_speed
  306.         if key == arcade.key.W:
  307.             self.player_sprite.change_y = player_speed
  308.    
  309.  
  310.     def on_key_release(self, key, modifier):                 # Reads key releases.
  311.        
  312.         if len(self.current_keys) != 0:
  313.             self.current_keys.remove(key)
  314.  
  315.         if (key == arcade.key.A or key == arcade.key.D) \
  316.             and (arcade.key.A not in self.current_keys and arcade.key.D not in self.current_keys):  # Handles realease and press of multiple keys at once
  317.             self.player_sprite.change_x = 0                                                         # allowing the player to move after a key release if
  318.         elif key == arcade.key.A and arcade.key.D in self.current_keys:                             # another key is still being pressed.
  319.             self.player_sprite.change_x = player_speed
  320.         elif key == arcade.key.D and arcade.key.A in self.current_keys:
  321.             self.player_sprite.change_x = -player_speed
  322.  
  323.         if (key == arcade.key.S or key == arcade.key.W) \
  324.             and (arcade.key.S not in self.current_keys and arcade.key.W not in self.current_keys):
  325.             self.player_sprite.change_y = 0
  326.         elif key == arcade.key.S and arcade.key.W in self.current_keys:
  327.             self.player_sprite.change_y = player_speed
  328.         elif key == arcade.key.W and arcade.key.S in self.current_keys:
  329.             self.player_sprite.change_y = -player_speed
  330.    
  331.  
  332.     def enemy_spawns(self):
  333.  
  334.         if len(self.enemy_sprite_list1) == 0:
  335.             enemy_count1 = random.randint(18,35)             # To set a random number of enemies to spawn (first row)
  336.            
  337.             for _ in range(enemy_count1):                    # Populating the first row on enemies.
  338.                 self.enemy_sprite = Enemies()
  339.                 self.enemy_sprite_list1.append(self.enemy_sprite)
  340.            
  341.             for enemy in self.enemy_sprite_list1:            # Setting the positions of the first row of enemies.
  342.                 enemy.center_x = random.randrange(0 + enemy_radius/2, WINDOW_WIDTH - enemy_radius/2, enemy_radius)
  343.                 enemy.center_y = WINDOW_HEIGHT + enemy_radius*2
  344.                 while arcade.check_for_collision_with_list(enemy, self.enemy_sprite_list1): # So that enemies don t spawn overlapped.
  345.                     enemy.center_x = random.randrange(0 + enemy_radius/2, WINDOW_WIDTH - enemy_radius/2, enemy_radius)
  346.        
  347.         for enemy1 in self.enemy_sprite_list1:
  348.            
  349.             if enemy1.center_y <= WINDOW_HEIGHT/2 and len(self.enemy_sprite_list2) == 0: # When the first row of enemy is at half screen (500) we create and spawn the second row.
  350.                 enemy_count2 = random.randint(18,35)            # To set a random number of enemies to spawn (second row)
  351.                
  352.                 for _ in range(enemy_count2):                   # Populating the second row of enemies.
  353.                     self.enemy_sprite = Enemies()
  354.                     self.enemy_sprite_list2.append(self.enemy_sprite)
  355.                
  356.                 for enemy2 in self.enemy_sprite_list2:          # Setting the positions of the second row of enemies.
  357.                     enemy2.center_x = random.randrange(0 + enemy_radius/2, WINDOW_WIDTH - enemy_radius/2, enemy_radius)
  358.                     enemy2.center_y = WINDOW_HEIGHT + enemy_radius*2
  359.                     while arcade.check_for_collision_with_list(enemy2, self.enemy_sprite_list2): # So that enemies don t spawn overlapped.
  360.                         enemy2.center_x = random.randrange(0 + enemy_radius/2, WINDOW_WIDTH - enemy_radius/2, enemy_radius)
  361.                    
  362.             if enemy1.center_y < 0:              # When the obstacles's center is below the screen
  363.                 self.enemy_sprite_list1.clear()  # clear the sprite list.
  364.                 self.score_updated = False       # Current row's score can be updated again.
  365.        
  366.         for enemy2 in self.enemy_sprite_list2:
  367.  
  368.             if enemy2.center_y < 0:
  369.                 self.enemy_sprite_list2.clear()
  370.                 self.score_updated = False       # Current row's score can be updated again.
  371.  
  372.  
  373.     def collisions(self):
  374.  
  375.         if arcade.check_for_collision_with_lists(self.player_sprite, self.enemy_collision_list): # Checking for collision between player and falling obstacles.
  376.             self.game_over_screen(self.score)
  377.    
  378.  
  379.     def scoring(self):
  380.        
  381.         for enemy1 in self.enemy_sprite_list1:
  382.  
  383.             if self.player_sprite.center_y > enemy1.center_y and self.score_updated == False: # Check if player has passed the obstacle
  384.                 self.score += len(self.enemy_sprite_list1)  # Adds the number of obstacles to the score
  385.                 self.score_updated = True                   # Don't update the score untill obstacles's center is under the screen.
  386.            
  387.         for enemy2 in self.enemy_sprite_list2:
  388.  
  389.             if self.player_sprite.center_y > enemy2.center_y and self.score_updated == False:
  390.                 self.score += len(self.enemy_sprite_list2)
  391.                 self.score_updated = True
  392.            
  393.            
  394.         self.score_text.text = f"SCORE: {self.score}"  # Updating the score widget on screen
  395.    
  396.  
  397.     def game_over_screen(self, score):
  398.        
  399.         self.window.show_view(GameOverView(self, score))    # Opens the game over screen
  400.  
  401.    
  402.     def leaderboard_update(self, player_name, score):
  403.        
  404.         if len(self.leaderboard_list) < 10 or score > any([value for name, value in self.leaderboard_list]):
  405.            
  406.             self.leaderboard_list.append({player_name: score})
  407.             self.leaderboard_list = sorted(self.leaderboard_list, key=lambda x: list(x.values()), reverse=True)
  408.            
  409.             with open(working_directory / 'leaderboard.json', "w") as file:
  410.                 json.dump(self.leaderboard_list, file, indent= 1)
  411.  
  412.  
  413. def main():
  414.     window = arcade.Window(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE, center_window=True)
  415.    
  416.     Reflex = GameView()  
  417.     main_menu = MainMenuView(Reflex)
  418.     window.show_view(main_menu)
  419.     Reflex.setup()
  420.     arcade.run()
  421.  
  422.  
  423. if __name__ == "__main__":          # Checks if the program is being run deirectly from the file. Won t run if the file is imported
  424.     main()
Advertisement
Comments
  • Luca8
    1 year
    # text 0.35 KB | 0 0
    1. I m working on this very simple first game. The problem i m incountering is that as i switch from gameover view to the game view class to start the game again, the more i do that the more the game becomes jittery. For what i know this is a problem of cache, but i ve checked for every variable multiple times and all should be resetting every time. Any ideas?
Add Comment
Please, Sign In to add comment
Advertisement