pvjc26/final/README.md
2026-05-10 10:44:22 +02:00

322 lines
9.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Arkanoid
Autor: Filip Chochol
Predmet: Programovanie, TUKE FEI, 2026
---
## Popis projektu
Projekt je terminálová hra Arkanoid napísaná v jazyku C s využitím
knižnice ncurses. Hra beží priamo v termináli bez akéhokoľvek
grafického rozhrania. Všetka grafika je tvorená ASCII znakmi
s farebnými atribútmi ktoré poskytuje ncurses.
Hráč ovláda palku, odráža loptu a ničí tehly usporiadané do špirálového
vzoru. Hra obsahuje tri levely s rastúcou rýchlosťou, systém power-upov,
bossa s vlastnou logikou správania a automatické ukladanie skóre
do textového súboru po každom skončení hry.
---
## Preklad a spustenie
make
./game
Vymazanie skompilovaných súborov:
make clean
Hra sa prekladá kompilátorom gcc s prepínačmi -Wall -Wextra -g
a linkuje sa s knižnicami ncurses (-lncurses) a matematickou
knižnicou (-lm).
---
## Architektura projektu
Projekt je rozdelený do troch logických vrstiev:
main.c vstupný bod, odovzdá riadenie knižnici world
world.c/h engine event loop, vykreslovanie, vstup
game.c/h herná logika všetky herné pravidlá a stav
Táto separácia zabezpečuje že herná logika je úplne nezávislá
od konkrétnej implementácie vykreslovania. Keby sa zmenila
knižnica world, game.c by ostalo nedotknuté.
---
## Datove struktury
Celý stav hry je uložený v jednej štruktúre Hra ktorá sa
alokuje dynamicky pri štarte a uvoľňuje pri ukončení.
### Hra hlavna struktura
typedef struct {
Palka palka;
Lopta lopty[MAX_LOPT];
int pocet_lopt;
Tehla tehly[MAX_RIADKOV][MAX_STLPCOV];
int zivoty;
int skore;
int zostatok_tehiel;
int level;
float rychlost;
StavHry stav;
int sirka, vyska;
char meno[32];
PowerUp powerupy[2];
int hit_counter;
int sirka_timer;
int cas_tikov;
int special_dostupny;
Boss boss;
} Hra;
### Tehla
typedef struct {
int ziva;
int farba;
char znak;
} Tehla;
Tehly sú uložené v dvojrozmernom poli tehly[MAX_RIADKOV][MAX_STLPCOV]
teda 7x10 pozícií. Nie všetky sú obsadené rozloženie určuje
statické pole spirala[7][10] kde 1 znamená tehla existuje, 0 prázdne.
Atribút ziva slúži na označenie zničených tehiel bez nutnosti
preusporiadavať pole.
### Lopta
typedef struct {
float x, y;
float dx, dy;
int ziva;
} Lopta;
Pozícia a smer sú float aby pohyb bol plynulý a uhly presné.
Hra podporuje až MAX_LOPT = 16 lôpt súčasne v jednom statickom poli.
Pridávanie lôpt prechádza pole a hľadá prvý slot kde ziva == 0.
### Palka
typedef struct {
int x, y;
int sirka;
} Palka;
### PowerUp
typedef struct {
int ziva;
float x, y;
char znak;
short farba;
} PowerUp;
### Boss
typedef struct {
int ziva;
float x, y;
float dx;
int pada;
} Boss;
### StavHry stavovy automat
Hra funguje ako stavový automat s týmito stavmi:
STAV_UVOD úvodná obrazovka, zadávanie mena
STAV_CAKA lopta čaká na palke pred štartom
STAV_HRAJE hra beží
STAV_KONIEC hráč prehral
STAV_VYHRAL hráč vyhral všetky 3 levely
STAV_DALSI_LEVEL level dokončený, čaká na pokračovanie
Každý stav určuje čo sa vykresluje a aké udalosti sa spracúvajú.
---
## Herna logika
### Event loop
Knižnica world.c beží v nekonečnej slučke. Pri každom tiku
(každých RYCHLOST_HRY = 120 ms) zavolá funkciu game_event()
s informáciou o stlačenom klávesu alebo uplynutom čase.
game_event() spracuje vstup, zavolá pohni_lopty() a vykresli_hru().
### Fyzika lopty
Každý tick sa pre každú živú loptu zavolá pohni_jednu_loptu():
1. Vypočíta sa nová pozícia:
nx = lopta.x + lopta.dx
ny = lopta.y + lopta.dy
2. Kontrola narazu na steny ak lopta dosiahne okraj,
príslušná zložka smeru sa neguje:
ak nx <= lavy_okraj -> dx = +|dx|
ak nx >= pravy_okraj -> dx = -|dx|
ak ny <= horny_okraj -> dy = +|dy|
3. Kontrola odrazu od palky ak lopta dosiahne riadok palky
a je v jej horizontálnom rozsahu:
offset = (nx - stred_palky) / (sirka_palky / 2)
dx = offset * rychlost
Čím ďalej od stredu, tým väčší horizontálny smer.
dy sa vždy nastaví na -rychlost (lopta ide hore).
4. Kontrola kolízie s tehlami porovnanie pozície lopty
s pozíciou každej živej tehly. Pri zhode sa tehla označí
ziva = 0, skóre sa zvýši a dy sa neguje (odraz).
5. Ak ny >= dolna_hranica (pod palkou) lopta zomrie,
pocet_lopt sa zníži.
### Pohyb palky
Palka sa pohybuje o 2 znaky na každé stlačenie klávesi.
Pri pohybe myšou sa x palky nastaví priamo na pozíciu kurzora
mínus polovica šírky palky, čo dáva plynulé sledovanie myši.
Pohyb je ohraničený na lavy_okraj až pravy_okraj sirka_palky.
### Boss logika
Boss sa objaví po BOSS_CAS = 240 tikoch od začiatku levelu.
Fáza 1 horizontálny pohyb:
boss.x += boss.dx
pri náraze na okraj sa dx neguje
Fáza 2 pád (keď cas_tikov >= BOSS_CAS):
boss.pada = 1
boss.y += 0.15 každý tick
ak boss trafí tehlu tehla zomrie, skore -= 50
ak boss.y >= palka.y okamžite STAV_KONIEC
Zásah bossa loptou:
boss.ziva = 0, skore += 200
vystrelí 5 lôpt rôznymi smermi (vystrel_z_bossa)
### Power-upy
hit_counter počíta každú zničenú tehlu.
hit_counter % 3 == 0 -> power-up $ (extra lopty)
hit_counter % 12 == 0 -> power-up W (siroka palka)
Power-upy padajú dolu (y += 0.5 každý tick).
Pri chytení palkou sa aktivuje efekt:
$ pridajú sa 2 nové lopty s mierne odchýleným smerom
W palka.sirka = PALKA_SIRKA_MAX, sirka_timer = 300 tickov
po 300 tickoch sa palka vráti na PALKA_SIRKA_MIN
### Specialny vystrel
Stlačením E sa vypália 2 lopty pod uhlom od stredu palky.
Dostupnosť sa sleduje premennou special_dostupny (1/0).
Po použití sa nastaví na 0 a už sa nedá obnoviť.
### Skore
Za každú zničenú tehlu: 10 * cislo_levelu bodov.
Za zničenie bossa: +200 bodov.
Za tehlu zničenú bossom: -50 bodov.
### Ukladanie skore
Po každom skončení hry (STAV_KONIEC aj STAV_VYHRAL) sa zavolá
funkcia uloz_skore() ktorá otvorí scores.txt v append móde ("a")
a pripíše formátovaný záznam s týmito údajmi:
- meno hráča
- dosiahnuté skóre
- level na ktorom hra skončila
- čas od začiatku levelu (prepočítaný z cas_tikov)
- výsledok (VYHRAL / GAME OVER)
- dátum a čas (zo systémovej funkcie localtime)
Súbor sa nevymazáva každá hra sa pripíše na koniec
takže ostáva kompletná história všetkých hier.
---
## Vykreslovanie
Celá hra sa vykresluje funkciou vykresli_hru() ktorá sa volá
po každej udalosti. Funkcia najprv vymaže obrazovku (clear_screen)
a potom podľa aktuálneho stavu hry vykreslí príslušné prvky.
Súradnicový systém: [0,0] je ľavý horný roh obrazovky.
X rastie doprava, Y rastie smerom nadol.
Hracia plocha má dva rámčeky:
vonkajší ohraničuje celú obrazovku (žltý)
vnútorný ohraničuje hernú plochu (biely)
Rozmery hracej plochy sa počítajú dynamicky podľa aktuálnej
veľkosti terminálu (h->sirka, h->vyska) čo zabezpečuje
že hra funguje správne aj pri zmene veľkosti okna.
Pozície tehiel:
tx = tehla_zacatek_x + stlpec * 3
ty = tehla_zac_y + riadok
Každá tehla zaberá 3 znaky: [X] kde X je znak z mena hráča.
---
## Ovládanie
| Kláves | Akcia |
|----------------------|------------------------------|
| A / sipka vlavo | Pohyb palky vlavo |
| D / sipka vpravo | Pohyb palky vpravo |
| Pohyb mysou | Palka sleduje kurzor |
| Medzernik | Spustenie lopty |
| Lavy klik mysou | Spustenie lopty |
| E | Specialny vystrel |
| Q | Ukoncenie hry |
---
## Bodovanie
| Udalost | Body |
|--------------------------|-------|
| Znicenie tehly level 1 | +10 |
| Znicenie tehly level 2 | +20 |
| Znicenie tehly level 3 | +30 |
| Znicenie bossa | +200 |
| Boss znici tehlu | -50 |
---
## Levely
| Level | Rychlost lopty | Body za tehlu |
|-------|----------------|---------------|
| 1 | 0.7 | 10 |
| 2 | 0.9 | 20 |
| 3 | 1.1 | 30 |
---
## Subory projektu
| Subor | Obsah |
|------------|------------------------------------------------|
| main.c | Vstupny bod, spusta hernu slucku cez world |
| game.c | Cela herna logika pohyb, kolizie, kreslenie |
| game.h | Struktury, konstanty, deklaracie funkcii |
| world.c | Kniźnica pre vykreslovanie v terminali |
| world.h | Rozhranie kniźnice world |
| Makefile | Preklad projektu prikazom make |
| README.md | Tato dokumentacia |
| scores.txt | Ukladanie skore (vytvori sa automaticky) |
---