Dies ist eine alte Version des Dokuments!
EF Python Projekt
Konzept:
Ein Spiel bei dem man so zu sagen nach vorne fährt und über lücken springen muss
der spieler charakter ist ein mexikaner auf einem velo
Erweiterungen:
- Verschiedene Hindernisse
- Punkte sammeln
- Main Menu
- Skins
- Verschiedene Spiel modi
Dokumentation:
Di. 3.12.2024:
- Eine Zeichnung vom Mexikaner auf dem Velo gemacht und eingefügt
- Der Mexikaner kann springen mit abbremsen
Di. 10.12.2024
- Ein Boden gemacht mit dem der Mexikaner kollidieren kann → wurde entfernt
- Ein Kaktus Hindernis erstellt
Di, 17.12.2024
- Game Over Menu hinzugefügt
- Hintergrund erstellt
- Sprites für den Mexikaner gemacht
- Sprite animiert
Mo. 23.12.2024:
- Code gekürzt und klarer gemacht mit typesetting
Do. 2.1.2025:
- Hintergrund verfeinert
- Angefangen ein Main Menu zu programmieren
Fr. 3.1.2025
- Neue Kakteen gezeichnet
- Programmieren, dass verschiedene Kakteen als Hindernisse kommen
- Musik hinzugefügt
Sa. 4.1.2025
- Score hinzugefügt
- Game over screen verfeinert
So. 5.1.2025
- Gemacht, dass die Hindernisse schneller werden, je nach dem wie lange man schon lebt → funktioniert noch nicht ganz
Mo. 6.1.2025
- Das schneller werden funktioniert jetzt
- versucht das spiel in vollbildmodus zu setzen aber es macht probleme
Di. 7.1.2025
- Hintergrund verfeinert
- Mit neuen game modi gearbeitet
Mo. 14.1.2025
- an steuerung für anderer game modus gearbeitet
Di. 15.1.2025
- Steuerung für anderer game modus beendet
- Sprites und hintergrund bearbeitet
Mo. 20.1.2025
- Steuerung verbessert von 2. spiel modus
- grund steuerung und klasse für 3. spiel modus beendet
Di. 21.1.2025
- An Grundgerüst von 3. Game modus gearbeitet → hat grosse Probleme bereitet
- Sprite groups aufgeräumt
- generell code aufgeräumt und redundanzen entfernt
Mi 22.01.2025
- Grundgerüst von 3. Game Modus überarbeitet und probleme entfernt → es ist jetzt spielbar
Sa. 15.1.2025
- mit tile generation gearbeitet
- game over angefangen zu programmieren
So. 16.1.2025
- game over fast fertig
- neue sprites für hintergrund und vordergrund im 3. game mode
- an hintergrund bewegungen gearbeitet
- score von 3. game modus programmiert
Di. 28.1.2025
- Code etwas gekürzt/verfeinert
- Wolken Sprites erstellt
- Versucht einen drückbaren knopf zu machen → funktioniert nicht, man kann ihn klicken aber er erscheint nicht auf dem bildschirm
Do. 30.1.2025
- Weiterhin am Knopf gearbeitet
- Sprites für knöpfe erstellt
- Code erneut gekürzt
Sa. 01.02.2025
- Versucht die Hitbox vom Spieler zu ändern
- 2. Game Modus entfernt, Grund: zu ähnlich zu 1. spiel modus, zeit gründe
So. 02.02.2025
- Sprites für Knöpfe erstellt
- Knöpfe beendet
- Main Menu erstellt das Knöpfe hat um das spiel zu beenden/starten
- code gekürzt, unnötige dateien entfernt
ABGABE
Code
import pygame, sys from pygame.locals import * import random pygame.init() FPS = 60 FramePerSec = pygame.time.Clock() BLACK = (0, 0, 0) WHITE = (255, 255, 255) YELLOW = (255, 204, 0) # -------------------------------------------------------------------------------------------- # GAME MODES / GAME STATES / OTHER STUFF IN THAT DIRECTION # -------------------------------------------------------------------------------------------- # game modes MAIN_MENU : bool = True DOODLE_JUMP : bool = False GOOGLE_DINO : bool = False HOME_SCREEN : bool = True GAME_SELECTION : bool = False # game states GAME_RUNNING : bool = False GAME_PAUSED : bool = False GAME_OVER : bool = False RESTARTING : bool = False # skins skin_mexican : bool = False # -------------------------------------------------------------------------------------------- # OTHER VARS # -------------------------------------------------------------------------------------------- # Screen information RES : tuple = 1100, 619 # Game related start_counter : int = 0 stop_counter : bool = False dino_is_scrolling : bool = False scrollable : bool = True IMMORTAL : bool = False reset_player : bool = False SCORE : int = 0 # dino specific cactus_type : int = 0 # Velocities JUMP_SPEED : int = 20 FALL_SPEED : int = 2 DOODLE_BASE_TILE_SPEED : float = 15.0 #Setting up Fonts font_score_in_game = pygame.font.SysFont("Determination Sans", 20) font_score_game_over = pygame.font.SysFont("Determination Sans", 60) font_distance = font_score_in_game.render("m", True, BLACK) font_score_str = font_score_game_over.render("SCORE:", True, BLACK) font_restart_game = font_score_game_over.render("Press R to restart", True, BLACK) # setting up images background_dino = pygame.image.load("bg_sky.png") background_doodle = pygame.image.load("doodle_bg2.png") background_dino_static = pygame.image.load("bg_static.png") pause_screen = pygame.image.load("pause_screen_nobg.png") game_over_font = pygame.image.load("gameove_red_big.png") title_img = pygame.image.load("title_game.png") title_bg = pygame.image.load("bg_static_no_shadow.png") # -------------------------------------------------------------------------------------------- # MUSIC AND OTHER FUNCS # -------------------------------------------------------------------------------------------- def play_music(): pygame.mixer.music.load("mexican music loop.mp3") pygame.mixer.music.play(-1) # -------------------------------------------------------------------------------------------- # BASIC GAME SETUP # -------------------------------------------------------------------------------------------- DISPLAYSURF = pygame.display.set_mode(RES) DISPLAYSURF.fill(WHITE) pygame.display.set_caption("El Mexicano Y Su Bicicleta") def load_image(name): image = pygame.image.load(name) return image #--------------------------------------------------------------------------------------------- # CLASSES: BUTTON #----------------------------------------------------------------------------------------------- button_entities = [] button_entities_selection = [] button_entities_in_game = [] class Button(): def __init__(self, POS_X_Y : tuple, SPRITE_NORMAL : str, SPRITE_HOVER : str, SPRITE_PRESSED : str, LIST_NUMBER : int, on_click_function = None, ONE_PRESS : bool = False): self.on_click_function = on_click_function self.one_press = ONE_PRESS self.sprites = [] self.sprites.append(load_image(SPRITE_NORMAL)) self.sprites.append(load_image(SPRITE_HOVER)) self.sprites.append(load_image(SPRITE_PRESSED)) self.index = 0 self.image = self.sprites[self.index] self.rect = self.image.get_rect() self.rect.center = (POS_X_Y) self.already_pressed : bool = False if LIST_NUMBER == 1: button_entities.append(self) if LIST_NUMBER == 2: button_entities_selection.append(self) if LIST_NUMBER == 3: button_entities_in_game.append(self) def process(self): self.image = self.sprites[self.index] mousePos = pygame.mouse.get_pos() if self.rect.collidepoint(mousePos): self.index = 1 if pygame.mouse.get_pressed(num_buttons=3)[0]: self.index = 2 if self.one_press: self.on_click_function() elif not self.already_pressed: self.on_click_function() self.already_pressed = True else: self.already_pressed = False else: self.index = 0 def exit_button_func(): pygame.quit() sys.exit() def exit_game_button_func(): global GAME_RUNNING global GAME_OVER global MAIN_MENU global GOOGLE_DINO global DOODLE_JUMP global HOME_SCREEN global GAME_SELECTION global RESTARTING RESTARTING = True GAME_OVER = False GAME_RUNNING = False GOOGLE_DINO = False DOODLE_JUMP = False MAIN_MENU = True GAME_SELECTION = False HOME_SCREEN = True def start_button_func(): global HOME_SCREEN global GAME_SELECTION HOME_SCREEN = False GAME_SELECTION = True def doodle_game_mode_func(): global HOME_SCREEN global GAME_SELECTION global GAME_RUNNING global MAIN_MENU global GOOGLE_DINO global DOODLE_JUMP global RESTARTING RESTARTING = True HOME_SCREEN = True GAME_SELECTION = False MAIN_MENU = False GAME_RUNNING = True GOOGLE_DINO = False DOODLE_JUMP = True def dino_game_mode_func(): global HOME_SCREEN global GAME_SELECTION global GAME_RUNNING global MAIN_MENU global GOOGLE_DINO global DOODLE_JUMP global RESTARTING RESTARTING = True HOME_SCREEN = True GAME_SELECTION = False MAIN_MENU = False GAME_RUNNING = True GOOGLE_DINO = True DOODLE_JUMP = False B_EXIT = Button((550, 500), "exit_button.png", "exit_button_hover.png", "exit_button_pressed.png", 1, exit_button_func) B_START = Button((550, 370), "start_button.png", "start_button_hover.png", "start_button_pressed.png", 1, start_button_func) B_EXIT_GAME = Button((323, 500), "exit_button.png", "exit_button_hover.png", "exit_button_pressed.png", 3, exit_game_button_func) B_DOODLE = Button((800, 400), "doodle_button.png", "doodle_button_hover.png", "doodle_button_pressed.png", 2, doodle_game_mode_func) B_DINO = Button((300, 400), "dino_button.png", "dino_button_hover.png", "dino_button_pressed.png", 2, dino_game_mode_func) # -------------------------------------------------------------------------------------------- # CLASSES: SCROLLABLE ELEMENTS # -------------------------------------------------------------------------------------------- cactus_objects = [] cactus_objects_hazards = [] class Scrollable_Elements(pygame.sprite.Sprite): def __init__(self, POS_X_Y : tuple, SPRITE_NAME : str, HAZARD : bool, SPEED : float, WAIT_TIME : int): super().__init__() self.image = pygame.image.load(SPRITE_NAME) self.rect = self.image.get_rect() self.rect.center = (POS_X_Y) if HAZARD == True: self.rect.left = (1100) cactus_objects_hazards.append(self) else: cactus_objects.append(self) self.counter = 0 self.scroll_speed : float = SPEED self.starting_speed : float = SPEED self.sprite : str = SPRITE_NAME self.is_hazard : bool = HAZARD self.wait_time = WAIT_TIME def handle_reset_dino(self): global SCORE self.scroll_speed = self.starting_speed SCORE = 0 if self.is_hazard == True: self.rect.left = 1100 def handle_scroll_h(self): global scrollable self.counter += 1 if self.counter >= self.wait_time: self.counter = 0 self.rect.move_ip(-self.scroll_speed, 0) if self.rect.right < 0: self.rect.left = (1100) scrollable = True if self.is_hazard == True: if self.scroll_speed < 20.0: self.scroll_speed += 0.5 print(self.scroll_speed) # -------------------------------------------------------------------------------------------- # CLASSES: DOODLE TILES # -------------------------------------------------------------------------------------------- tile_moving_down : bool = False tile_moving_up : bool = True tile_colliding : bool = False player_fall : bool = False off_screen_counter : int = 0 doodle_objects = [] class Doodle_Tiles(pygame.sprite.Sprite): def __init__(self, POS_X_Y : tuple, O_NAME : str, SPEED : float=15.0, COLLISION_TILE : bool=True): super().__init__() self.image = pygame.image.load("TILE.png") self.rect = self.image.get_rect() self.rect.center = (POS_X_Y) self.name : str = O_NAME self.interactable : bool = COLLISION_TILE if COLLISION_TILE == True: doodle_objects.append(self) self.jump_speed : float = SPEED self.counter : int = 0 def reset_speed(self): self.jump_speed = 15.0 def handle_move_tiles(self): global tile_moving_down global tile_moving_up global tile_colliding global off_screen_counter global player_fall global SCORE if tile_moving_up == True: tile_moving_down = False self.rect.move_ip(0, -self.jump_speed) off_screen_counter += 1 if self.jump_speed <= 20.0: self.jump_speed *= 1.2 if tile_moving_down == True: if self.jump_speed > 1: self.rect.move_ip(0, self.jump_speed) self.jump_speed *= 0.93 if self.jump_speed < 1: self.jump_speed = 1 tile_moving_up = True tile_moving_down = False if self.rect.top > 700: self.rect.center = (550 + random.randint(-550, 550), -10) SCORE += 5 if off_screen_counter >= 550: player_fall = True def handle_reset_doodle(self): if self.name == "T1": self.rect.center = (300, 500) if self.name == "T2": self.rect.center = (800, 400) if self.name == "T3": self.rect.center = (500, 300) if self.name == "T4": self.rect.center = (700, 200) if self.name == "T5": self.rect.center = (400, 100) if self.name == "T6": self.rect.center = (300, 0) if self.name == "T7": self.rect.center = (0, 600) # -------------------------------------------------------------------------------------------- # CLASSES: PLAYER # -------------------------------------------------------------------------------------------- # states and what not IS_JUMPING : bool = False MOVE_UP : bool = False MOVE_DOWN : bool = False stop_game : bool = False player = [] class Player(pygame.sprite.Sprite): def __init__(self): super().__init__() global GOOGLE_DINO global DOODLE_JUMP self.sprite = [] self.sprite.append(load_image("Player1.png")) self.sprite.append(load_image("Player2.png")) self.sprite.append(load_image("Player3.png")) self.sprite.append(load_image("Player4.png")) self.counter = 0 self.score_countdown = 0 self.index = 0 self.image = self.sprite[self.index] self.rect = self.image.get_rect() if GOOGLE_DINO == True: self.hitbox = pygame.Rect(1, 1, 238, 110) self.hitbox.center = (-100, -100) self.rect.center = (160, 380) if DOODLE_JUMP == True: self.hitbox = pygame.Rect(1, 1, 180, 334) self.rect.center = (500, 350) player.append(self) def handle_reset(self): global GOOGLE_DINO global DOODLE_JUMP if GOOGLE_DINO == True: self.rect.center = (160, 380) if DOODLE_JUMP == True: self.rect.center = (500, 350) def handle_jump(self): global reset_player global IS_JUMPING global JUMP_SPEED global FALL_SPEED if IS_JUMPING == False: pressed_keys = pygame.key.get_pressed() if pressed_keys [K_SPACE]: if JUMP_SPEED > 1: self.rect.move_ip(0, -JUMP_SPEED) JUMP_SPEED *= 0.93 if JUMP_SPEED < 1: IS_JUMPING = True else: IS_JUMPING = True else: if self.rect.bottom < 540: self.rect.move_ip(0, FALL_SPEED) FALL_SPEED *= 1.1 if self.rect.bottom > 539: self.rect.center = (160, 380) IS_JUMPING = False JUMP_SPEED = 20 FALL_SPEED = 2 def handle_left_right(self, MOVE_SPEED : int): pressed_keys = pygame.key.get_pressed() if pressed_keys [K_a]: self.rect.move_ip(-MOVE_SPEED, 0) if self.rect.right < (0): self.rect.left = (1100) if pressed_keys [K_d]: self.rect.move_ip(MOVE_SPEED , 0) if self.rect.left > (1100): self.rect.right = (0) def handle_animation(self): self.counter += 1 if self.counter >= 4: self.counter = 0 self.index += 1 if self.index >= len(self.sprite): self.index = 0 self.image = self.sprite[self.index] def handle_doodle_game_over(self): global stop_game self.rect.move_ip(0, 25) if self.rect.top >= 1200: stop_game = True def handle_score_dino(self): global SCORE self.score_countdown += 1 if self.score_countdown >= 7: SCORE += 1 self.score_countdown = 0 # -------------------------------------------------------------------------------------------- # CREATING OBJECTS # -------------------------------------------------------------------------------------------- HBG3_1 = Scrollable_Elements((1100, 347), "dune.png", False, 1, 0) #dune layer HBG3_2 = Scrollable_Elements((1800, 267), "dune2.png", False, 1, 0) HBG2_1 = Scrollable_Elements((1100, 315), "smallest_cactus.png", False, 2, 0) # small cactus HBG2_2 = Scrollable_Elements((1400, 320), "bg_cactus.png", False, 2, 1) # small cactus HBG1_1 = Scrollable_Elements((1100, 380), "middle_ground_cactus.png", False, 3, 0) # big cactus BG_CLOUDS1 = Scrollable_Elements((550, 309), "bg_clouds.png", False, 1, 2) BG_CLOUDS2 = Scrollable_Elements((1650, 309), "bg_clouds.png", False, 1, 2) P1 = Player() C1 = Scrollable_Elements((1100, 460), "default_cactus.png", True, 10, 0) C2 = Scrollable_Elements((1100, 500), "flat_wide_cactus.png", True, 10, 0) C3 = Scrollable_Elements((1100, 520), "small_round_cactus.png", True, 10, 0) C4 = Scrollable_Elements((1100, 460), "tall_slim_cactus.png", True, 10, 0) T1 = Doodle_Tiles((300, 500), "T1") T2 = Doodle_Tiles((800, 400), "T2") T3 = Doodle_Tiles((500, 300), "T3") T4 = Doodle_Tiles((700, 200), "T4") T5 = Doodle_Tiles((100, 100), "T5") T6 = Doodle_Tiles((100, 0), "T6") T7 = Doodle_Tiles((100, 600), "T7") # -------------------------------------------------------------------------------------------- # GROUPS # -------------------------------------------------------------------------------------------- players = pygame.sprite.Group() players.add(P1) # collision group hazards = pygame.sprite.Group() hazards.add(C1) hazards.add(C2) hazards.add(C3) hazards.add(C4) # draw group bg_objects = pygame.sprite.Group() bg_objects.add(BG_CLOUDS1) bg_objects.add(BG_CLOUDS2) # draw and collision group doodle_tile = pygame.sprite.Group() doodle_tile.add(T1) doodle_tile.add(T2) doodle_tile.add(T3) doodle_tile.add(T4) doodle_tile.add(T5) doodle_tile.add(T6) doodle_tile.add(T7) # draw group main_menu_background = pygame.sprite.Group() main_menu_background.add(HBG3_1) main_menu_background.add(HBG3_2) main_menu_background.add(HBG2_1) main_menu_background.add(HBG2_2) main_menu_background.add(HBG1_1) # draw group dino_sprites = pygame.sprite.Group() dino_sprites.add(HBG3_1) dino_sprites.add(HBG3_2) dino_sprites.add(HBG2_1) dino_sprites.add(HBG2_2) dino_sprites.add(HBG1_1) dino_sprites.add(C1) dino_sprites.add(C2) dino_sprites.add(C3) dino_sprites.add(C4) # -------------------------------------------------------------------------------------------- # GENERAL FUNCS # -------------------------------------------------------------------------------------------- def reset_doodle_speed_all(): for entity in doodle_objects: entity.reset_speed() if RESTARTING == True: for entity in doodle_objects: entity.handle_reset_doodle() def handle_collision_detection(): global tile_colliding global tile_moving_down global tile_moving_up global off_screen_counter if tile_moving_up == True: if pygame.sprite.spritecollideany(P1, doodle_tile): tile_colliding = True reset_doodle_speed_all() tile_moving_down = True tile_moving_up = False off_screen_counter = 0 def handle_invulnerability(): global IMMORTAL pressed_keys = pygame.key.get_pressed() if IMMORTAL == False: if pressed_keys [K_1]: IMMORTAL = True print("Immortal") if IMMORTAL == True: if pressed_keys [K_2]: IMMORTAL = False print("mortal") # -------------------------------------------------------------------------------------------- # GAME PROCESS GENERAL # -------------------------------------------------------------------------------------------- play_music() while True: pressed_keys = pygame.key.get_pressed() handle_invulnerability() for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() if MAIN_MENU == True: DISPLAYSURF.blit(background_dino, (0,0)) for entity in bg_objects: DISPLAYSURF.blit(entity.image, entity.rect) DISPLAYSURF.blit(title_bg, (0,0)) for entity in cactus_objects: entity.handle_scroll_h() for entity in main_menu_background: DISPLAYSURF.blit(entity.image, entity.rect) if HOME_SCREEN == True: DISPLAYSURF.blit(title_img, (150, 20)) for entity in button_entities: entity.process() DISPLAYSURF.blit(entity.image, entity.rect) if GAME_SELECTION == True: for entity in button_entities_selection: entity.process() DISPLAYSURF.blit(entity.image, entity.rect) if GAME_OVER == True: font_score_num_game_over = font_score_game_over.render(str(SCORE), True, BLACK) DISPLAYSURF.fill(YELLOW) DISPLAYSURF.blit(game_over_font, (150,100)) DISPLAYSURF.blit(font_score_str, (220, 280)) DISPLAYSURF.blit(font_restart_game, (220, 350)) DISPLAYSURF.blit(font_score_num_game_over, (420, 280)) for entity in button_entities_in_game: DISPLAYSURF.blit(entity.image, entity.rect) entity.process() pygame.display.update() if pressed_keys [K_r]: GAME_RUNNING = True GAME_OVER = False RESTARTING = True if GAME_PAUSED == True: GAME_RUNNING = False DISPLAYSURF.blit(pause_screen, (0,0)) if pressed_keys [K_e]: GAME_PAUSED = False GAME_RUNNING = True # -------------------------------------------------------------------------------------------- # GAME RUNNING SHIT THAT IS ACTUALLY RUNNING # -------------------------------------------------------------------------------------------- if GAME_RUNNING == True: if pressed_keys [K_ESCAPE]: GAME_PAUSED = True if RESTARTING == True: start_counter = 0 stop_counter = False dino_is_scrolling = False scrollable = False stop_game = False player_fall = False off_screen_counter = 0 SCORE = 0 P1.handle_reset() if GOOGLE_DINO == True: for entity in cactus_objects_hazards: entity.handle_reset_dino() if DOODLE_JUMP == True: reset_doodle_speed_all() RESTARTING = False # -------------------------------------------------------------------------------------------- # DOODLE JUMP GAME # -------------------------------------------------------------------------------------------- if DOODLE_JUMP == True: score_number = font_score_in_game.render(str(SCORE), True, BLACK) DISPLAYSURF.blit(background_doodle, (0,0)) for entity in doodle_tile: DISPLAYSURF.blit(entity.image, entity.rect) DISPLAYSURF.blit(score_number, (1000, 10)) DISPLAYSURF.blit(font_distance, (1080, 10)) handle_collision_detection() for entity in player: entity.handle_left_right(15) entity.handle_animation() DISPLAYSURF.blit(entity.image, entity.rect) for entity in doodle_objects: entity.handle_move_tiles() if player_fall == True: P1.handle_doodle_game_over() if stop_game == True: GAME_RUNNING = False GAME_OVER = True # -------------------------------------------------------------------------------------------- # GOOGLE DINO GAME # -------------------------------------------------------------------------------------------- if GOOGLE_DINO == True: score_number = font_score_in_game.render(str(SCORE), True, BLACK) if scrollable == True: cactus_type = random.randint(1, 4) for entity in cactus_objects: entity.handle_scroll_h() P1.handle_jump() P1.handle_score_dino() if stop_counter == False: if start_counter < 80: start_counter += 1 if start_counter >= 80: dino_is_scrolling = True stop_counter = True scrollable = True if dino_is_scrolling == True: if cactus_type == 1: scrollable = False C1.handle_scroll_h() if cactus_type == 2: scrollable = False C2.handle_scroll_h() if cactus_type == 3: scrollable = False C3.handle_scroll_h() if cactus_type == 4: scrollable = False C4.handle_scroll_h() DISPLAYSURF.blit(background_dino, (0,0)) for entity in bg_objects: DISPLAYSURF.blit(entity.image, entity.rect) DISPLAYSURF.blit(background_dino_static, (0,0)) for entity in dino_sprites: DISPLAYSURF.blit(entity.image, entity.rect) for entity in players: DISPLAYSURF.blit(entity.image, entity.rect) DISPLAYSURF.blit(score_number, (1000, 10)) DISPLAYSURF.blit(font_distance, (1080, 10)) P1.handle_animation() if IMMORTAL == False: if pygame.sprite.spritecollideany(P1, hazards): reset_player = True GAME_OVER = True GAME_RUNNING = False # -------------------------------------------------------------------------------------------- # -------------------------------------------------------------------------------------------- pygame.display.update() FramePerSec.tick(FPS) # .\virt_env\Scripts\activate
Ordner
Quellen
(Für genauere Details siehe '00 READ ME.txt' im zip Ordner)
Alle visuellen Assets wurden von mir gemacht, mit einigen Hilfen von heruntergeladenen Schriften
Audio ist von YouTube
Code wurde von mir gemacht mit einigen Tutorials (im txt Dokument '00 READ ME.txt' vermerkt), AI wurde nie gebraucht