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 = Button1)
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 ''