8 changed files with 1136 additions and 0 deletions
@ -0,0 +1,90 @@ |
|||||
|
import pygame |
||||
|
import sys |
||||
|
import os |
||||
|
|
||||
|
pygame.init() |
||||
|
pygame.mixer.init() # DŮLEŽITÉ: Inicializace zvukového modulu |
||||
|
|
||||
|
okno = pygame.display.set_mode((800, 600)) |
||||
|
pygame.display.set_caption("Lekce 5: Práce s obrázky a zvuky (Assety)") |
||||
|
|
||||
|
# ===================================================================== |
||||
|
# 1. NAČÍTÁNÍ OBRÁZKŮ |
||||
|
# ===================================================================== |
||||
|
# Pro správné načtení je nejlepší mít obrázky ve stejné složce jako skript. |
||||
|
# Doporučujeme formát .png (podporuje průhledné pozadí) nebo .jpg. |
||||
|
cesta_k_obrazku = "hrac.png" |
||||
|
|
||||
|
try: |
||||
|
# Načteme obrázek z disku |
||||
|
obrazek_hrace = pygame.image.load(cesta_k_obrazku) |
||||
|
|
||||
|
# DŮLEŽITÉ: convert_alpha() výrazně zrychlí vykreslování v Pygame |
||||
|
# a zachová průhlednost u PNG obrázků. |
||||
|
obrazek_hrace = obrazek_hrace.convert_alpha() |
||||
|
|
||||
|
# Pokud je obrázek moc velký, můžeme ho zmenšit (např. na 50x50 pixelů) |
||||
|
obrazek_hrace = pygame.transform.scale(obrazek_hrace, (50, 50)) |
||||
|
|
||||
|
obrazek_nacten = True |
||||
|
except FileNotFoundError: |
||||
|
print(f"POZOR: Obrázek '{cesta_k_obrazku}' nebyl nalezen! Nakreslím místo něj čtverec.") |
||||
|
obrazek_nacten = False |
||||
|
|
||||
|
# ===================================================================== |
||||
|
# 2. NAČÍTÁNÍ ZVUKŮ |
||||
|
# ===================================================================== |
||||
|
# Zvuky (.wav nebo .ogg - mp3 někdy v Pygame zlobí) |
||||
|
cesta_ke_zvuku = "skok.wav" |
||||
|
|
||||
|
try: |
||||
|
zvuk_skoku = pygame.mixer.Sound(cesta_ke_zvuku) |
||||
|
# Zvuku můžeme nastavit hlasitost (0.0 až 1.0) |
||||
|
zvuk_skoku.set_volume(0.5) |
||||
|
zvuk_nacten = True |
||||
|
except FileNotFoundError: |
||||
|
print(f"POZOR: Zvuk '{cesta_ke_zvuku}' nebyl nalezen! Hra poběží potichu.") |
||||
|
zvuk_nacten = False |
||||
|
|
||||
|
|
||||
|
# Pozice a barvy |
||||
|
x, y = 350, 250 |
||||
|
CERNA = (0, 0, 0) |
||||
|
MODRA = (0, 0, 255) |
||||
|
BILA = (255, 255, 255) |
||||
|
|
||||
|
font = pygame.font.SysFont("Arial", 24) |
||||
|
|
||||
|
bezime = True |
||||
|
while bezime: |
||||
|
for udalost in pygame.event.get(): |
||||
|
if udalost.type == pygame.QUIT: |
||||
|
bezime = False |
||||
|
|
||||
|
# Zvuk přehrajeme např. při stisku mezerníku |
||||
|
if udalost.type == pygame.KEYDOWN: |
||||
|
if udalost.key == pygame.K_SPACE: |
||||
|
if zvuk_nacten: |
||||
|
zvuk_skoku.play() # Přehraje zvuk |
||||
|
else: |
||||
|
print("PÍÍÍP! (Tady by hrál zvuk)") |
||||
|
|
||||
|
# Vykreslování |
||||
|
okno.fill(CERNA) |
||||
|
|
||||
|
text = font.render("Stiskni MEZERNÍK pro přehrání zvuku.", True, BILA) |
||||
|
okno.blit(text, (10, 10)) |
||||
|
|
||||
|
if obrazek_nacten: |
||||
|
# Místo pygame.draw.rect() použijeme okno.blit() pro vykreslení obrázku |
||||
|
okno.blit(obrazek_hrace, (x, y)) |
||||
|
else: |
||||
|
# Nouzové řešení, pokud obrázek chybí |
||||
|
pygame.draw.rect(okno, MODRA, (x, y, 50, 50)) |
||||
|
text_chyba = font.render(f"Chybí soubor {cesta_k_obrazku}", True, (255, 0, 0)) |
||||
|
okno.blit(text_chyba, (x, y - 30)) |
||||
|
|
||||
|
pygame.display.flip() |
||||
|
|
||||
|
pygame.quit() |
||||
|
sys.exit() |
||||
@ -0,0 +1,107 @@ |
|||||
|
import pygame |
||||
|
import sys |
||||
|
import random |
||||
|
|
||||
|
# Inicializace knihovny Pygame (nutné zavolat na začátku každého Pygame programu) |
||||
|
pygame.init() |
||||
|
|
||||
|
# --- Nastavení okna --- |
||||
|
SIRKA = 800 |
||||
|
VYSKA = 600 |
||||
|
okno = pygame.display.set_mode((SIRKA, VYSKA)) |
||||
|
pygame.display.set_caption("Chytání jablek") |
||||
|
|
||||
|
# --- Barvy (R, G, B) --- |
||||
|
CERNA = (0, 0, 0) |
||||
|
ZELENA = (0, 255, 0) # Barva hráče (košíku) |
||||
|
CERVENA = (255, 0, 0) # Barva jablka |
||||
|
BILA = (255, 255, 255) # Barva textu |
||||
|
|
||||
|
# Hodiny pro udržení stabilní rychlosti hry (FPS) |
||||
|
hodiny = pygame.time.Clock() |
||||
|
font = pygame.font.SysFont("Arial", 36) |
||||
|
|
||||
|
# --- Proměnné Hráče (Košíku) --- |
||||
|
hrac_sirka = 100 |
||||
|
hrac_vyska = 20 |
||||
|
# Začínáme uprostřed obrazovky dole |
||||
|
hrac_x = SIRKA // 2 - hrac_sirka // 2 |
||||
|
hrac_y = VYSKA - 40 |
||||
|
rychlost_hrace = 8 |
||||
|
|
||||
|
# --- Proměnné Jablka --- |
||||
|
jablko_velikost = 30 |
||||
|
# Jablko začne na náhodné X pozici, ale nahoře mimo obrazovku (Y = záporné) |
||||
|
jablko_x = random.randint(0, SIRKA - jablko_velikost) |
||||
|
jablko_y = -jablko_velikost |
||||
|
rychlost_jablka = 5 |
||||
|
|
||||
|
skore = 0 |
||||
|
zivoty = 3 |
||||
|
|
||||
|
bezime = True |
||||
|
# --- Hlavní herní smyčka --- |
||||
|
while bezime: |
||||
|
# 1. Zpracování událostí (kliknutí na křížek pro zavření okna) |
||||
|
for udalost in pygame.event.get(): |
||||
|
if udalost.type == pygame.QUIT: |
||||
|
bezime = False |
||||
|
|
||||
|
# Pokud ještě máme životy, hrajeme |
||||
|
if zivoty > 0: |
||||
|
# 2. Logika pohybu hráče (čtení aktuálně stisknutých kláves) |
||||
|
klavesy = pygame.key.get_pressed() |
||||
|
if klavesy[pygame.K_LEFT] and hrac_x > 0: |
||||
|
hrac_x -= rychlost_hrace |
||||
|
# Omezení, aby hráč nevyjel zprava ven |
||||
|
if klavesy[pygame.K_RIGHT] and hrac_x < SIRKA - hrac_sirka: |
||||
|
hrac_x += rychlost_hrace |
||||
|
|
||||
|
# 3. Logika padání jablka (měníme pouze osu Y) |
||||
|
jablko_y += rychlost_jablka |
||||
|
|
||||
|
# --- KOLIZE (Zjištění, zda hráč chytil jablko) --- |
||||
|
# Vytvoříme si virtuální obdélníky (Rect) pro zjednodušení detekce |
||||
|
hrac_rect = pygame.Rect(hrac_x, hrac_y, hrac_sirka, hrac_vyska) |
||||
|
jablko_rect = pygame.Rect(jablko_x, jablko_y, jablko_velikost, jablko_velikost) |
||||
|
|
||||
|
# Metoda colliderect zjistí, zda se dva obdélníky právě teď překrývají |
||||
|
if hrac_rect.colliderect(jablko_rect): |
||||
|
skore += 1 |
||||
|
rychlost_jablka += 0.2 # Hra se postupně stává těžší (jablka padají rychleji) |
||||
|
|
||||
|
# Vygenerování nového jablka nahoře |
||||
|
jablko_y = -jablko_velikost |
||||
|
jablko_x = random.randint(0, SIRKA - jablko_velikost) |
||||
|
|
||||
|
# Co když jablko spadne na zem a my ho nechytíme? |
||||
|
elif jablko_y > VYSKA: |
||||
|
zivoty -= 1 |
||||
|
# Vygenerování nového jablka nahoře pro další pokus |
||||
|
jablko_y = -jablko_velikost |
||||
|
jablko_x = random.randint(0, SIRKA - jablko_velikost) |
||||
|
|
||||
|
# 4. Vykreslování na obrazovku |
||||
|
okno.fill(CERNA) # Vymazání předchozího snímku z obrazovky |
||||
|
|
||||
|
if zivoty > 0: |
||||
|
# Vykreslení hráče |
||||
|
pygame.draw.rect(okno, ZELENA, (hrac_x, hrac_y, hrac_sirka, hrac_vyska)) |
||||
|
# Vykreslení jablka |
||||
|
pygame.draw.rect(okno, CERVENA, (jablko_x, jablko_y, jablko_velikost, jablko_velikost)) |
||||
|
|
||||
|
# Vykreslení textů (Skóre a Životy) |
||||
|
text_skore = font.render(f"Skóre: {skore}", True, BILA) |
||||
|
text_zivoty = font.render(f"Životy: {zivoty}", True, BILA) |
||||
|
okno.blit(text_skore, (10, 10)) # blit znamená "překresli tento text na okno" |
||||
|
okno.blit(text_zivoty, (SIRKA - 150, 10)) |
||||
|
else: |
||||
|
# Pokud došly životy, zobrazíme červený nápis Konec Hry uprostřed |
||||
|
text_konec = font.render(f"KONEC HRY! Tvé skóre: {skore}", True, CERVENA) |
||||
|
okno.blit(text_konec, (SIRKA//2 - 180, VYSKA//2)) |
||||
|
|
||||
|
pygame.display.flip() # Propíšeme vše na monitor pro hráče |
||||
|
hodiny.tick(60) # Udržujeme rychlost na stabilních 60 snímcích za sekundu (FPS) |
||||
|
|
||||
|
pygame.quit() |
||||
|
sys.exit() |
||||
@ -0,0 +1,172 @@ |
|||||
|
import pygame |
||||
|
import random |
||||
|
import sys |
||||
|
|
||||
|
# Inicializace Pygame |
||||
|
pygame.init() |
||||
|
|
||||
|
# --- Nastavení okna a základních konstant --- |
||||
|
SIRKA_OKNA = 400 |
||||
|
VYSKA_OKNA = 600 |
||||
|
FPS = 60 # Vyšší FPS pro plynulejší pád |
||||
|
|
||||
|
# Barvy (R, G, B) |
||||
|
CERNA = (0, 0, 0) |
||||
|
BILA = (255, 255, 255) |
||||
|
MODRA_OBLOHA = (135, 206, 235) |
||||
|
ZELENA = (34, 139, 34) |
||||
|
ZLUTYP_PTAK = (255, 215, 0) |
||||
|
CERVENA = (255, 0, 0) |
||||
|
|
||||
|
# Vytvoření okna |
||||
|
okno = pygame.display.set_mode((SIRKA_OKNA, VYSKA_OKNA)) |
||||
|
pygame.display.set_caption("Flappy Bird") |
||||
|
|
||||
|
# Hodiny pro řízení rychlosti hry |
||||
|
hodiny = pygame.time.Clock() |
||||
|
|
||||
|
# Písma pro texty |
||||
|
font_velky = pygame.font.SysFont("arial", 48, bold=True) |
||||
|
font_maly = pygame.font.SysFont("arial", 24) |
||||
|
|
||||
|
def zobraz_text(text, font, barva, x, y, zarovnat_stred=False): |
||||
|
"""Pomocná funkce pro text. Umí vycentrovat text podle zadané pozice x, y.""" |
||||
|
plocha = font.render(text, True, barva) |
||||
|
if zarovnat_stred: |
||||
|
rect = plocha.get_rect(center=(x, y)) |
||||
|
okno.blit(plocha, rect) |
||||
|
else: |
||||
|
okno.blit(plocha, (x, y)) |
||||
|
|
||||
|
def hlavni_smycka(): |
||||
|
# --- Proměnné Ptáka --- |
||||
|
ptak_x = 50 |
||||
|
ptak_y = VYSKA_OKNA // 2 |
||||
|
ptak_sirka = 30 |
||||
|
ptak_vyska = 30 |
||||
|
|
||||
|
rychlost_padu = 0 # Aktuální vertikální rychlost |
||||
|
gravitace = 0.5 # Jak moc ptáka přitahuje zem v každém snímku |
||||
|
sila_skoku = -8 # Negativní hodnota posouvá ptáka nahoru |
||||
|
|
||||
|
# --- Proměnné Překážek (Trubek) --- |
||||
|
trubka_sirka = 60 |
||||
|
mezera_mezi_trubkami = 160 # Výšková mezera kudy pták prolétá |
||||
|
rychlost_posunu = 3 # Rychlost, kterou jedou trubky doleva |
||||
|
|
||||
|
# Seznam překážek. Budeme ukládat slovníky se souřadnicemi. |
||||
|
# Např: {"x": 400, "y_stred": 300} -> 'y_stred' určuje, kde je střed mezery pro průlet. |
||||
|
trubky = [] |
||||
|
|
||||
|
# Funkce, která náhodně vymyslí, kde bude mezera, a přidá trubku do seznamu |
||||
|
def pridej_trubku(x_pozice): |
||||
|
# Střed mezery nebude příliš blízko u okraje (150 pixelů od okrajů) |
||||
|
stred_mezery = random.randint(150, VYSKA_OKNA - 150) |
||||
|
trubky.append({"x": x_pozice, "y_stred": stred_mezery}) |
||||
|
|
||||
|
# Přidáme první dvě překážky na začátek (úplně mimo obrazovku vpravo) |
||||
|
pridej_trubku(SIRKA_OKNA + 100) |
||||
|
pridej_trubku(SIRKA_OKNA + 400) # Druhá trubka bude o 300 pixelů dále |
||||
|
|
||||
|
skore = 0 |
||||
|
# Stavy hry jsou výborné pro pochopení "Stavových automatů" (State Machines) |
||||
|
stav_hry = "START" # Stavy: "START", "HRA", "KONEC" |
||||
|
|
||||
|
# --- Hlavní herní smyčka --- |
||||
|
while True: |
||||
|
# 1. Zpracování událostí (klávesnice) |
||||
|
for udalost in pygame.event.get(): |
||||
|
if udalost.type == pygame.QUIT: |
||||
|
pygame.quit() |
||||
|
sys.exit() |
||||
|
|
||||
|
if udalost.type == pygame.KEYDOWN: |
||||
|
if udalost.key == pygame.K_SPACE: |
||||
|
# Co dělá mezerník záleží na tom, v jakém stavu je hra |
||||
|
if stav_hry == "START": |
||||
|
stav_hry = "HRA" # Zapneme hru a ihned skočíme |
||||
|
rychlost_padu = sila_skoku |
||||
|
elif stav_hry == "HRA": |
||||
|
rychlost_padu = sila_skoku # Skok nahoru |
||||
|
elif stav_hry == "KONEC": |
||||
|
return # Vyskočíme z této funkce, aby vnější smyčka spustila hru od znova |
||||
|
|
||||
|
# 2. Logika a pohyb |
||||
|
if stav_hry == "HRA": |
||||
|
# Pták padá vlivem gravitace |
||||
|
rychlost_padu += gravitace |
||||
|
ptak_y += rychlost_padu |
||||
|
|
||||
|
# Posouváme všechny trubky doleva |
||||
|
for t in trubky: |
||||
|
t["x"] -= rychlost_posunu |
||||
|
|
||||
|
# Odstranění trubky, která celá zmizela za levým okrajem obrazovky |
||||
|
if trubky[0]["x"] < -trubka_sirka: |
||||
|
trubky.pop(0) # Smaže první trubku v seznamu |
||||
|
|
||||
|
# Spočítáme pozici X té poslední trubky v seznamu a novou dáme za ni |
||||
|
posledni_trubka_x = trubky[-1]["x"] |
||||
|
pridej_trubku(posledni_trubka_x + 300) |
||||
|
|
||||
|
# Pokud zmizí trubka (pták ji přeletěl), získáme bod! |
||||
|
skore += 1 |
||||
|
|
||||
|
# --- Detekce kolizí (nárazů) --- |
||||
|
# Vytvoříme 'Neviditelný obdélník' (Rect) kolem ptáka pro snadnější zjišťování kolizí |
||||
|
ptak_rect = pygame.Rect(ptak_x, ptak_y, ptak_sirka, ptak_vyska) |
||||
|
|
||||
|
# Náraz do stropu nebo podlahy okna |
||||
|
if ptak_y < 0 or ptak_y + ptak_vyska > VYSKA_OKNA: |
||||
|
stav_hry = "KONEC" |
||||
|
|
||||
|
# Náraz do trubek |
||||
|
for t in trubky: |
||||
|
# Rect pro horní zelenou trubku |
||||
|
horni_vyska = t["y_stred"] - (mezera_mezi_trubkami // 2) |
||||
|
horni_rect = pygame.Rect(t["x"], 0, trubka_sirka, horni_vyska) |
||||
|
|
||||
|
# Rect pro dolní zelenou trubku |
||||
|
dolni_y = t["y_stred"] + (mezera_mezi_trubkami // 2) |
||||
|
dolni_rect = pygame.Rect(t["x"], dolni_y, trubka_sirka, VYSKA_OKNA - dolni_y) |
||||
|
|
||||
|
# Pokud se náš obdélník ptáka překrývá s horní nebo dolní trubkou, je konec! |
||||
|
if ptak_rect.colliderect(horni_rect) or ptak_rect.colliderect(dolni_rect): |
||||
|
stav_hry = "KONEC" |
||||
|
|
||||
|
# 3. Vykreslování |
||||
|
okno.fill(MODRA_OBLOHA) |
||||
|
|
||||
|
# Vykreslení trubek |
||||
|
for t in trubky: |
||||
|
# Horní trubka |
||||
|
horni_vyska = t["y_stred"] - (mezera_mezi_trubkami // 2) |
||||
|
pygame.draw.rect(okno, ZELENA, (t["x"], 0, trubka_sirka, horni_vyska)) |
||||
|
|
||||
|
# Dolní trubka |
||||
|
dolni_y = t["y_stred"] + (mezera_mezi_trubkami // 2) |
||||
|
pygame.draw.rect(okno, ZELENA, (t["x"], dolni_y, trubka_sirka, VYSKA_OKNA - dolni_y)) |
||||
|
|
||||
|
# Vykreslení ptáka (žlutý čtvereček) |
||||
|
pygame.draw.rect(okno, ZLUTYP_PTAK, (ptak_x, int(ptak_y), ptak_sirka, ptak_vyska)) |
||||
|
|
||||
|
# Texty přes obrazovku podle toho, v jakém stavu hra je |
||||
|
if stav_hry == "START": |
||||
|
zobraz_text("Stiskni MEZERNÍK", font_maly, BILA, SIRKA_OKNA//2, VYSKA_OKNA//2 - 50, zarovnat_stred=True) |
||||
|
zobraz_text("pro začátek létání", font_maly, BILA, SIRKA_OKNA//2, VYSKA_OKNA//2, zarovnat_stred=True) |
||||
|
elif stav_hry == "HRA": |
||||
|
# Skóre nahoře |
||||
|
zobraz_text(str(skore), font_velky, BILA, SIRKA_OKNA//2, 50, zarovnat_stred=True) |
||||
|
elif stav_hry == "KONEC": |
||||
|
# Konec hry - tisk statistik uprostřed |
||||
|
zobraz_text("GAME OVER", font_velky, CERVENA, SIRKA_OKNA//2, VYSKA_OKNA//2 - 50, zarovnat_stred=True) |
||||
|
zobraz_text(f"Skóre: {skore}", font_maly, BILA, SIRKA_OKNA//2, VYSKA_OKNA//2 + 10, zarovnat_stred=True) |
||||
|
zobraz_text("Stiskni MEZERNÍK pro restart", font_maly, CERNA, SIRKA_OKNA//2, VYSKA_OKNA//2 + 50, zarovnat_stred=True) |
||||
|
|
||||
|
pygame.display.flip() # Prohození bufferu na obrazovku |
||||
|
hodiny.tick(FPS) # Udržuje hru na správné rychlosti snímků |
||||
|
|
||||
|
# Takzvaný "Entry point" - zde program skutečně začne vykonávat kód |
||||
|
if __name__ == "__main__": |
||||
|
while True: |
||||
|
hlavni_smycka() |
||||
@ -0,0 +1,138 @@ |
|||||
|
import pygame |
||||
|
import random |
||||
|
import sys |
||||
|
|
||||
|
# Inicializace Pygame |
||||
|
pygame.init() |
||||
|
|
||||
|
# --- Nastavení okna a základních konstant --- |
||||
|
SIRKA_OKNA = 800 |
||||
|
VYSKA_OKNA = 600 |
||||
|
VELIKOST_DILKU = 20 # Velikost jednoho čtverečku hada a jídla |
||||
|
FPS = 15 # Rychlost hry (počet snímků za sekundu) |
||||
|
|
||||
|
# Barvy (R, G, B) |
||||
|
CERNA = (0, 0, 0) |
||||
|
BILA = (255, 255, 255) |
||||
|
ZELENA = (0, 255, 0) |
||||
|
CERVENA = (255, 0, 0) |
||||
|
|
||||
|
# Vytvoření okna |
||||
|
okno = pygame.display.set_mode((SIRKA_OKNA, VYSKA_OKNA)) |
||||
|
pygame.display.set_caption("Klasický Had (Snake)") |
||||
|
|
||||
|
# Hodiny pro řízení rychlosti hry |
||||
|
hodiny = pygame.time.Clock() |
||||
|
font = pygame.font.SysFont("arial", 36) |
||||
|
|
||||
|
def zobraz_text(text, barva, x, y): |
||||
|
"""Pomocná funkce pro vykreslení textu na obrazovku.""" |
||||
|
text_plocha = font.render(text, True, barva) |
||||
|
okno.blit(text_plocha, (x, y)) |
||||
|
|
||||
|
def hlavni_smycka(): |
||||
|
# --- Počáteční stav hry --- |
||||
|
# Had je reprezentován seznamem souřadnic [x, y]. První prvek je hlava. |
||||
|
had_telo = [ |
||||
|
[SIRKA_OKNA // 2, VYSKA_OKNA // 2], |
||||
|
[SIRKA_OKNA // 2 - VELIKOST_DILKU, VYSKA_OKNA // 2], |
||||
|
[SIRKA_OKNA // 2 - 2 * VELIKOST_DILKU, VYSKA_OKNA // 2] |
||||
|
] |
||||
|
|
||||
|
# Směr pohybu (změna x, změna y) |
||||
|
smer_x = VELIKOST_DILKU |
||||
|
smer_y = 0 |
||||
|
|
||||
|
# Jídlo - náhodná pozice zarovnaná na mřížku |
||||
|
jidlo_x = random.randrange(0, SIRKA_OKNA, VELIKOST_DILKU) |
||||
|
jidlo_y = random.randrange(0, VYSKA_OKNA, VELIKOST_DILKU) |
||||
|
|
||||
|
skore = 0 |
||||
|
konec_hry = False |
||||
|
|
||||
|
# --- Hlavní herní smyčka --- |
||||
|
while True: |
||||
|
# 1. Zpracování událostí (klávesnice, křížek) |
||||
|
for udalost in pygame.event.get(): |
||||
|
if udalost.type == pygame.QUIT: |
||||
|
pygame.quit() |
||||
|
sys.exit() |
||||
|
|
||||
|
# Změna směru pomocí šipek |
||||
|
if udalost.type == pygame.KEYDOWN: |
||||
|
# Zabráníme otočení o 180 stupňů (had nemůže couvat do sebe) |
||||
|
if udalost.key == pygame.K_LEFT and smer_x == 0: |
||||
|
smer_x = -VELIKOST_DILKU |
||||
|
smer_y = 0 |
||||
|
elif udalost.key == pygame.K_RIGHT and smer_x == 0: |
||||
|
smer_x = VELIKOST_DILKU |
||||
|
smer_y = 0 |
||||
|
elif udalost.key == pygame.K_UP and smer_y == 0: |
||||
|
smer_x = 0 |
||||
|
smer_y = -VELIKOST_DILKU |
||||
|
elif udalost.key == pygame.K_DOWN and smer_y == 0: |
||||
|
smer_x = 0 |
||||
|
smer_y = VELIKOST_DILKU |
||||
|
|
||||
|
# Pokud je hra u konce, stiskem mezerníku ji restartujeme |
||||
|
if udalost.key == pygame.K_SPACE and konec_hry: |
||||
|
return # Ukončí tuto iteraci smyčky a spustí hru znovu |
||||
|
|
||||
|
if not konec_hry: |
||||
|
# 2. Logika hry (pohyb a kolize) |
||||
|
|
||||
|
# Vypočítáme novou pozici hlavy |
||||
|
nova_hlava_x = had_telo[0][0] + smer_x |
||||
|
nova_hlava_y = had_telo[0][1] + smer_y |
||||
|
|
||||
|
# Přidáme novou hlavu na začátek seznamu |
||||
|
had_telo.insert(0, [nova_hlava_x, nova_hlava_y]) |
||||
|
|
||||
|
# Kontrola kolize s jídlem |
||||
|
if nova_hlava_x == jidlo_x and nova_hlava_y == jidlo_y: |
||||
|
skore += 1 |
||||
|
# Vygenerujeme nové jídlo jinde |
||||
|
jidlo_x = random.randrange(0, SIRKA_OKNA, VELIKOST_DILKU) |
||||
|
jidlo_y = random.randrange(0, VYSKA_OKNA, VELIKOST_DILKU) |
||||
|
# DŮLEŽITÉ: Pokud had sní jídlo, neodmažeme ocas. Tím had povyroste! |
||||
|
else: |
||||
|
# Pokud had jídlo nesnědl, odmažeme ocas, aby délka zůstala stejná |
||||
|
had_telo.pop() |
||||
|
|
||||
|
# Kontrola kolize se stěnami (náraz do okraje okna) |
||||
|
if (nova_hlava_x < 0 or nova_hlava_x >= SIRKA_OKNA or |
||||
|
nova_hlava_y < 0 or nova_hlava_y >= VYSKA_OKNA): |
||||
|
konec_hry = True |
||||
|
|
||||
|
# Kontrola kolize hada se sebou samým |
||||
|
# Pokud nová pozice hlavy je na stejném místě jako jakýkoli jiný dílek těla |
||||
|
for dilek in had_telo[1:]: |
||||
|
if nova_hlava_x == dilek[0] and nova_hlava_y == dilek[1]: |
||||
|
konec_hry = True |
||||
|
|
||||
|
# 3. Vykreslování |
||||
|
okno.fill(CERNA) # Vymažeme obrazovku (černé pozadí) |
||||
|
|
||||
|
# Vykreslíme jídlo jako červený čtverec |
||||
|
pygame.draw.rect(okno, CERVENA, (jidlo_x, jidlo_y, VELIKOST_DILKU, VELIKOST_DILKU)) |
||||
|
|
||||
|
# Vykreslíme tělo hada jako zelené čtverce |
||||
|
for dilek in had_telo: |
||||
|
pygame.draw.rect(okno, ZELENA, (dilek[0], dilek[1], VELIKOST_DILKU, VELIKOST_DILKU)) |
||||
|
|
||||
|
# Zobrazíme skóre |
||||
|
zobraz_text(f"Skóre: {skore}", BILA, 10, 10) |
||||
|
|
||||
|
# Pokud hra skončila, zobrazíme text pro restart |
||||
|
if konec_hry: |
||||
|
zobraz_text("Konec hry! Stiskni MEZERNÍK pro novou hru.", CERVENA, 100, VYSKA_OKNA // 2) |
||||
|
|
||||
|
pygame.display.flip() # Propíšeme změny na obrazovku |
||||
|
|
||||
|
# 4. Časování - čekání, aby hra běžela na zadaný počet FPS |
||||
|
hodiny.tick(FPS) |
||||
|
|
||||
|
# Spouštíme hru v nekonečné smyčce, aby po Game Over a mezerníku začala znovu |
||||
|
if __name__ == "__main__": |
||||
|
while True: |
||||
|
hlavni_smycka() |
||||
@ -0,0 +1,146 @@ |
|||||
|
import pygame |
||||
|
import sys |
||||
|
|
||||
|
pygame.init() |
||||
|
|
||||
|
# --- Nastavení okna --- |
||||
|
SIRKA = 800 |
||||
|
VYSKA = 600 |
||||
|
okno = pygame.display.set_mode((SIRKA, VYSKA)) |
||||
|
pygame.display.set_caption("Pong - Plná Hra") |
||||
|
|
||||
|
# --- Barvy --- |
||||
|
BILA = (255, 255, 255) |
||||
|
CERNA = (0, 0, 0) |
||||
|
ZELENA = (0, 255, 0) |
||||
|
|
||||
|
hodiny = pygame.time.Clock() |
||||
|
font_velky = pygame.font.SysFont("Arial", 50) |
||||
|
font_maly = pygame.font.SysFont("Arial", 30) |
||||
|
|
||||
|
# --- Stavový automat --- |
||||
|
# Hra může být ve 3 různých stavech. Díky tomu víme, jaká pravidla zrovna platí a co kreslit |
||||
|
STAV_MENU = 0 |
||||
|
STAV_HRA = 1 |
||||
|
STAV_KONEC = 2 |
||||
|
stav = STAV_MENU # Na začátku jsme v menu |
||||
|
|
||||
|
# --- Proměnné hráčů (pálek) a míčku --- |
||||
|
palka_sirka = 15 |
||||
|
palka_vyska = 100 |
||||
|
rychlost_palky = 7 |
||||
|
micek_velikost = 15 |
||||
|
|
||||
|
# Funkce pro resetování proměnných na začátek (použije se při nové hře) |
||||
|
def reset_hry(): |
||||
|
# Pomocí klíčového slova 'global' říkáme funkci, aby upravila proměnné venku (celkové proměnné) |
||||
|
global hrac1_y, hrac2_y, skore1, skore2, micek_x, micek_y, micek_rychlost_x, micek_rychlost_y |
||||
|
hrac1_y = VYSKA // 2 - palka_vyska // 2 |
||||
|
hrac2_y = VYSKA // 2 - palka_vyska // 2 |
||||
|
skore1 = 0 |
||||
|
skore2 = 0 |
||||
|
micek_x = SIRKA // 2 - micek_velikost // 2 |
||||
|
micek_y = VYSKA // 2 - micek_velikost // 2 |
||||
|
micek_rychlost_x = 5 |
||||
|
micek_rychlost_y = 5 |
||||
|
|
||||
|
reset_hry() # Zavoláme ihned, abychom pro začátek vůbec měli výchozí hodnoty |
||||
|
|
||||
|
bezime = True |
||||
|
while bezime: |
||||
|
# 1. Zpracování událostí |
||||
|
for udalost in pygame.event.get(): |
||||
|
if udalost.type == pygame.QUIT: |
||||
|
bezime = False |
||||
|
|
||||
|
# Reakce na stisk kláves nezávisle na plynulém pohybu (např. pouhé stisknutí mezerníku) |
||||
|
if udalost.type == pygame.KEYDOWN: |
||||
|
if stav == STAV_MENU and udalost.key == pygame.K_SPACE: |
||||
|
stav = STAV_HRA # Z menu se posuneme rovnou do hry |
||||
|
elif stav == STAV_KONEC and udalost.key == pygame.K_SPACE: |
||||
|
reset_hry() # Z konce hry ji vyresetujeme a jdeme hrát |
||||
|
stav = STAV_HRA |
||||
|
|
||||
|
klavesy = pygame.key.get_pressed() |
||||
|
|
||||
|
# 2. Logika se provádí POUZE tehdy, když zrovna HRAJEME |
||||
|
if stav == STAV_HRA: |
||||
|
# Ovládání hráče 1 vlevo (Klávesy W a S) |
||||
|
if klavesy[pygame.K_w] and hrac1_y > 0: |
||||
|
hrac1_y -= rychlost_palky |
||||
|
if klavesy[pygame.K_s] and hrac1_y < VYSKA - palka_vyska: |
||||
|
hrac1_y += rychlost_palky |
||||
|
|
||||
|
# Ovládání hráče 2 vpravo (Šipky Nahoru a Dolů) |
||||
|
if klavesy[pygame.K_UP] and hrac2_y > 0: |
||||
|
hrac2_y -= rychlost_palky |
||||
|
if klavesy[pygame.K_DOWN] and hrac2_y < VYSKA - palka_vyska: |
||||
|
hrac2_y += rychlost_palky |
||||
|
|
||||
|
# Pohyb míčku (k X a Y se neustále přičítá aktuální rychlost) |
||||
|
micek_x += micek_rychlost_x |
||||
|
micek_y += micek_rychlost_y |
||||
|
|
||||
|
# --- Odraz míčku od horní a dolní stěny okna --- |
||||
|
# Trik: Vynásobením rychlosti číslem -1 se obrátí směr pohybu na opačný! |
||||
|
if micek_y <= 0 or micek_y >= VYSKA - micek_velikost: |
||||
|
micek_rychlost_y *= -1 |
||||
|
|
||||
|
# --- Odraz od pálek hráčů (kolize obdélníků) --- |
||||
|
rect_micek = pygame.Rect(micek_x, micek_y, micek_velikost, micek_velikost) |
||||
|
rect_hrac1 = pygame.Rect(30, hrac1_y, palka_sirka, palka_vyska) |
||||
|
rect_hrac2 = pygame.Rect(SIRKA - 30 - palka_sirka, hrac2_y, palka_sirka, palka_vyska) |
||||
|
|
||||
|
if rect_micek.colliderect(rect_hrac1) or rect_micek.colliderect(rect_hrac2): |
||||
|
micek_rychlost_x *= -1.1 # Po odrazu otočíme směr (do stran) a míček trošku zrychlíme (o 10%) |
||||
|
|
||||
|
# --- Zjištění gólu (míček vyletí z obrazovky ven vpravo nebo vlevo) --- |
||||
|
if micek_x < 0: |
||||
|
skore2 += 1 # Gól pro hráče 2 |
||||
|
micek_x, micek_y = SIRKA // 2, VYSKA // 2 # Reset na střed okna |
||||
|
micek_rychlost_x = 5 # Vrácení pomalejší rychlosti a míření na pravou stranu |
||||
|
elif micek_x > SIRKA: |
||||
|
skore1 += 1 # Gól pro hráče 1 |
||||
|
micek_x, micek_y = SIRKA // 2, VYSKA // 2 # Reset na střed okna |
||||
|
micek_rychlost_x = -5 # Míření na levou stranu |
||||
|
|
||||
|
# --- Podmínka pro vítězství ve hře --- |
||||
|
if skore1 >= 5 or skore2 >= 5: |
||||
|
stav = STAV_KONEC |
||||
|
|
||||
|
# 3. Vykreslování |
||||
|
okno.fill(CERNA) |
||||
|
|
||||
|
# Co přesně kreslíme? Záleží na tom, v jakém jsme stavu! |
||||
|
if stav == STAV_MENU: |
||||
|
nadpis = font_velky.render("PONG", True, BILA) |
||||
|
navod = font_maly.render("Stiskni MEZERNÍK pro start", True, ZELENA) |
||||
|
okno.blit(nadpis, (SIRKA//2 - nadpis.get_width()//2, 200)) |
||||
|
okno.blit(navod, (SIRKA//2 - navod.get_width()//2, 300)) |
||||
|
|
||||
|
elif stav == STAV_HRA: |
||||
|
# Vykreslení půlící čáry uprostřed (aaline znamená anti-aliased, tedy hezky vyhlazená čára) |
||||
|
pygame.draw.aaline(okno, BILA, (SIRKA // 2, 0), (SIRKA // 2, VYSKA)) |
||||
|
|
||||
|
# Vykreslení pálek a míčku z našich Rect obdélníků |
||||
|
pygame.draw.rect(okno, BILA, rect_hrac1) |
||||
|
pygame.draw.rect(okno, BILA, rect_hrac2) |
||||
|
pygame.draw.ellipse(okno, BILA, rect_micek) # ellipse z obdélníku udělá kruh/ovál |
||||
|
|
||||
|
# Skóre nahoře uprostřed |
||||
|
text_skore = font_velky.render(f"{skore1} {skore2}", True, BILA) |
||||
|
okno.blit(text_skore, (SIRKA // 2 - text_skore.get_width() // 2, 20)) |
||||
|
|
||||
|
elif stav == STAV_KONEC: |
||||
|
# Zjištění, kdo vyhrál pomocí tzv. zkráceného if/else (ternárního operátoru) |
||||
|
vitez = "Hráč 1" if skore1 >= 5 else "Hráč 2" |
||||
|
text_vitez = font_velky.render(f"{vitez} vyhrál!", True, ZELENA) |
||||
|
text_restart = font_maly.render("Stiskni MEZERNÍK pro novou hru", True, BILA) |
||||
|
okno.blit(text_vitez, (SIRKA//2 - text_vitez.get_width()//2, 200)) |
||||
|
okno.blit(text_restart, (SIRKA//2 - text_restart.get_width()//2, 300)) |
||||
|
|
||||
|
pygame.display.flip() |
||||
|
hodiny.tick(60) |
||||
|
|
||||
|
pygame.quit() |
||||
|
sys.exit() |
||||
@ -0,0 +1,141 @@ |
|||||
|
import pygame |
||||
|
import sys |
||||
|
import random |
||||
|
|
||||
|
pygame.init() |
||||
|
|
||||
|
SIRKA = 800 |
||||
|
VYSKA = 600 |
||||
|
okno = pygame.display.set_mode((SIRKA, VYSKA)) |
||||
|
pygame.display.set_caption("Skákačka - Plná Hra") |
||||
|
|
||||
|
# --- Barvy --- |
||||
|
BILA = (255, 255, 255) |
||||
|
CERNA = (0, 0, 0) |
||||
|
MODRA = (50, 150, 255) # Obloha |
||||
|
ZELENA = (50, 200, 50) # Země |
||||
|
CERVENA = (255, 0, 0) # Překážky |
||||
|
|
||||
|
hodiny = pygame.time.Clock() |
||||
|
font = pygame.font.SysFont("Arial", 40) |
||||
|
font_maly = pygame.font.SysFont("Arial", 25) |
||||
|
|
||||
|
# --- Stavový automat --- |
||||
|
STAV_MENU = 0 |
||||
|
STAV_HRA = 1 |
||||
|
STAV_KONEC = 2 |
||||
|
stav = STAV_MENU |
||||
|
|
||||
|
# --- Nastavení hráče a fyziky --- |
||||
|
podlaha_y = VYSKA - 50 # Odkud začíná tráva (y souřadnice) |
||||
|
hrac_sirka = 40 |
||||
|
hrac_vyska = 40 |
||||
|
|
||||
|
# Gravitace v počítačové hře znamená, že rychlost pádu se KAZDÝM SNÍMKEM (FPS) zvyšuje! |
||||
|
gravitace = 0.6 |
||||
|
sila_skoku = -12 # Skok funguje jako nastavení nárazové záporné rychlosti (směr vzhůru) |
||||
|
|
||||
|
# --- Funkce pro reset --- |
||||
|
def reset_hry(): |
||||
|
global hrac_x, hrac_y, rychlost_y, na_zemi, prekazky, skore, rychlost_hry |
||||
|
hrac_x = 100 |
||||
|
hrac_y = podlaha_y - hrac_vyska |
||||
|
rychlost_y = 0 |
||||
|
na_zemi = True # Aby mohl hráč vyskočit, musí samozřejmě stát pevně na zemi |
||||
|
|
||||
|
prekazky = [] # Seznam všech aktuálních překážek v obrazovce, začíná prázdný |
||||
|
skore = 0 |
||||
|
rychlost_hry = 6 |
||||
|
|
||||
|
reset_hry() |
||||
|
|
||||
|
# --- Vlastní Časovač (Custom Event) --- |
||||
|
# Tímto si vytvoříme VLASTNÍ UDÁLOST podobnou pygame.QUIT, která se automaticky spustí každých 1500 milisekund (1.5s) |
||||
|
SPAWN_PREKAZKY = pygame.USEREVENT + 1 |
||||
|
pygame.time.set_timer(SPAWN_PREKAZKY, 1500) |
||||
|
|
||||
|
bezime = True |
||||
|
while bezime: |
||||
|
for udalost in pygame.event.get(): |
||||
|
if udalost.type == pygame.QUIT: |
||||
|
bezime = False |
||||
|
|
||||
|
if udalost.type == pygame.KEYDOWN: |
||||
|
if stav == STAV_MENU and udalost.key == pygame.K_SPACE: |
||||
|
stav = STAV_HRA |
||||
|
elif stav == STAV_KONEC and udalost.key == pygame.K_SPACE: |
||||
|
reset_hry() |
||||
|
stav = STAV_HRA |
||||
|
|
||||
|
# Jak se skáče? Jen když se stiskne šipka nahoru A ZÁROVEŇ postava stojí na zemi |
||||
|
elif stav == STAV_HRA and udalost.key == pygame.K_UP and na_zemi: |
||||
|
rychlost_y = sila_skoku # Dáme mu masivní impuls směrem nahoru |
||||
|
na_zemi = False # Už není na zemi, takže nesmí znovu vyskočit (zabráníme double skokům) |
||||
|
|
||||
|
# Zpracování naší vlastní události pro přidání nové překážky |
||||
|
if udalost.type == SPAWN_PREKAZKY and stav == STAV_HRA: |
||||
|
# Přidáme nový pygame.Rect() překážky úplně na pravý konec obrazovky (SIRKA) |
||||
|
prekazky.append(pygame.Rect(SIRKA, podlaha_y - 40, 30, 40)) |
||||
|
rychlost_hry += 0.1 # Postupně celou hru zrychlujeme, čím déle hráč hraje |
||||
|
|
||||
|
if stav == STAV_HRA: |
||||
|
# --- Fyzika postavy --- |
||||
|
rychlost_y += gravitace # Gravitace neustále táhne rychlost do kladných hodnot (směrem dolů) |
||||
|
hrac_y += rychlost_y # Aplikujeme tuto rychlost na aktuální Y pozici hráče |
||||
|
|
||||
|
# Zastavení o podlahu, aby se hráč nepropadl skrz texturu do nekonečna |
||||
|
if hrac_y + hrac_vyska >= podlaha_y: |
||||
|
hrac_y = podlaha_y - hrac_vyska # Srovnáme ho přesně s podlahou |
||||
|
rychlost_y = 0 # Rychlost pádu je najednou nula |
||||
|
na_zemi = True # Zase může skákat |
||||
|
|
||||
|
hrac_rect = pygame.Rect(hrac_x, hrac_y, hrac_sirka, hrac_vyska) |
||||
|
|
||||
|
# --- Překážky --- |
||||
|
# Trik prekazky[:] znamená, že for-cyklus prochází přes KOPII seznamu. |
||||
|
# To nám umožňuje během cyklu prvky ze seznamu (z toho originálního) bezpečně odstraňovat |
||||
|
# bez toho, aby for-cyklus 'přeskočil' další prvky kvůli změně délky seznamu. |
||||
|
for p in prekazky[:]: |
||||
|
p.x -= int(rychlost_hry) # Překážka se hýbe směrem k hráči doleva |
||||
|
|
||||
|
# Pokud překážka narazí přímo do hráče |
||||
|
if p.colliderect(hrac_rect): |
||||
|
stav = STAV_KONEC |
||||
|
|
||||
|
# Pokud překážka zajela celá za levý okraj (x < -30) |
||||
|
if p.x < -30: |
||||
|
prekazky.remove(p) # Můžeme smazat |
||||
|
skore += 1 # Získáme bod za úspěšné přeskočení |
||||
|
|
||||
|
# --- Vykreslování --- |
||||
|
okno.fill(MODRA) # Obloha |
||||
|
# Tráva/podlaha (nakreslí se obdélník od y = podlaha_y až úplně dolů) |
||||
|
pygame.draw.rect(okno, ZELENA, (0, podlaha_y, SIRKA, VYSKA - podlaha_y)) |
||||
|
|
||||
|
if stav == STAV_MENU: |
||||
|
text = font.render("SKÁKAČKA", True, BILA) |
||||
|
start = font_maly.render("Stiskni MEZERNÍK. Skáče se šipkou NAHORU.", True, CERNA) |
||||
|
okno.blit(text, (SIRKA//2 - text.get_width()//2, 200)) |
||||
|
okno.blit(start, (SIRKA//2 - start.get_width()//2, 300)) |
||||
|
|
||||
|
elif stav == STAV_HRA: |
||||
|
pygame.draw.rect(okno, CERNA, hrac_rect) # Nakreslení Hráče |
||||
|
for p in prekazky: |
||||
|
pygame.draw.rect(okno, CERVENA, p) # Nakreslení všech aktuálních překážek |
||||
|
|
||||
|
skore_text = font.render(f"Skóre: {skore}", True, CERNA) |
||||
|
okno.blit(skore_text, (10, 10)) |
||||
|
|
||||
|
elif stav == STAV_KONEC: |
||||
|
text = font.render("KONEC HRY", True, CERVENA) |
||||
|
skore_text = font.render(f"Dosažené skóre: {skore}", True, BILA) |
||||
|
restart = font_maly.render("Stiskni MEZERNÍK pro novou hru", True, CERNA) |
||||
|
okno.blit(text, (SIRKA//2 - text.get_width()//2, 150)) |
||||
|
okno.blit(skore_text, (SIRKA//2 - skore_text.get_width()//2, 220)) |
||||
|
okno.blit(restart, (SIRKA//2 - restart.get_width()//2, 300)) |
||||
|
|
||||
|
pygame.display.flip() |
||||
|
hodiny.tick(60) |
||||
|
|
||||
|
pygame.quit() |
||||
|
sys.exit() |
||||
@ -0,0 +1,154 @@ |
|||||
|
import pygame |
||||
|
import sys |
||||
|
import random |
||||
|
|
||||
|
pygame.init() |
||||
|
|
||||
|
SIRKA = 800 |
||||
|
VYSKA = 600 |
||||
|
okno = pygame.display.set_mode((SIRKA, VYSKA)) |
||||
|
pygame.display.set_caption("Vesmírná střílečka - Plná Hra") |
||||
|
|
||||
|
# --- Barvy --- |
||||
|
CERNA = (0, 0, 0) |
||||
|
ZELENA = (0, 255, 0) # Hráč (naše loď) |
||||
|
CERVENA = (255, 0, 0) # Nepřátelé (meteority) |
||||
|
ZLUCA = (255, 255, 0) # Projektily (Lasery) |
||||
|
BILA = (255, 255, 255) # Text |
||||
|
|
||||
|
hodiny = pygame.time.Clock() |
||||
|
font_velky = pygame.font.SysFont("Arial", 50) |
||||
|
font_maly = pygame.font.SysFont("Arial", 30) |
||||
|
|
||||
|
STAV_MENU = 0 |
||||
|
STAV_HRA = 1 |
||||
|
STAV_KONEC = 2 |
||||
|
stav = STAV_MENU |
||||
|
|
||||
|
hrac_sirka = 40 |
||||
|
hrac_vyska = 40 |
||||
|
rychlost_hrace = 6 |
||||
|
rychlost_projektilu = 10 # Jak rychle letí laser nahoru |
||||
|
|
||||
|
# Vytvoření vlastního časovače pro přidávání nepřátel |
||||
|
SPAWN_NEPRITELE = pygame.USEREVENT + 1 |
||||
|
|
||||
|
# Funkce pro reset a začátek zbrusu nové hry |
||||
|
def reset_hry(): |
||||
|
global hrac_x, hrac_y, projektily, nepratele, skore, rychlost_nepritele, spawn_cas |
||||
|
hrac_x = SIRKA // 2 - hrac_sirka // 2 |
||||
|
hrac_y = VYSKA - 60 |
||||
|
|
||||
|
projektily = [] # Seznam na letící kulky (lasery) |
||||
|
nepratele = [] # Seznam na padající obdélníky |
||||
|
|
||||
|
skore = 0 |
||||
|
rychlost_nepritele = 2.0 |
||||
|
spawn_cas = 1000 # Čas k přidání nového nepřítele v ms (1 sekunda) |
||||
|
# Zapneme náš vytvořený časovač na zvolený interval |
||||
|
pygame.time.set_timer(SPAWN_NEPRITELE, spawn_cas) |
||||
|
|
||||
|
reset_hry() |
||||
|
|
||||
|
bezime = True |
||||
|
while bezime: |
||||
|
for udalost in pygame.event.get(): |
||||
|
if udalost.type == pygame.QUIT: |
||||
|
bezime = False |
||||
|
|
||||
|
if udalost.type == pygame.KEYDOWN: |
||||
|
if stav == STAV_MENU and udalost.key == pygame.K_SPACE: |
||||
|
stav = STAV_HRA |
||||
|
elif stav == STAV_KONEC and udalost.key == pygame.K_SPACE: |
||||
|
reset_hry() |
||||
|
stav = STAV_HRA |
||||
|
elif stav == STAV_HRA and udalost.key == pygame.K_SPACE: |
||||
|
# --- Výstřel --- |
||||
|
# Když stiskneme mezerník, spočítáme střed hráče a vystřelíme nahoru |
||||
|
projektil_x = hrac_x + hrac_sirka // 2 - 5 |
||||
|
# Přidáme nový obdélník laseru do seznamu kulek |
||||
|
projektily.append(pygame.Rect(projektil_x, hrac_y, 10, 20)) |
||||
|
|
||||
|
# Když vyprší náš nastavený časovač SPAWN_NEPRITELE (tzn. uběhla sekunda) |
||||
|
if udalost.type == SPAWN_NEPRITELE and stav == STAV_HRA: |
||||
|
# Vygenerujeme nepřítele na náhodné X souřadnici, hned nad okrajem obrazovky (-40) |
||||
|
n_x = random.randint(0, SIRKA - 40) |
||||
|
nepratele.append(pygame.Rect(n_x, -40, 40, 40)) |
||||
|
|
||||
|
# Postupné zrychlování hry (těžší obtížnost s ubíhajícím časem) |
||||
|
rychlost_nepritele += 0.05 |
||||
|
if spawn_cas > 300: # Ochrana: Nechceme aby se spawnovali nesmyslně rychle (limit) |
||||
|
spawn_cas -= 20 # Zkrátíme čas mezi nepřáteli |
||||
|
pygame.time.set_timer(SPAWN_NEPRITELE, spawn_cas) |
||||
|
|
||||
|
if stav == STAV_HRA: |
||||
|
# --- Plynulý Pohyb Hráče --- |
||||
|
klavesy = pygame.key.get_pressed() |
||||
|
if klavesy[pygame.K_LEFT] and hrac_x > 0: |
||||
|
hrac_x -= rychlost_hrace |
||||
|
if klavesy[pygame.K_RIGHT] and hrac_x < SIRKA - hrac_sirka: |
||||
|
hrac_x += rychlost_hrace |
||||
|
|
||||
|
# --- Pohyb všech vystřelených projektilů --- |
||||
|
# Používáme [:] pro KOPII seznamu, abychom z originálu mohli během cyklu mazat bez chyb |
||||
|
for p in projektily[:]: |
||||
|
p.y -= rychlost_projektilu # Kulky letí nahoru, y se zmenšuje |
||||
|
|
||||
|
# Pokud kulka vyletí nahoře z obrazovky, vymažeme ji, aby nezabírala paměť RAM |
||||
|
if p.y < 0: projektily.remove(p) |
||||
|
|
||||
|
# --- Pohyb nepřátel a kontrola kolizí --- |
||||
|
hrac_rect = pygame.Rect(hrac_x, hrac_y, hrac_sirka, hrac_vyska) |
||||
|
|
||||
|
for n in nepratele[:]: |
||||
|
n.y += int(rychlost_nepritele) # Nepřátelé letí dolů, y roste |
||||
|
|
||||
|
# Pokud nepřítel proletí až dolů (ZEMĚ) nebo narazí přímo do HRÁČE = GAME OVER |
||||
|
if n.y > VYSKA or n.colliderect(hrac_rect): |
||||
|
stav = STAV_KONEC |
||||
|
|
||||
|
# --- Zásah nepřítele kulkou (DVOJITÝ CYKLUS - FOR VE FORU) --- |
||||
|
# Kontrolujeme každého nepřítele vůči VŠEM létajícím kulkám |
||||
|
for p in projektily[:]: |
||||
|
if p.colliderect(n): |
||||
|
# Zásah! Odstraníme kulku i nepřítele ze seznamů |
||||
|
# Musíme bezpečně ověřit pomocí 'in', jestli už nebyla kulka/nepřítel vymazán |
||||
|
if p in projektily: projektily.remove(p) |
||||
|
if n in nepratele: nepratele.remove(n) |
||||
|
skore += 10 # Přičteme body za sestřel |
||||
|
|
||||
|
# Slovo 'break' okamžitě ukončí VNTŘNÍ FOR CYKLUS. |
||||
|
# Tento konkrétní nepřítel už byl zničen, nemá smysl zkoumat, jestli ho trefila další kulka. |
||||
|
break |
||||
|
|
||||
|
# --- Vykreslování všeho na monitor --- |
||||
|
okno.fill(CERNA) |
||||
|
|
||||
|
if stav == STAV_MENU: |
||||
|
text = font_velky.render("VESMÍRNÁ STŘÍLEČKA", True, ZLUCA) |
||||
|
start = font_maly.render("Stiskni MEZERNÍK. Střílíš mezerníkem, pohyb šipkami.", True, BILA) |
||||
|
okno.blit(text, (SIRKA//2 - text.get_width()//2, 200)) |
||||
|
okno.blit(start, (SIRKA//2 - start.get_width()//2, 300)) |
||||
|
|
||||
|
elif stav == STAV_HRA: |
||||
|
# Postupně vykreslíme ze seznamů všechny aktuální obdélníčky pomocí pygame.draw.rect() |
||||
|
pygame.draw.rect(okno, ZELENA, hrac_rect) # Hráč |
||||
|
for p in projektily: pygame.draw.rect(okno, ZLUCA, p) # Všechny lasery (Žlutě) |
||||
|
for n in nepratele: pygame.draw.rect(okno, CERVENA, n) # Všichni nepřátelé (Červeně) |
||||
|
|
||||
|
skore_text = font_maly.render(f"Skóre: {skore}", True, BILA) |
||||
|
okno.blit(skore_text, (10, 10)) |
||||
|
|
||||
|
elif stav == STAV_KONEC: |
||||
|
text = font_velky.render("ZEMŘEL JSI!", True, CERVENA) |
||||
|
skore_text = font_velky.render(f"Tvé skóre: {skore}", True, BILA) |
||||
|
restart = font_maly.render("Stiskni MEZERNÍK pro novou hru", True, ZLUCA) |
||||
|
okno.blit(text, (SIRKA//2 - text.get_width()//2, 150)) |
||||
|
okno.blit(skore_text, (SIRKA//2 - skore_text.get_width()//2, 250)) |
||||
|
okno.blit(restart, (SIRKA//2 - restart.get_width()//2, 350)) |
||||
|
|
||||
|
pygame.display.flip() |
||||
|
hodiny.tick(60) |
||||
|
|
||||
|
pygame.quit() |
||||
|
sys.exit() |
||||
@ -0,0 +1,188 @@ |
|||||
|
import pygame |
||||
|
import random |
||||
|
import sys |
||||
|
|
||||
|
pygame.init() |
||||
|
|
||||
|
# --- Konstanty okna a rozvržení mřížky --- |
||||
|
SIRKA_OKNA = 600 |
||||
|
VYSKA_OKNA = 600 |
||||
|
FPS = 30 |
||||
|
|
||||
|
RADKY = 4 |
||||
|
SLOUPCE = 4 |
||||
|
KARTICKA_VELIKOST = 100 |
||||
|
MEZERA = 20 |
||||
|
|
||||
|
# Výpočet celkové šířky a výšky mřížky, abychom ji mohli vycentrovat |
||||
|
Mrizka_sirka = (SLOUPCE * KARTICKA_VELIKOST) + ((SLOUPCE - 1) * MEZERA) |
||||
|
Mrizka_vyska = (RADKY * KARTICKA_VELIKOST) + ((RADKY - 1) * MEZERA) |
||||
|
|
||||
|
# Odskoky zleva a shora pro vykreslování |
||||
|
Odsazeni_x = (SIRKA_OKNA - Mrizka_sirka) // 2 |
||||
|
Odsazeni_y = (VYSKA_OKNA - Mrizka_vyska) // 2 |
||||
|
|
||||
|
# Barvy (R, G, B) |
||||
|
BILA = (255, 255, 255) |
||||
|
SEDA = (150, 150, 150) |
||||
|
TMAVE_MODRA = (20, 20, 80) |
||||
|
ZELENA_TEXT = (50, 255, 50) |
||||
|
|
||||
|
# Potřebujeme 8 barev pro 8 párů = 16 karet |
||||
|
BARVY_PARU = [ |
||||
|
(255, 0, 0), # Červená |
||||
|
(0, 255, 0), # Světle Zelená |
||||
|
(0, 0, 255), # Modrá |
||||
|
(255, 255, 0), # Žlutá |
||||
|
(255, 0, 255), # Fialová |
||||
|
(0, 255, 255), # Azurová |
||||
|
(255, 165, 0), # Oranžová |
||||
|
(139, 69, 19) # Hnědá |
||||
|
] |
||||
|
|
||||
|
okno = pygame.display.set_mode((SIRKA_OKNA, VYSKA_OKNA)) |
||||
|
pygame.display.set_caption("Pexeso (Hledání barevných párů)") |
||||
|
hodiny = pygame.time.Clock() |
||||
|
font = pygame.font.SysFont("arial", 40, bold=True) |
||||
|
font_maly = pygame.font.SysFont("arial", 20) |
||||
|
|
||||
|
# --- Třída objektu - objektově orientované programování (OOP) --- |
||||
|
# Použití objektu pro "Kartičku" nám velmi zjednoduší udržování informace |
||||
|
# o tom, jaká barva na kartičce je, a jestli je otočená nebo zakrytá. |
||||
|
class Karticka: |
||||
|
def __init__(self, radek, sloupec, barva_vnitrku): |
||||
|
self.barva = barva_vnitrku |
||||
|
|
||||
|
# Stavy kartičky (boolean) |
||||
|
self.odkryta = False # Zda ji hráč právě otočil |
||||
|
self.nalezena = False # Zda už hráč našel její pár (tím ji vyřadil) |
||||
|
|
||||
|
# Výpočet její pevné x,y souřadnice na obrazovce podle toho v jakém je sloupci a řádku |
||||
|
self.x = Odsazeni_x + sloupec * (KARTICKA_VELIKOST + MEZERA) |
||||
|
self.y = Odsazeni_y + radek * (KARTICKA_VELIKOST + MEZERA) |
||||
|
|
||||
|
# Uložíme si Rect pro zjišťování kolize s myší |
||||
|
self.rect = pygame.Rect(self.x, self.y, KARTICKA_VELIKOST, KARTICKA_VELIKOST) |
||||
|
|
||||
|
def vykresli(self): |
||||
|
# Pokud je karta lícem nahoru (odkrytá nebo už nalezena), kreslíme její skrytou barvu |
||||
|
if self.odkryta or self.nalezena: |
||||
|
pygame.draw.rect(okno, self.barva, self.rect) |
||||
|
else: |
||||
|
# Rub karty - šedivá barva |
||||
|
pygame.draw.rect(okno, SEDA, self.rect) |
||||
|
|
||||
|
# Obrys kolem kartičky pro lepší vzhled |
||||
|
pygame.draw.rect(okno, BILA, self.rect, 3) |
||||
|
|
||||
|
def hlavni_smycka(): |
||||
|
# 1. Příprava seznamu barev |
||||
|
# Seznam BARVY_PARU znásobíme 2, abychom od každé barvy měli dvě (pár) |
||||
|
barvy_do_hry = BARVY_PARU * 2 |
||||
|
random.shuffle(barvy_do_hry) # Náhodně zamícháme pořadí |
||||
|
|
||||
|
# 2. Vytvoření mřížky kartiček (2D pole) |
||||
|
# Vznikne struktura 'seznam v seznamu', ke kartě se přistoupí pomocí karticky[radek][sloupec] |
||||
|
karticky = [] |
||||
|
index_barvy = 0 |
||||
|
for radek in range(RADKY): |
||||
|
rada = [] |
||||
|
for sloupec in range(SLOUPCE): |
||||
|
karta = Karticka(radek, sloupec, barvy_do_hry[index_barvy]) |
||||
|
rada.append(karta) |
||||
|
index_barvy += 1 |
||||
|
karticky.append(rada) |
||||
|
|
||||
|
# Proměnné pro pamatování si, na které karty hráč zrovna kliknul |
||||
|
prvni_vybrana = None |
||||
|
druha_vybrana = None |
||||
|
|
||||
|
pocet_pokusu = 0 |
||||
|
nalezeno_paru = 0 |
||||
|
|
||||
|
while True: |
||||
|
# --- Zpracování událostí --- |
||||
|
for udalost in pygame.event.get(): |
||||
|
if udalost.type == pygame.QUIT: |
||||
|
pygame.quit() |
||||
|
sys.exit() |
||||
|
|
||||
|
# Zjišťování KLIKNUTÍ MYŠÍ |
||||
|
if udalost.type == pygame.MOUSEBUTTONDOWN and udalost.button == 1: # button 1 = levé tlačítko |
||||
|
|
||||
|
# Bezpečnostní pojistka - zablokujeme klikání, pokud už máme 2 karty otočené |
||||
|
# a čekáme např. na jejich skrytí v případě, že se neshodují. |
||||
|
if prvni_vybrana is not None and druha_vybrana is not None: |
||||
|
continue |
||||
|
|
||||
|
# Kde přesně je myš? Získáme X a Y obrazovky |
||||
|
mys_x, mys_y = pygame.mouse.get_pos() |
||||
|
|
||||
|
# Projdeme všechny karty a zjistíme, jestli bod myši je v obdélníku karty |
||||
|
for radek in range(RADKY): |
||||
|
for sloupec in range(SLOUPCE): |
||||
|
karta = karticky[radek][sloupec] |
||||
|
|
||||
|
# collidepoint() vrací True, pokud je x,y uvnitř obdélníku karty |
||||
|
if karta.rect.collidepoint(mys_x, mys_y): |
||||
|
# Otočíme kartu, jen když ještě není odkrytá nebo nalezena |
||||
|
if not karta.odkryta and not karta.nalezena: |
||||
|
karta.odkryta = True |
||||
|
|
||||
|
# Je to první vybraná karta v tomto tahu? |
||||
|
if prvni_vybrana is None: |
||||
|
prvni_vybrana = karta |
||||
|
else: |
||||
|
# Je to druhá vybraná karta! Tah je dokončen. |
||||
|
druha_vybrana = karta |
||||
|
pocet_pokusu += 1 |
||||
|
|
||||
|
# --- Vykreslování --- |
||||
|
okno.fill(TMAVE_MODRA) |
||||
|
|
||||
|
# Zavoláme metodu vykresli() pro všechny kartičky v tabulce |
||||
|
for radek in range(RADKY): |
||||
|
for sloupec in range(SLOUPCE): |
||||
|
karticky[radek][sloupec].vykresli() |
||||
|
|
||||
|
# UI s počtem tahů |
||||
|
text_tahy = font_maly.render(f"Počet pokusů: {pocet_pokusu}", True, BILA) |
||||
|
okno.blit(text_tahy, (10, 10)) |
||||
|
|
||||
|
# Zpráva o vítězství |
||||
|
if nalezeno_paru == 8: # Maximum možných párů je polovina počtu karet |
||||
|
text_konec = font.render("Vítězství! Skvělá paměť.", True, ZELENA_TEXT) |
||||
|
rect = text_konec.get_rect(center=(SIRKA_OKNA // 2, VYSKA_OKNA - 30)) |
||||
|
okno.blit(text_konec, rect) |
||||
|
|
||||
|
# Provedeme "vyfocení" na obrazovku ABY BYLA DRUHÁ KARTA VIDĚT PŘED PAUZOU! |
||||
|
pygame.display.flip() |
||||
|
|
||||
|
# --- Logika Pexesa (Vyhodnocení po odkrytí druhé karty) --- |
||||
|
if prvni_vybrana is not None and druha_vybrana is not None: |
||||
|
if prvni_vybrana.barva == druha_vybrana.barva: |
||||
|
# Našli jsme PÁR! |
||||
|
prvni_vybrana.nalezena = True |
||||
|
druha_vybrana.nalezena = True |
||||
|
nalezeno_paru += 1 |
||||
|
else: |
||||
|
# NENAŠLI. Karty se k sobě nehodí. |
||||
|
# Musíme na 1 vteřinu zastavit program, aby si hráč stihl zapamatovat barvy. |
||||
|
# Použijeme pygame.time.wait(), které "zmrazí" program (hráč nemůže klikat atd.). |
||||
|
# Pro takhle jednoduché výukové pexeso je to naprosto v pořádku. |
||||
|
pygame.time.wait(1000) |
||||
|
|
||||
|
# Zase je otočíme rubem vzhůru |
||||
|
prvni_vybrana.odkryta = False |
||||
|
druha_vybrana.odkryta = False |
||||
|
|
||||
|
# Vynulujeme výběr pro další tah, ať hráč může volit další karty |
||||
|
prvni_vybrana = None |
||||
|
druha_vybrana = None |
||||
|
|
||||
|
# Rychlost smyčky |
||||
|
hodiny.tick(FPS) |
||||
|
|
||||
|
if __name__ == "__main__": |
||||
|
# Tady pexeso neběží donekonečna, po vítězství program čeká, dokud jej nezavřeme |
||||
|
hlavni_smycka() |
||||
Loading…
Reference in new issue