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