final
This commit is contained in:
parent
8d0f3c5047
commit
700d025fe4
24
final/Makefile
Normal file
24
final/Makefile
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
CC = gcc
|
||||||
|
CFLAGS = -Wall -Wextra -g
|
||||||
|
LIBS = -lncurses -lm
|
||||||
|
|
||||||
|
TARGET = game
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
$(TARGET): main.o game.o world.o
|
||||||
|
$(CC) $(CFLAGS) -o $(TARGET) main.o game.o world.o $(LIBS)
|
||||||
|
|
||||||
|
main.o: main.c
|
||||||
|
$(CC) $(CFLAGS) -c -o main.o main.c
|
||||||
|
|
||||||
|
game.o: game.c
|
||||||
|
$(CC) $(CFLAGS) -c -o game.o game.c
|
||||||
|
|
||||||
|
world.o: world.c
|
||||||
|
$(CC) $(CFLAGS) -c -o world.o world.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f main.o game.o world.o $(TARGET)
|
||||||
|
|
||||||
|
.PHONY: all clean
|
||||||
321
final/README.md
Normal file
321
final/README.md
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
# 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) |
|
||||||
|
|
||||||
|
---
|
||||||
814
final/game.c
Normal file
814
final/game.c
Normal file
@ -0,0 +1,814 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include "game.h"
|
||||||
|
#include "world.h"
|
||||||
|
|
||||||
|
static short farby_riadkov_level1[7] = {
|
||||||
|
COLOR_RED, COLOR_MAGENTA, COLOR_YELLOW,
|
||||||
|
COLOR_GREEN, COLOR_CYAN, COLOR_BLUE, COLOR_WHITE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static short farby_riadkov_level2[7] = {
|
||||||
|
COLOR_CYAN, COLOR_GREEN, COLOR_WHITE,
|
||||||
|
COLOR_YELLOW, COLOR_RED, COLOR_MAGENTA, COLOR_BLUE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static short farby_riadkov_level3[7] = {
|
||||||
|
COLOR_YELLOW, COLOR_WHITE, COLOR_RED,
|
||||||
|
COLOR_CYAN, COLOR_MAGENTA, COLOR_GREEN, COLOR_BLUE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int von_lav(Hra* h) { (void)h; return 0; }
|
||||||
|
static int von_prav(Hra* h) { return h->sirka - 1; }
|
||||||
|
static int von_hor(Hra* h) { (void)h; return 0; }
|
||||||
|
static int von_dno(Hra* h) { return h->vyska - 2; }
|
||||||
|
|
||||||
|
static int lavy_okraj(Hra* h) { return h->sirka / 4; }
|
||||||
|
static int pravy_okraj(Hra* h) { return h->sirka - h->sirka / 4; }
|
||||||
|
static int horny_okraj(Hra* h) { (void)h; return 3; }
|
||||||
|
static int dolna_hranica(Hra* h) { return h->palka.y + 1; }
|
||||||
|
|
||||||
|
static int tehla_zacatek_x(Hra* h) {
|
||||||
|
return (h->sirka - MAX_STLPCOV * 3) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tehla_zac_y(Hra* h) {
|
||||||
|
return horny_okraj(h) + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int palka_default_y(Hra* h) {
|
||||||
|
return tehla_zac_y(h) + MAX_RIADKOV + 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void inicializuj_boss(Hra* h) {
|
||||||
|
h->boss.ziva = 1;
|
||||||
|
h->boss.x = (float)(h->sirka / 2);
|
||||||
|
h->boss.y = 1.0f;
|
||||||
|
h->boss.dx = 0.5f;
|
||||||
|
h->boss.pada = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void inicializuj_tehly(Hra* h) {
|
||||||
|
h->zostatok_tehiel = 0;
|
||||||
|
int dlzka = h->meno_dlzka > 0 ? h->meno_dlzka : 4;
|
||||||
|
|
||||||
|
static const int spirala[7][10] = {
|
||||||
|
{1,1,1,1,1,1,1,1,1,1},
|
||||||
|
{1,0,0,0,0,0,0,0,0,1},
|
||||||
|
{1,0,1,1,1,1,1,1,0,1},
|
||||||
|
{1,0,1,0,0,0,0,1,0,0},
|
||||||
|
{1,0,1,0,1,1,0,1,0,1},
|
||||||
|
{1,0,1,0,1,0,0,1,0,1},
|
||||||
|
{1,0,0,0,1,1,1,1,0,1},
|
||||||
|
};
|
||||||
|
|
||||||
|
short* farby;
|
||||||
|
switch (h->level) {
|
||||||
|
case 2: farby = farby_riadkov_level2; break;
|
||||||
|
case 3: farby = farby_riadkov_level3; break;
|
||||||
|
default: farby = farby_riadkov_level1; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int r = 0; r < MAX_RIADKOV; r++) {
|
||||||
|
for (int s = 0; s < MAX_STLPCOV; s++) {
|
||||||
|
if (spirala[r][s]) {
|
||||||
|
h->tehly[r][s].ziva = 1;
|
||||||
|
h->tehly[r][s].farba = farby[r % 7];
|
||||||
|
h->tehly[r][s].znak = h->meno[(r + s) % dlzka];
|
||||||
|
h->zostatok_tehiel++;
|
||||||
|
} else {
|
||||||
|
h->tehly[r][s].ziva = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nastav_level(Hra* h) {
|
||||||
|
switch (h->level) {
|
||||||
|
case 1: h->riadkov = 7; h->rychlost = 0.7f; break;
|
||||||
|
case 2: h->riadkov = 7; h->rychlost = 0.9f; break;
|
||||||
|
case 3: h->riadkov = 7; h->rychlost = 1.1f; break;
|
||||||
|
default: h->riadkov = 7; h->rychlost = 0.7f; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pridaj_loptu(Hra* h, float x, float y, float dx, float dy) {
|
||||||
|
for (int i = 0; i < MAX_LOPT; i++) {
|
||||||
|
if (!h->lopty[i].ziva) {
|
||||||
|
h->lopty[i].x = x;
|
||||||
|
h->lopty[i].y = y;
|
||||||
|
h->lopty[i].dx = dx;
|
||||||
|
h->lopty[i].dy = dy;
|
||||||
|
h->lopty[i].ziva = 1;
|
||||||
|
h->pocet_lopt++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void inicializuj_lopty(Hra* h) {
|
||||||
|
for (int i = 0; i < MAX_LOPT; i++) h->lopty[i].ziva = 0;
|
||||||
|
h->pocet_lopt = 0;
|
||||||
|
pridaj_loptu(h,
|
||||||
|
(float)(h->palka.x + h->palka.sirka / 2),
|
||||||
|
(float)(h->palka.y - 1),
|
||||||
|
h->rychlost, -h->rychlost);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vystrel_z_bossa(Hra* h, float bstred, float bposy) {
|
||||||
|
float smery[5][2] = {
|
||||||
|
{ 0.0f, h->rychlost },
|
||||||
|
{-h->rychlost, h->rychlost },
|
||||||
|
{ h->rychlost, h->rychlost },
|
||||||
|
{-h->rychlost * 0.7f, -h->rychlost * 0.7f },
|
||||||
|
{ h->rychlost * 0.7f, -h->rychlost * 0.7f },
|
||||||
|
};
|
||||||
|
for (int s = 0; s < 5; s++) {
|
||||||
|
if (h->pocet_lopt < MAX_LOPT)
|
||||||
|
pridaj_loptu(h, bstred, bposy, smery[s][0], smery[s][1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pohni_palku(Hra* h, int smer) {
|
||||||
|
int novy_x = h->palka.x + smer * 2;
|
||||||
|
int lav = lavy_okraj(h);
|
||||||
|
int prav = pravy_okraj(h) - h->palka.sirka + 1;
|
||||||
|
if (novy_x < lav) novy_x = lav;
|
||||||
|
if (novy_x > prav) novy_x = prav;
|
||||||
|
h->palka.x = novy_x;
|
||||||
|
if (h->stav == STAV_CAKA)
|
||||||
|
h->lopty[0].x = (float)(h->palka.x + h->palka.sirka / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vystrel_special(Hra* h) {
|
||||||
|
if (!h->special_dostupny) return;
|
||||||
|
if (h->stav != STAV_HRAJE) return;
|
||||||
|
h->special_dostupny = 0;
|
||||||
|
|
||||||
|
float stred = (float)(h->palka.x + h->palka.sirka / 2);
|
||||||
|
float y = (float)(h->palka.y - 1);
|
||||||
|
|
||||||
|
if (h->pocet_lopt < MAX_LOPT)
|
||||||
|
pridaj_loptu(h, stred - 1, y, -h->rychlost * 0.5f, -h->rychlost);
|
||||||
|
if (h->pocet_lopt < MAX_LOPT)
|
||||||
|
pridaj_loptu(h, stred + 1, y, h->rychlost * 0.5f, -h->rychlost);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uloz_skore(Hra* h) {
|
||||||
|
FILE* f = fopen("scores.txt", "a");
|
||||||
|
if (!f) return;
|
||||||
|
|
||||||
|
time_t t = time(NULL);
|
||||||
|
struct tm* tm_info = localtime(&t);
|
||||||
|
char datum[32];
|
||||||
|
strftime(datum, sizeof(datum), "%d.%m.%Y %H:%M:%S", tm_info);
|
||||||
|
|
||||||
|
int sekundy = h->cas_tikov * RYCHLOST_HRY / 1000;
|
||||||
|
int min = sekundy / 60;
|
||||||
|
int sek = sekundy % 60;
|
||||||
|
|
||||||
|
const char* vysledok;
|
||||||
|
if (h->stav == STAV_VYHRAL) vysledok = "VYHRAL";
|
||||||
|
else if (h->stav == STAV_KONIEC) vysledok = "GAME OVER";
|
||||||
|
else vysledok = "KONIEC";
|
||||||
|
|
||||||
|
fprintf(f, "+-------------------------------------------------+\n");
|
||||||
|
fprintf(f, "| Hrac : %-36s|\n", h->meno);
|
||||||
|
fprintf(f, "| Skore : %-36d|\n", h->skore);
|
||||||
|
fprintf(f, "| Level : %-36d|\n", h->level);
|
||||||
|
fprintf(f, "| Cas : %02d:%02d%-32s|\n", min, sek, "");
|
||||||
|
fprintf(f, "| Vysledok: %-36s|\n", vysledok);
|
||||||
|
fprintf(f, "| Datum : %-36s|\n", datum);
|
||||||
|
fprintf(f, "+-------------------------------------------------+\n\n");
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pohni_boss(Hra* h) {
|
||||||
|
if (!h->boss.ziva) return;
|
||||||
|
|
||||||
|
if (h->cas_tikov >= BOSS_CAS && !h->boss.pada) {
|
||||||
|
h->boss.pada = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h->boss.pada) {
|
||||||
|
h->boss.y += 0.15f;
|
||||||
|
|
||||||
|
int tx0 = tehla_zacatek_x(h);
|
||||||
|
int ty0 = tehla_zac_y(h);
|
||||||
|
int by = (int)h->boss.y;
|
||||||
|
int bx = (int)h->boss.x;
|
||||||
|
|
||||||
|
for (int r = 0; r < MAX_RIADKOV; r++) {
|
||||||
|
for (int s = 0; s < MAX_STLPCOV; s++) {
|
||||||
|
if (!h->tehly[r][s].ziva) continue;
|
||||||
|
int tx = tx0 + s * 3;
|
||||||
|
int ty = ty0 + r;
|
||||||
|
if (by == ty && bx + 4 >= tx && bx <= tx + 2) {
|
||||||
|
h->tehly[r][s].ziva = 0;
|
||||||
|
h->zostatok_tehiel--;
|
||||||
|
h->skore -= 50;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((int)h->boss.y >= h->palka.y) {
|
||||||
|
h->stav = STAV_KONIEC;
|
||||||
|
uloz_skore(h);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
h->boss.x += h->boss.dx;
|
||||||
|
if (h->boss.x <= (float)lavy_okraj(h)) {
|
||||||
|
h->boss.x = (float)lavy_okraj(h);
|
||||||
|
h->boss.dx = fabsf(h->boss.dx);
|
||||||
|
}
|
||||||
|
if (h->boss.x + 4 >= (float)pravy_okraj(h)) {
|
||||||
|
h->boss.x = (float)(pravy_okraj(h) - 4);
|
||||||
|
h->boss.dx = -fabsf(h->boss.dx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_LOPT; i++) {
|
||||||
|
if (!h->lopty[i].ziva) continue;
|
||||||
|
int bx = (int)h->boss.x;
|
||||||
|
int by = (int)h->boss.y;
|
||||||
|
int lx = (int)h->lopty[i].x;
|
||||||
|
int ly = (int)h->lopty[i].y;
|
||||||
|
if (ly == by && lx >= bx && lx <= bx + 4) {
|
||||||
|
h->boss.ziva = 0;
|
||||||
|
h->skore += 200;
|
||||||
|
h->lopty[i].dy = fabsf(h->lopty[i].dy);
|
||||||
|
vystrel_z_bossa(h, h->boss.x + 2.0f, h->boss.y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pohni_powerupy(Hra* h) {
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
if (!h->powerupy[i].ziva) continue;
|
||||||
|
|
||||||
|
h->powerupy[i].y += 0.5f;
|
||||||
|
|
||||||
|
if ((int)h->powerupy[i].y >= h->palka.y &&
|
||||||
|
(int)h->powerupy[i].x >= h->palka.x &&
|
||||||
|
(int)h->powerupy[i].x < h->palka.x + h->palka.sirka) {
|
||||||
|
h->powerupy[i].ziva = 0;
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
int idx = h->posledna_lopta;
|
||||||
|
if (h->lopty[idx].ziva) {
|
||||||
|
if (h->pocet_lopt < MAX_LOPT)
|
||||||
|
pridaj_loptu(h, h->lopty[idx].x, h->lopty[idx].y,
|
||||||
|
-h->lopty[idx].dx + 0.2f, -fabsf(h->lopty[idx].dy));
|
||||||
|
if (h->pocet_lopt < MAX_LOPT)
|
||||||
|
pridaj_loptu(h, h->lopty[idx].x, h->lopty[idx].y,
|
||||||
|
h->lopty[idx].dx - 0.2f, -fabsf(h->lopty[idx].dy));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
h->palka.sirka = PALKA_SIRKA_MAX;
|
||||||
|
h->sirka_timer = 300;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((int)h->powerupy[i].y >= dolna_hranica(h))
|
||||||
|
h->powerupy[i].ziva = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pohni_jednu_loptu(Hra* h, int idx) {
|
||||||
|
Lopta* l = &h->lopty[idx];
|
||||||
|
if (!l->ziva) return 0;
|
||||||
|
|
||||||
|
float nx = l->x + l->dx;
|
||||||
|
float ny = l->y + l->dy;
|
||||||
|
|
||||||
|
int lav = lavy_okraj(h);
|
||||||
|
int prav = pravy_okraj(h);
|
||||||
|
int hor = horny_okraj(h);
|
||||||
|
|
||||||
|
if (nx <= lav) { nx = (float)lav; l->dx = fabsf(l->dx); }
|
||||||
|
if (nx >= prav) { nx = (float)prav; l->dx = -fabsf(l->dx); }
|
||||||
|
if (ny <= hor) { ny = (float)hor; l->dy = fabsf(l->dy); }
|
||||||
|
|
||||||
|
if (h->boss.ziva) {
|
||||||
|
int bx = (int)h->boss.x;
|
||||||
|
int by = (int)h->boss.y;
|
||||||
|
if ((int)ny == by && (int)nx >= bx && (int)nx <= bx + 4) {
|
||||||
|
h->boss.ziva = 0;
|
||||||
|
h->skore += 200;
|
||||||
|
l->dy = fabsf(l->dy);
|
||||||
|
vystrel_z_bossa(h, h->boss.x + 2.0f, h->boss.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int py = h->palka.y;
|
||||||
|
if ((int)ny >= py - 1 && (int)ny <= py) {
|
||||||
|
if ((int)nx >= h->palka.x && (int)nx < h->palka.x + h->palka.sirka) {
|
||||||
|
float stred = (float)(h->palka.x) + h->palka.sirka / 2.0f;
|
||||||
|
float offset = (nx - stred) / (h->palka.sirka / 2.0f);
|
||||||
|
l->dx = offset * h->rychlost;
|
||||||
|
if (l->dx > h->rychlost) l->dx = h->rychlost;
|
||||||
|
if (l->dx < -h->rychlost) l->dx = -h->rychlost;
|
||||||
|
if (l->dx == 0.0f) l->dx = 0.3f;
|
||||||
|
l->dy = -h->rychlost;
|
||||||
|
ny = (float)(py - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int tx0 = tehla_zacatek_x(h);
|
||||||
|
int ty0 = tehla_zac_y(h);
|
||||||
|
|
||||||
|
for (int r = 0; r < MAX_RIADKOV && h->zostatok_tehiel > 0; r++) {
|
||||||
|
for (int s = 0; s < MAX_STLPCOV; s++) {
|
||||||
|
if (!h->tehly[r][s].ziva) continue;
|
||||||
|
int tx = tx0 + s * 3;
|
||||||
|
int ty = ty0 + r;
|
||||||
|
if ((int)ny == ty && (int)nx >= tx && (int)nx < tx + 3) {
|
||||||
|
h->tehly[r][s].ziva = 0;
|
||||||
|
h->zostatok_tehiel--;
|
||||||
|
h->skore += 10 * h->level;
|
||||||
|
l->dy = -l->dy;
|
||||||
|
|
||||||
|
h->posledna_lopta = idx;
|
||||||
|
h->hit_counter++;
|
||||||
|
|
||||||
|
if (h->hit_counter % 3 == 0 && h->hit_counter % 12 != 0 && !h->powerupy[0].ziva) {
|
||||||
|
h->powerupy[0].ziva = 1;
|
||||||
|
h->powerupy[0].x = nx;
|
||||||
|
h->powerupy[0].y = ny;
|
||||||
|
h->powerupy[0].znak = '$';
|
||||||
|
h->powerupy[0].farba = COLOR_YELLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h->hit_counter % 12 == 0 && !h->powerupy[1].ziva) {
|
||||||
|
h->powerupy[1].ziva = 1;
|
||||||
|
h->powerupy[1].x = nx;
|
||||||
|
h->powerupy[1].y = ny;
|
||||||
|
h->powerupy[1].znak = 'W';
|
||||||
|
h->powerupy[1].farba = COLOR_CYAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h->zostatok_tehiel == 0) {
|
||||||
|
h->stav = (h->level < 3) ? STAV_DALSI_LEVEL : STAV_VYHRAL;
|
||||||
|
if (h->stav == STAV_VYHRAL) uloz_skore(h);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((int)ny >= dolna_hranica(h)) {
|
||||||
|
l->ziva = 0;
|
||||||
|
h->pocet_lopt--;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
l->x = nx;
|
||||||
|
l->y = ny;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pohni_lopty(Hra* h) {
|
||||||
|
if (h->stav != STAV_HRAJE) return;
|
||||||
|
|
||||||
|
h->cas_tikov++;
|
||||||
|
|
||||||
|
pohni_boss(h);
|
||||||
|
if (h->stav == STAV_KONIEC) return;
|
||||||
|
|
||||||
|
if (h->sirka_timer > 0) {
|
||||||
|
h->sirka_timer--;
|
||||||
|
if (h->sirka_timer == 0)
|
||||||
|
h->palka.sirka = PALKA_SIRKA_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
pohni_powerupy(h);
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_LOPT; i++) {
|
||||||
|
if (h->lopty[i].ziva) pohni_jednu_loptu(h, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h->pocet_lopt <= 0) {
|
||||||
|
h->zivoty--;
|
||||||
|
if (h->zivoty <= 0) {
|
||||||
|
h->stav = STAV_KONIEC;
|
||||||
|
uloz_skore(h);
|
||||||
|
} else {
|
||||||
|
h->palka.sirka = PALKA_SIRKA_MIN;
|
||||||
|
h->stav = STAV_CAKA;
|
||||||
|
inicializuj_lopty(h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vykresli_uvod(Hra* h) {
|
||||||
|
int sx = h->sirka / 2;
|
||||||
|
int sy = h->vyska / 2 - 12;
|
||||||
|
|
||||||
|
static const char* logo[] = {
|
||||||
|
" _ ____ _ __ _ _ _ ___ ___ ____",
|
||||||
|
" / \\ | _ \\| |/ / / \\ | \\ | |/ _ \\|_ _| _ \\",
|
||||||
|
" / _ \\ | |_) | ' / / _ \\ | \\| | | | || | | | |",
|
||||||
|
" / ___ \\| _ <| . \\ / ___ \\| |\\ | |_| || | |_| |",
|
||||||
|
"/_/ \\_\\_| \\_\\_|\\_\\/_/ \\_\\_| \\_|\\___/|___|____/",
|
||||||
|
};
|
||||||
|
static const short logo_farby[] = {
|
||||||
|
COLOR_RED, COLOR_MAGENTA, COLOR_YELLOW, COLOR_GREEN, COLOR_CYAN,
|
||||||
|
};
|
||||||
|
|
||||||
|
int logo_x = sx - 25;
|
||||||
|
if (logo_x < 0) logo_x = 0;
|
||||||
|
|
||||||
|
for (int r = 0; r < 5; r++) {
|
||||||
|
const char* riadok = logo[r];
|
||||||
|
int dl = (int)strlen(riadok);
|
||||||
|
for (int c = 0; c < dl; c++) {
|
||||||
|
if (logo_x + c < h->sirka)
|
||||||
|
set_color_cell(riadok[c], logo_x + c, sy + r, logo_farby[r], COLOR_BLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int b1y = sy + 6;
|
||||||
|
set_message("* . * . * . * . * . *", sx - 16, b1y);
|
||||||
|
|
||||||
|
int b2y = b1y + 2;
|
||||||
|
set_color_cell('[', sx - 14, b2y, COLOR_YELLOW, COLOR_BLACK);
|
||||||
|
set_message(" Zadaj meno a stlac ENTER ", sx - 13, b2y);
|
||||||
|
set_color_cell(']', sx + 13, b2y, COLOR_YELLOW, COLOR_BLACK);
|
||||||
|
|
||||||
|
int b3y = b2y + 2;
|
||||||
|
char riadok_mena[40];
|
||||||
|
snprintf(riadok_mena, sizeof(riadok_mena), "Meno: %s_", h->meno);
|
||||||
|
int meno_dl = (int)strlen(riadok_mena);
|
||||||
|
int meno_x = sx - meno_dl / 2;
|
||||||
|
set_color_cell('>', meno_x - 1, b3y, COLOR_CYAN, COLOR_BLACK);
|
||||||
|
set_message(riadok_mena, meno_x, b3y);
|
||||||
|
|
||||||
|
int b4y = b3y + 2;
|
||||||
|
static const short uk_farby[] = {
|
||||||
|
COLOR_RED, COLOR_MAGENTA, COLOR_YELLOW,
|
||||||
|
COLOR_GREEN, COLOR_CYAN, COLOR_BLUE, COLOR_WHITE
|
||||||
|
};
|
||||||
|
static const char* uk_znaky[] = {"[R]","[M]","[Y]","[G]","[C]","[B]","[W]"};
|
||||||
|
int uk_x = sx - 10;
|
||||||
|
for (int i = 0; i < 7; i++) {
|
||||||
|
const char* z = uk_znaky[i];
|
||||||
|
for (int c = 0; c < 3; c++)
|
||||||
|
set_color_cell(z[c], uk_x + i*3 + c, b4y, uk_farby[i], COLOR_BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
int lpy = b4y + 2;
|
||||||
|
set_color_cell('O', sx - 12, lpy, COLOR_WHITE, COLOR_BLACK);
|
||||||
|
set_color_cell('o', sx - 8, lpy, COLOR_WHITE, COLOR_BLACK);
|
||||||
|
set_color_cell('.', sx - 5, lpy, COLOR_WHITE, COLOR_BLACK);
|
||||||
|
set_color_cell('.', sx + 5, lpy, COLOR_WHITE, COLOR_BLACK);
|
||||||
|
set_color_cell('o', sx + 8, lpy, COLOR_WHITE, COLOR_BLACK);
|
||||||
|
set_color_cell('O', sx + 12, lpy, COLOR_WHITE, COLOR_BLACK);
|
||||||
|
|
||||||
|
int pky = lpy + 1;
|
||||||
|
set_color_cell('<', sx - 10, pky, COLOR_CYAN, COLOR_BLACK);
|
||||||
|
for (int i = -9; i <= 9; i++)
|
||||||
|
set_color_cell('=', sx + i, pky, COLOR_CYAN, COLOR_BLACK);
|
||||||
|
set_color_cell('>', sx + 10, pky, COLOR_CYAN, COLOR_BLACK);
|
||||||
|
|
||||||
|
set_message("* . * . * . * . * . *", sx - 16, pky + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vykresli_hru(Hra* h) {
|
||||||
|
clear_screen();
|
||||||
|
|
||||||
|
if (h->stav == STAV_UVOD) {
|
||||||
|
vykresli_uvod(h);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h->stav == STAV_DALSI_LEVEL) {
|
||||||
|
int sx = h->sirka / 2;
|
||||||
|
int sy = h->vyska / 2 - 2;
|
||||||
|
char msg[40];
|
||||||
|
snprintf(msg, sizeof(msg), "*** LEVEL %d DOKONCENY! ***", h->level);
|
||||||
|
set_message(msg, sx - 14, sy);
|
||||||
|
snprintf(msg, sizeof(msg), " Skore: %d", h->skore);
|
||||||
|
set_message(msg, sx - 14, sy + 1);
|
||||||
|
set_message(" Stlac MEDZERNIK na dalsi level", sx - 16, sy + 3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vl = von_lav(h), vp = von_prav(h), vh = von_hor(h), vd = von_dno(h);
|
||||||
|
set_color_cell('+', vl, vh, COLOR_YELLOW, COLOR_BLACK);
|
||||||
|
set_color_cell('+', vp, vh, COLOR_YELLOW, COLOR_BLACK);
|
||||||
|
set_color_cell('+', vl, vd, COLOR_YELLOW, COLOR_BLACK);
|
||||||
|
set_color_cell('+', vp, vd, COLOR_YELLOW, COLOR_BLACK);
|
||||||
|
for (int x = vl + 1; x < vp; x++) {
|
||||||
|
set_color_cell('=', x, vh, COLOR_YELLOW, COLOR_BLACK);
|
||||||
|
set_color_cell('=', x, vd, COLOR_YELLOW, COLOR_BLACK);
|
||||||
|
}
|
||||||
|
for (int y = vh + 1; y < vd; y++) {
|
||||||
|
set_color_cell('|', vl, y, COLOR_YELLOW, COLOR_BLACK);
|
||||||
|
set_color_cell('|', vp, y, COLOR_YELLOW, COLOR_BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
int il = lavy_okraj(h) - 1;
|
||||||
|
int ip = pravy_okraj(h) + 1;
|
||||||
|
int ih = horny_okraj(h) - 1;
|
||||||
|
int id = h->palka.y + 2;
|
||||||
|
set_color_cell('+', il, ih, COLOR_WHITE, COLOR_BLACK);
|
||||||
|
set_color_cell('+', ip, ih, COLOR_WHITE, COLOR_BLACK);
|
||||||
|
set_color_cell('+', il, id, COLOR_WHITE, COLOR_BLACK);
|
||||||
|
set_color_cell('+', ip, id, COLOR_WHITE, COLOR_BLACK);
|
||||||
|
for (int x = il + 1; x < ip; x++) {
|
||||||
|
set_color_cell('-', x, ih, COLOR_WHITE, COLOR_BLACK);
|
||||||
|
set_color_cell('-', x, id, COLOR_WHITE, COLOR_BLACK);
|
||||||
|
}
|
||||||
|
for (int y = ih + 1; y < id; y++) {
|
||||||
|
set_color_cell('|', il, y, COLOR_WHITE, COLOR_BLACK);
|
||||||
|
set_color_cell('|', ip, y, COLOR_WHITE, COLOR_BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h->boss.ziva) {
|
||||||
|
short boss_farba = h->boss.pada ? COLOR_RED : COLOR_MAGENTA;
|
||||||
|
int bx = (int)h->boss.x;
|
||||||
|
int by = (int)h->boss.y;
|
||||||
|
set_color_cell('[', bx, by, COLOR_WHITE, boss_farba);
|
||||||
|
set_color_cell('!', bx + 1, by, COLOR_WHITE, boss_farba);
|
||||||
|
set_color_cell('!', bx + 2, by, COLOR_WHITE, boss_farba);
|
||||||
|
set_color_cell('!', bx + 3, by, COLOR_WHITE, boss_farba);
|
||||||
|
set_color_cell(']', bx + 4, by, COLOR_WHITE, boss_farba);
|
||||||
|
if (h->boss.pada) {
|
||||||
|
int sx = h->sirka / 2;
|
||||||
|
set_message("!!! BOSS PADA !!!", sx - 8, vh + 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
set_message("BOSS ZNICENY! +200", lavy_okraj(h), vh + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tx0 = tehla_zacatek_x(h);
|
||||||
|
int ty0 = tehla_zac_y(h);
|
||||||
|
for (int r = 0; r < MAX_RIADKOV; r++) {
|
||||||
|
for (int s = 0; s < MAX_STLPCOV; s++) {
|
||||||
|
if (!h->tehly[r][s].ziva) continue;
|
||||||
|
int tx = tx0 + s * 3;
|
||||||
|
int ty = ty0 + r;
|
||||||
|
short fc = h->tehly[r][s].farba;
|
||||||
|
set_color_cell('[', tx, ty, COLOR_WHITE, fc);
|
||||||
|
set_color_cell(h->tehly[r][s].znak, tx + 1, ty, COLOR_WHITE, fc);
|
||||||
|
set_color_cell(']', tx + 2, ty, COLOR_WHITE, fc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < h->palka.sirka; i++)
|
||||||
|
set_color_cell('=', h->palka.x + i, h->palka.y, COLOR_CYAN, COLOR_BLACK);
|
||||||
|
set_color_cell('<', h->palka.x, h->palka.y, COLOR_CYAN, COLOR_BLACK);
|
||||||
|
set_color_cell('>', h->palka.x + h->palka.sirka - 1, h->palka.y, COLOR_CYAN, COLOR_BLACK);
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
if (h->powerupy[i].ziva)
|
||||||
|
set_color_cell(h->powerupy[i].znak,
|
||||||
|
(int)h->powerupy[i].x, (int)h->powerupy[i].y,
|
||||||
|
h->powerupy[i].farba, COLOR_BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h->stav != STAV_KONIEC && h->stav != STAV_VYHRAL) {
|
||||||
|
for (int i = 0; i < MAX_LOPT; i++) {
|
||||||
|
if (h->lopty[i].ziva)
|
||||||
|
set_color_cell('O', (int)h->lopty[i].x, (int)h->lopty[i].y,
|
||||||
|
COLOR_WHITE, COLOR_BLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char skore_msg[32];
|
||||||
|
snprintf(skore_msg, sizeof(skore_msg), "Skore: %d", h->skore);
|
||||||
|
set_message(skore_msg, vl + 1, vh + 1);
|
||||||
|
|
||||||
|
if (h->special_dostupny)
|
||||||
|
set_message("[E=SPECIAL]", vl + 1, vh + 2);
|
||||||
|
else
|
||||||
|
set_message("[E=POUZITY]", vl + 1, vh + 2);
|
||||||
|
|
||||||
|
if (h->sirka_timer > 0)
|
||||||
|
set_message("[WIDE]", vl + 1, vh + 3);
|
||||||
|
|
||||||
|
int sekundy = h->cas_tikov * RYCHLOST_HRY / 1000;
|
||||||
|
int min = sekundy / 60;
|
||||||
|
int sek = sekundy % 60;
|
||||||
|
char timer[16];
|
||||||
|
snprintf(timer, sizeof(timer), "%02d:%02d", min, sek);
|
||||||
|
set_message(timer, vp - 5, vh + 1);
|
||||||
|
|
||||||
|
if (h->boss.ziva && !h->boss.pada) {
|
||||||
|
int zostava = (BOSS_CAS - h->cas_tikov) / (1000 / RYCHLOST_HRY);
|
||||||
|
if (zostava < 0) zostava = 0;
|
||||||
|
char boss_msg[20];
|
||||||
|
snprintf(boss_msg, sizeof(boss_msg), "BOSS:%ds", zostava);
|
||||||
|
set_message(boss_msg, vp - 8, vh + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
char hud[120];
|
||||||
|
snprintf(hud, sizeof(hud),
|
||||||
|
" %s | Level: %d | Zivoty: %d | Lopty: %d | A/D=pohyb E=special Q=koniec",
|
||||||
|
h->meno, h->level, h->zivoty, h->pocet_lopt);
|
||||||
|
set_message(hud, 0, h->vyska - 1);
|
||||||
|
|
||||||
|
if (h->stav == STAV_CAKA) {
|
||||||
|
int sx = h->sirka / 2;
|
||||||
|
int tehly_koniec = tehla_zac_y(h) + MAX_RIADKOV;
|
||||||
|
int volny_stred = (tehly_koniec + h->palka.y) / 2;
|
||||||
|
set_message("** STLAC MEDZERNIK / KLIKNI **", sx - 15, volny_stred);
|
||||||
|
|
||||||
|
} else if (h->stav == STAV_KONIEC || h->stav == STAV_VYHRAL) {
|
||||||
|
|
||||||
|
int lav = lavy_okraj(h);
|
||||||
|
int prav = pravy_okraj(h);
|
||||||
|
int tehly_koniec = tehla_zac_y(h) + MAX_RIADKOV;
|
||||||
|
int volny_stred = (tehly_koniec + h->palka.y) / 2;
|
||||||
|
|
||||||
|
int sx2 = (lav + prav) / 2;
|
||||||
|
int cy = volny_stred - 5;
|
||||||
|
if (cy < tehly_koniec + 1) cy = tehly_koniec + 1;
|
||||||
|
|
||||||
|
for (int x = lav + 1; x < prav; x++)
|
||||||
|
set_color_cell('=', x, cy, COLOR_CYAN, COLOR_BLACK);
|
||||||
|
|
||||||
|
if (h->stav == STAV_VYHRAL) {
|
||||||
|
char t[] = "** VYHRAL SI! **";
|
||||||
|
set_color_cell('*', sx2 - 8, cy + 1, COLOR_YELLOW, COLOR_BLACK);
|
||||||
|
set_color_cell('*', sx2 + 7, cy + 1, COLOR_YELLOW, COLOR_BLACK);
|
||||||
|
set_message(t, sx2 - (int)strlen(t) / 2, cy + 1);
|
||||||
|
char s[] = "Gratulujeme, hrdina!";
|
||||||
|
set_message(s, sx2 - (int)strlen(s) / 2, cy + 2);
|
||||||
|
} else {
|
||||||
|
char t[] = "** GAME OVER **";
|
||||||
|
set_color_cell('X', sx2 - 8, cy + 1, COLOR_RED, COLOR_BLACK);
|
||||||
|
set_color_cell('X', sx2 + 7, cy + 1, COLOR_RED, COLOR_BLACK);
|
||||||
|
set_message(t, sx2 - (int)strlen(t) / 2, cy + 1);
|
||||||
|
char s[] = "Nevzdavaj sa, bojovnik!";
|
||||||
|
set_message(s, sx2 - (int)strlen(s) / 2, cy + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
char riadok[40];
|
||||||
|
snprintf(riadok, sizeof(riadok), "Skore: %d Level: %d", h->skore, h->level);
|
||||||
|
set_message(riadok, sx2 - (int)strlen(riadok) / 2, cy + 3);
|
||||||
|
|
||||||
|
for (int x = lav + 1; x < prav; x++)
|
||||||
|
set_color_cell('-', x, cy + 4, COLOR_CYAN, COLOR_BLACK);
|
||||||
|
|
||||||
|
char inf[] = "Skore zapisane do:";
|
||||||
|
set_message(inf, sx2 - (int)strlen(inf) / 2, cy + 5);
|
||||||
|
|
||||||
|
char sub[] = "> scores.txt <";
|
||||||
|
set_color_cell('>', sx2 - (int)strlen(sub) / 2, cy + 6, COLOR_YELLOW, COLOR_BLACK);
|
||||||
|
set_message(sub, sx2 - (int)strlen(sub) / 2, cy + 6);
|
||||||
|
set_color_cell('<', sx2 + (int)strlen(sub) / 2 - 1, cy + 6, COLOR_YELLOW, COLOR_BLACK);
|
||||||
|
|
||||||
|
char kde[] = "(priecinok hry)";
|
||||||
|
set_message(kde, sx2 - (int)strlen(kde) / 2, cy + 7);
|
||||||
|
|
||||||
|
for (int x = lav + 1; x < prav; x++)
|
||||||
|
set_color_cell('=', x, cy + 8, COLOR_CYAN, COLOR_BLACK);
|
||||||
|
|
||||||
|
char kon[] = "Stlac Q pre ukoncenie";
|
||||||
|
set_message(kon, sx2 - (int)strlen(kon) / 2, cy + 9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void* init_game() {
|
||||||
|
Hra* h = (Hra*)malloc(sizeof(Hra));
|
||||||
|
if (!h) return NULL;
|
||||||
|
|
||||||
|
h->sirka = 60;
|
||||||
|
h->vyska = 30;
|
||||||
|
h->zivoty = ZIVOTY;
|
||||||
|
h->skore = 0;
|
||||||
|
h->level = 1;
|
||||||
|
h->stav = STAV_UVOD;
|
||||||
|
h->meno[0] = '\0';
|
||||||
|
h->meno_dlzka = 0;
|
||||||
|
h->hit_counter = 0;
|
||||||
|
h->sirka_timer = 0;
|
||||||
|
h->posledna_lopta = 0;
|
||||||
|
h->cas_tikov = 0;
|
||||||
|
h->special_dostupny = 1;
|
||||||
|
h->powerupy[0].ziva = 0;
|
||||||
|
h->powerupy[1].ziva = 0;
|
||||||
|
|
||||||
|
nastav_level(h);
|
||||||
|
|
||||||
|
h->palka.sirka = PALKA_SIRKA_MIN;
|
||||||
|
h->palka.y = palka_default_y(h);
|
||||||
|
h->palka.x = h->sirka / 2 - PALKA_SIRKA_MIN / 2;
|
||||||
|
|
||||||
|
inicializuj_boss(h);
|
||||||
|
inicializuj_lopty(h);
|
||||||
|
inicializuj_tehly(h);
|
||||||
|
game_speed(RYCHLOST_HRY);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy_game(void* hra) {
|
||||||
|
free(hra);
|
||||||
|
}
|
||||||
|
|
||||||
|
int game_event(struct event* udalost, void* hra) {
|
||||||
|
Hra* h = (Hra*)hra;
|
||||||
|
|
||||||
|
if (udalost->width > 0) h->sirka = udalost->width;
|
||||||
|
if (udalost->height > 0) h->vyska = udalost->height;
|
||||||
|
|
||||||
|
if (h->stav == STAV_UVOD) {
|
||||||
|
if (udalost->type == EVENT_KEY) {
|
||||||
|
int k = udalost->key;
|
||||||
|
if (k == '\n' || k == KEY_ENTER) {
|
||||||
|
if (h->meno_dlzka == 0) {
|
||||||
|
strcpy(h->meno, "Hrac");
|
||||||
|
h->meno_dlzka = 4;
|
||||||
|
}
|
||||||
|
nastav_level(h);
|
||||||
|
inicializuj_tehly(h);
|
||||||
|
h->palka.sirka = PALKA_SIRKA_MIN;
|
||||||
|
h->palka.y = palka_default_y(h);
|
||||||
|
h->palka.x = h->sirka / 2 - PALKA_SIRKA_MIN / 2;
|
||||||
|
h->hit_counter = 0;
|
||||||
|
h->sirka_timer = 0;
|
||||||
|
h->posledna_lopta = 0;
|
||||||
|
h->cas_tikov = 0;
|
||||||
|
h->special_dostupny = 1;
|
||||||
|
h->powerupy[0].ziva = 0;
|
||||||
|
h->powerupy[1].ziva = 0;
|
||||||
|
inicializuj_boss(h);
|
||||||
|
inicializuj_lopty(h);
|
||||||
|
h->stav = STAV_CAKA;
|
||||||
|
} else if (k == KEY_BACKSPACE && h->meno_dlzka > 0) {
|
||||||
|
h->meno[--h->meno_dlzka] = '\0';
|
||||||
|
} else if (k >= 32 && k < 127 && h->meno_dlzka < 31) {
|
||||||
|
h->meno[h->meno_dlzka++] = (char)k;
|
||||||
|
h->meno[h->meno_dlzka] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vykresli_hru(h);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h->stav == STAV_DALSI_LEVEL) {
|
||||||
|
int next = 0;
|
||||||
|
if (udalost->type == EVENT_KEY && udalost->key == ' ') next = 1;
|
||||||
|
if (udalost->type == EVENT_MOUSE && udalost->mouse_left) next = 1;
|
||||||
|
if (next) {
|
||||||
|
h->level++;
|
||||||
|
nastav_level(h);
|
||||||
|
inicializuj_tehly(h);
|
||||||
|
h->palka.sirka = PALKA_SIRKA_MIN;
|
||||||
|
h->palka.y = palka_default_y(h);
|
||||||
|
h->palka.x = h->sirka / 2 - PALKA_SIRKA_MIN / 2;
|
||||||
|
h->hit_counter = 0;
|
||||||
|
h->sirka_timer = 0;
|
||||||
|
h->posledna_lopta = 0;
|
||||||
|
h->cas_tikov = 0;
|
||||||
|
h->special_dostupny = 1;
|
||||||
|
h->powerupy[0].ziva = 0;
|
||||||
|
h->powerupy[1].ziva = 0;
|
||||||
|
inicializuj_boss(h);
|
||||||
|
inicializuj_lopty(h);
|
||||||
|
h->stav = STAV_CAKA;
|
||||||
|
}
|
||||||
|
vykresli_hru(h);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (udalost->type == EVENT_MOUSE) {
|
||||||
|
int ciel_x = udalost->mouse_x - h->palka.sirka / 2;
|
||||||
|
int lav = lavy_okraj(h);
|
||||||
|
int prav = pravy_okraj(h) - h->palka.sirka + 1;
|
||||||
|
if (ciel_x < lav) ciel_x = lav;
|
||||||
|
if (ciel_x > prav) ciel_x = prav;
|
||||||
|
h->palka.x = ciel_x;
|
||||||
|
if (h->stav == STAV_CAKA)
|
||||||
|
h->lopty[0].x = (float)(h->palka.x + h->palka.sirka / 2);
|
||||||
|
if (udalost->mouse_left && h->stav == STAV_CAKA)
|
||||||
|
h->stav = STAV_HRAJE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (udalost->type == EVENT_KEY) {
|
||||||
|
int k = udalost->key;
|
||||||
|
if (k == 'q' || k == 'Q') return 1;
|
||||||
|
if (k == 'e' || k == 'E') {
|
||||||
|
vystrel_special(h);
|
||||||
|
} else if (k == KEY_LEFT || k == 'a' || k == 'A') {
|
||||||
|
pohni_palku(h, -1);
|
||||||
|
} else if (k == KEY_RIGHT || k == 'd' || k == 'D') {
|
||||||
|
pohni_palku(h, +1);
|
||||||
|
} else if (k == ' ' && h->stav == STAV_CAKA) {
|
||||||
|
h->stav = STAV_HRAJE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pohni_lopty(h);
|
||||||
|
vykresli_hru(h);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
90
final/game.h
Normal file
90
final/game.h
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#ifndef _GAME_H_
|
||||||
|
#define _GAME_H_
|
||||||
|
|
||||||
|
#include "world.h"
|
||||||
|
|
||||||
|
#define MAX_RIADKOV 7
|
||||||
|
#define MAX_STLPCOV 10
|
||||||
|
#define ZIVOTY 3
|
||||||
|
#define RYCHLOST_HRY 120
|
||||||
|
#define PALKA_SIRKA_MIN 7
|
||||||
|
#define PALKA_SIRKA_MAX 14
|
||||||
|
#define PALKA_ROW_OD_DNA 2
|
||||||
|
#define MAX_LOPT 16
|
||||||
|
#define BOSS_CAS 240
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
STAV_UVOD,
|
||||||
|
STAV_CAKA,
|
||||||
|
STAV_HRAJE,
|
||||||
|
STAV_KONIEC,
|
||||||
|
STAV_VYHRAL,
|
||||||
|
STAV_DALSI_LEVEL,
|
||||||
|
} StavHry;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int x, y;
|
||||||
|
int sirka;
|
||||||
|
} Palka;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float x, y;
|
||||||
|
float dx, dy;
|
||||||
|
int ziva;
|
||||||
|
} Lopta;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int ziva;
|
||||||
|
int farba;
|
||||||
|
char znak;
|
||||||
|
} Tehla;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int ziva;
|
||||||
|
float x, y;
|
||||||
|
char znak;
|
||||||
|
short farba;
|
||||||
|
} PowerUp;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int ziva;
|
||||||
|
float x, y;
|
||||||
|
float dx;
|
||||||
|
int pada;
|
||||||
|
} Boss;
|
||||||
|
|
||||||
|
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;
|
||||||
|
int riadkov;
|
||||||
|
float rychlost;
|
||||||
|
StavHry stav;
|
||||||
|
int sirka;
|
||||||
|
int vyska;
|
||||||
|
char meno[32];
|
||||||
|
int meno_dlzka;
|
||||||
|
PowerUp powerupy[2];
|
||||||
|
int hit_counter;
|
||||||
|
int sirka_timer;
|
||||||
|
int posledna_lopta;
|
||||||
|
int cas_tikov;
|
||||||
|
int special_dostupny;
|
||||||
|
Boss boss;
|
||||||
|
} Hra;
|
||||||
|
|
||||||
|
void* init_game();
|
||||||
|
int game_event(struct event* udalost, void* hra);
|
||||||
|
void destroy_game(void* hra);
|
||||||
|
|
||||||
|
void pohni_palku(Hra* h, int smer);
|
||||||
|
void pohni_lopty(Hra* h);
|
||||||
|
void inicializuj_tehly(Hra* h);
|
||||||
|
void vykresli_hru(Hra* h);
|
||||||
|
|
||||||
|
#endif
|
||||||
6
final/main.c
Normal file
6
final/main.c
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "world.h"
|
||||||
|
#include "game.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return start_world(init_game, game_event, destroy_game);
|
||||||
|
}
|
||||||
27
final/scores.txt
Normal file
27
final/scores.txt
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
+-------------------------------------------------+
|
||||||
|
| Hrac : Filip |
|
||||||
|
| Skore : 20 |
|
||||||
|
| Level : 1 |
|
||||||
|
| Cas : 00:23 |
|
||||||
|
| Vysledok: GAME OVER |
|
||||||
|
| Datum : 09.05.2026 17:37:02 |
|
||||||
|
+-------------------------------------------------+
|
||||||
|
|
||||||
|
+-------------------------------------------------+
|
||||||
|
| Hrac : Filip |
|
||||||
|
| Skore : 90 |
|
||||||
|
| Level : 1 |
|
||||||
|
| Cas : 00:15 |
|
||||||
|
| Vysledok: GAME OVER |
|
||||||
|
| Datum : 09.05.2026 17:43:40 |
|
||||||
|
+-------------------------------------------------+
|
||||||
|
|
||||||
|
+-------------------------------------------------+
|
||||||
|
| Hrac : Filip |
|
||||||
|
| Skore : 620 |
|
||||||
|
| Level : 2 |
|
||||||
|
| Cas : 00:03 |
|
||||||
|
| Vysledok: GAME OVER |
|
||||||
|
| Datum : 10.05.2026 09:22:53 |
|
||||||
|
+-------------------------------------------------+
|
||||||
|
|
||||||
198
final/world.c
Normal file
198
final/world.c
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
#include "world.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
int TIMEOUT;
|
||||||
|
|
||||||
|
void abort_game(const char* message){
|
||||||
|
endwin();
|
||||||
|
puts(message);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_bounds(const char* source,int x, int y){
|
||||||
|
char msg[200];
|
||||||
|
if (x < 0 || x >= COLS){
|
||||||
|
sprintf(msg,"%s:: width %d is out of bounds (0,%d)",source,x,COLS);
|
||||||
|
abort_game(msg);
|
||||||
|
}
|
||||||
|
if (y < 0 || y >= LINES){
|
||||||
|
sprintf(msg,"%s:: height %d is out of bounds (0,%d)",source,y,LINES);
|
||||||
|
abort_game(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_screen(){
|
||||||
|
// Clear screen
|
||||||
|
mvaddch(0,0,' ');
|
||||||
|
int screenchars = LINES*COLS;
|
||||||
|
for (int j = 1; j < screenchars;j++ ){
|
||||||
|
addch(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_speed(int value){
|
||||||
|
if (value < 0){
|
||||||
|
abort_game("world_seed:: cannot be negative\n");
|
||||||
|
}
|
||||||
|
TIMEOUT =value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_message(const char* message,int x,int y) {
|
||||||
|
int l = strlen(message);
|
||||||
|
for (int i = 0; i < l; i++){
|
||||||
|
check_bounds("set_message",x+i,y);
|
||||||
|
set_cell(message[i],x+i,y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void assert_message(int event,const char* message){
|
||||||
|
if (event == 0){
|
||||||
|
abort_game(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void set_cell(int character,int x,int y) {
|
||||||
|
check_bounds("set_cell",x,y);
|
||||||
|
set_color_cell(character,x,y,COLOR_WHITE,COLOR_BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_color_cell(int character,int x,int y,short front_color,short back_color){
|
||||||
|
check_bounds("set_color_cell",x,y);
|
||||||
|
if (has_colors()){
|
||||||
|
int pair = COLOR_COUNT * front_color + back_color;
|
||||||
|
attron(COLOR_PAIR(pair));
|
||||||
|
mvaddch(y,x,character);
|
||||||
|
attroff(COLOR_PAIR(pair));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
mvaddch(y,x,character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int start_world(void* (*init_game)(),int (*world_event)(struct event* event,void* game),void (*destroy_game)(void*)){
|
||||||
|
srand(time(NULL));
|
||||||
|
int r = 1;
|
||||||
|
// Speed global variable
|
||||||
|
TIMEOUT = 100;
|
||||||
|
if (initscr() == NULL){
|
||||||
|
// TODO Which Error?
|
||||||
|
puts("Curses Error.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
noecho(); // Nevypisuj vstup na obrazovku
|
||||||
|
cbreak(); // Zabudni starý vstup
|
||||||
|
nodelay(stdscr,TRUE); // Nečakaj na stlačenie
|
||||||
|
keypad(stdscr,TRUE); // Aktivuje šípky
|
||||||
|
curs_set(FALSE); // Neviditeľný kurzor
|
||||||
|
/* Get all the mouse events */
|
||||||
|
mousemask(ALL_MOUSE_EVENTS, NULL);
|
||||||
|
MEVENT mouse_event;
|
||||||
|
if (has_colors()){ // Zistenie či terminál podporuje farby
|
||||||
|
start_color();
|
||||||
|
for (int i = 0; i < COLOR_COUNT;i++){
|
||||||
|
for (int j = 0; j < COLOR_COUNT;j++){
|
||||||
|
init_pair(i * COLOR_COUNT + j, i,j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
puts("No colors!\n");
|
||||||
|
}
|
||||||
|
void* game = NULL;
|
||||||
|
if (init_game != NULL){
|
||||||
|
game = init_game();
|
||||||
|
assert_message(game != NULL,"init_game:: should return non null pointer");
|
||||||
|
}
|
||||||
|
timeout(TIMEOUT);
|
||||||
|
// Initial step
|
||||||
|
struct event event;
|
||||||
|
memset(&event,0,sizeof(struct event));
|
||||||
|
event.height = LINES;
|
||||||
|
event.width = COLS;
|
||||||
|
event.type = EVENT_START;
|
||||||
|
clock_t start_time = clock();
|
||||||
|
clock_t last_timeout = start_time;
|
||||||
|
clock_t next_timeout = last_timeout + TIMEOUT;
|
||||||
|
event.time_ms = start_time;
|
||||||
|
// Start event
|
||||||
|
r = world_event(&event,game);
|
||||||
|
refresh();
|
||||||
|
while (!r) {
|
||||||
|
memset(&event,0,sizeof(struct event));
|
||||||
|
event.height = LINES;
|
||||||
|
event.width = COLS;
|
||||||
|
event.key = getch();
|
||||||
|
// No key was pressed
|
||||||
|
if (event.key == ERR){
|
||||||
|
event.type = EVENT_TIMEOUT;
|
||||||
|
last_timeout = clock();
|
||||||
|
next_timeout = last_timeout + TIMEOUT;
|
||||||
|
}
|
||||||
|
// Mouse event
|
||||||
|
else if (event.key == KEY_MOUSE ){
|
||||||
|
event.type = EVENT_MOUSE;
|
||||||
|
if(getmouse(&mouse_event) == OK){
|
||||||
|
event.mouse_x = mouse_event.x;
|
||||||
|
event.mouse_y = mouse_event.y;
|
||||||
|
if(mouse_event.bstate & BUTTON1_PRESSED){
|
||||||
|
event.mouse_left = 1;
|
||||||
|
}
|
||||||
|
if(mouse_event.bstate & BUTTON2_PRESSED){
|
||||||
|
event.mouse_middle = 1;
|
||||||
|
}
|
||||||
|
if(mouse_event.bstate & BUTTON3_PRESSED){
|
||||||
|
event.mouse_right = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (event.key == KEY_RESIZE) {
|
||||||
|
event.type = EVENT_RESIZE;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
event.type = EVENT_KEY;
|
||||||
|
if (event.key == 27){
|
||||||
|
int k = getch();
|
||||||
|
if (k == -1){
|
||||||
|
// Esc Was pressed
|
||||||
|
event.type = EVENT_ESC;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Alt was pressed
|
||||||
|
event.key = k;
|
||||||
|
event.alt_key = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Draw new world
|
||||||
|
event.time_ms = clock();
|
||||||
|
r = world_event(&event,game);
|
||||||
|
refresh();
|
||||||
|
event.time_ms = clock();
|
||||||
|
// set new timeout
|
||||||
|
int nt = next_timeout - event.time_ms;
|
||||||
|
//printf("%d\n",nt);
|
||||||
|
if (nt > 0){
|
||||||
|
timeout(nt);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
timeout(TIMEOUT);
|
||||||
|
next_timeout = event.time_ms + TIMEOUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memset(&event,0,sizeof(struct event));
|
||||||
|
event.height = LINES;
|
||||||
|
event.width = COLS;
|
||||||
|
event.type = EVENT_END;
|
||||||
|
event.time_ms = clock();
|
||||||
|
world_event(&event,game);
|
||||||
|
if (destroy_game != NULL){
|
||||||
|
destroy_game(game);
|
||||||
|
}
|
||||||
|
endwin();
|
||||||
|
return r;
|
||||||
|
};
|
||||||
113
final/world.h
Normal file
113
final/world.h
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
#ifndef _WORLD_H_
|
||||||
|
#define _WORLD_H_
|
||||||
|
|
||||||
|
#include <curses.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* World represented as a rectangular matrix of colorful characters.
|
||||||
|
*
|
||||||
|
* Point [0,0] is displayed the upper left corner of the screen.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum event_type {
|
||||||
|
EVENT_START,
|
||||||
|
EVENT_TIMEOUT,
|
||||||
|
EVENT_KEY,
|
||||||
|
EVENT_MOUSE,
|
||||||
|
EVENT_RESIZE,
|
||||||
|
EVENT_ESC,
|
||||||
|
EVENT_END,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct event {
|
||||||
|
/**
|
||||||
|
* Last width of the screen.
|
||||||
|
*/
|
||||||
|
int width;
|
||||||
|
/**
|
||||||
|
* Last height of the screen.
|
||||||
|
*/
|
||||||
|
int height;
|
||||||
|
/**
|
||||||
|
* Last pressed key or Curses event.
|
||||||
|
*
|
||||||
|
* Special event values:
|
||||||
|
* ERR if timeout,
|
||||||
|
* KEY_RESIZE if screen resize
|
||||||
|
* KEY_EVENT, other event,
|
||||||
|
* KEY_MOUSE, mouse clicked
|
||||||
|
*
|
||||||
|
* Key values:
|
||||||
|
*
|
||||||
|
* ' ' Space
|
||||||
|
* KEY_DOWN Arrow down
|
||||||
|
* KEY_UP Arrow up
|
||||||
|
* KEY_LEFT Arrow left
|
||||||
|
* KEY_RIGHT Arrow right
|
||||||
|
* KEY_A1 Upper left of keypad
|
||||||
|
* KEY_A3 Upper right of keypad
|
||||||
|
* KEY_B2 Center of keypad
|
||||||
|
* KEY_C1 Lower left of keypad
|
||||||
|
* KEY_C3 Lower right of keypad
|
||||||
|
*
|
||||||
|
* KEY_ENTER
|
||||||
|
* KEY_BACKSPACE
|
||||||
|
*/
|
||||||
|
int key;
|
||||||
|
int alt_key;
|
||||||
|
enum event_type type;
|
||||||
|
int mouse_x;
|
||||||
|
int mouse_y;
|
||||||
|
int mouse_left;
|
||||||
|
int mouse_right;
|
||||||
|
int mouse_middle;
|
||||||
|
long int time_ms;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets cell to a state.
|
||||||
|
* @param event
|
||||||
|
* @param x coordinate of cell
|
||||||
|
* @param y coordinate of cell
|
||||||
|
* @param new state of the cell
|
||||||
|
*/
|
||||||
|
void set_cell(int character,int x,int y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* COLOR_BLACK 0
|
||||||
|
* COLOR_RED 1
|
||||||
|
* COLOR_GREEN 2
|
||||||
|
* COLOR_YELLOW 3
|
||||||
|
* COLOR_BLUE 4
|
||||||
|
* COLOR_MAGENTA 5
|
||||||
|
* COLOR_CYAN 6
|
||||||
|
* COLOR_WHITE 7
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define COLOR_COUNT 8
|
||||||
|
|
||||||
|
void set_color_cell(int character,int x,int y,short front_color,short back_color);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* @param number of commandline arguments
|
||||||
|
* @param init_world
|
||||||
|
* @param destroy_world
|
||||||
|
*
|
||||||
|
* void init_world(struct event* w);
|
||||||
|
* Initializes user state.
|
||||||
|
* Free user state.
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
|
|
||||||
|
int start_world(void* (*init_game)(),int (*world_event)(struct event* event,void* game),void (*destroy_game)(void* game));
|
||||||
|
|
||||||
|
void game_speed(int value);
|
||||||
|
|
||||||
|
void set_message(const char* message,int x,int y);
|
||||||
|
void clear_screen();
|
||||||
|
|
||||||
|
#endif
|
||||||
Loading…
Reference in New Issue
Block a user