322 lines
9.3 KiB
Markdown
322 lines
9.3 KiB
Markdown
# 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) |
|
||
|
||
---
|