Něco na začátek
Po článku o C++ od redaktora Firejs jsem vytvořil menší dodatek, když si budete chtít hru zpříjemnit, nebo nějak ozvláštnit. Můžete zde najít ukládání a načítání (hodí se pro delší hry), barevný text, vycentrování, a další různé tipy, které hru udělají zajímavější.
Budeme vytvářet funkce. Pokud jste programovali dříve, určitě znáte významy slov void, return, argument apod. Pokud ne, čtěte.
Funkce může mít argumenty a může vracet hodnotu. Vytvoření funkce je typ_navratove_hodnoty nazev(argumenty){ obsah funkce }. Příklad (vrátí třetí mocninu):
/*do promenne cislo se vlozi prvni argument*/
return cislo*cislo*cislo;
/*return vrací hodnotu*/
}
Typ návratové hodnoty může být typ proměnné (int, double, boolean, char, atd.) nebo funkce nevrací hodnotu (void).
Začneme programovat
Barevný text
Nejdříve vám ukážu, jak si jednoduše vytvořit barevný text. Můžete mít 7 barev, které mají 2 odstíny + bílá. Celkem to je tedy 15 barev. Otevřete si zdrojový soubor hry, musíme vložit hlavičku windows.h, proto na začátek vložte:
Než začneme s int main(), vytvoříme enumerátor (proměnná, která má více hodnot) a funkci, která nastaví barvu:
enum Color { DARKBLUE = 1, DARKGREEN, DARKTEAL, DARKRED, DARKPINK, DARKYELLOW, GRAY, DARKGRAY, BLUE, GREEN, TEAL, RED, PINK, YELLOW, WHITE };
void Col(Color c){
if(hCon == NULL)
hCon = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hCon, c);
}
Nyní si pomocí funkce Col() zvolíme barvu (argument je název barvy, která je v enumerátoru (takže chcete-li modrou, napíšete Col(BLUE), pokud tmavě červenou tak Col(DARKRED) apod.), pozor, píšeme jej BEZ UVOZOVEK!) a potom použijeme cout na vypsání. Pokud nechápete, podívejte se na vzorový příklad:
#include <windows.h>
using namespace std;
HANDLE hCon;
enum Color { DARKBLUE = 1, DARKGREEN, DARKTEAL, DARKRED, DARKPINK, DARKYELLOW, GRAY, DARKGRAY, BLUE, GREEN, TEAL, RED, PINK, YELLOW, WHITE };
void Col(Color c){
if(hCon == NULL)
hCon = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hCon, c);
}
int main(){
Col(GREEN);
cout << "Ja jsem zeleny text.\n";
Col(GRAY);
cout << "Ja jsem normalni text s ";
Col(DARKBLUE);
cout << "tmavemodrou";
Col(GRAY);
cout << " naplni.\n";
Col(DARKTEAL);
cout << "Stiskni ENTER pro ukonceni.\n";
cin.get();
return 0;
}
Výstup:
Zdroják: KLIK
Vycentrování textu
Vytvoříme funkci, která nám vycentruje text (text bude uprostřed). Cyklem vytvoříme mezery, jejichž počet bude vypočten aby text byl uprostřed. Na šířku se na jeden řádek vleze 80 znaků, proto od poloviny (40) odečteme poloviční počet znaků textu, který bude prvním argumentem funkce. Příkaz length() vrací počet znaků v textu. Používá se int vystup = stringova_promenna.length();. Konečná funkce vypadá takto:
for(int a=0; a<40-(text.length()/2); a++){
cout << " ";
}
cout << text;
}
A celý zdroják je teď:
#include <windows.h>
using namespace std;
HANDLE hCon;
enum Color { DARKBLUE = 1, DARKGREEN, DARKTEAL, DARKRED, DARKPINK, DARKYELLOW, GRAY, DARKGRAY, BLUE, GREEN, TEAL, RED, PINK, YELLOW, WHITE };
void Col(Color c){
if(hCon == NULL)
hCon = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hCon, c);
}
void Center(string text){
for(int a=0; a<40-(text.length()/2); a++){
cout << " ";
}
cout << text;
}
int main(){
Col(GREEN);
cout << "Ja jsem zeleny text.\n";
Col(GRAY);
cout << "Ja jsem normalni text s ";
Col(DARKBLUE);
cout << "tmavemodrou";
Col(GRAY);
cout << " naplni.\n";
Col(RED);
Center("Halo, hlasi se vam cerveny vycentrovany text!");
cout << "\n";
Col(YELLOW);
Center("A zluty taky!");
cout << "\n";
Col(DARKTEAL);
cout << "Stiskni ENTER pro ukonceni.\n";
cin.get();
return 0;
}
Výstup:
Zdroják: KLIK
Háčky, čárky a další znaky
Normálně nemůžete psát háčky, čárky a speciální znaky, protože se nezobrazí správně. Proto musíme vypsat všechny čísla a znaky. Vytvoříme cyklus, který vypíše všechny znaky. Znaků je 256, proto se cyklus zopakouje 256krát, vypíše se číslo, znak který k němu patří a nový řádek:
using namespace std;
int main(){
for(int a=0; a<256; a++){
cout << a << " : " << (char) a << "\n";
}
cin.get();
return 0;
}
Vložte kód zvlášť do jiného zdrojového souboru. Všechny znaky se vypíšou (počítač pípne, protože sedmý znak je PC Beep). Takhle by to mělo vypadat:
Zdroják: KLIK
Nyní se nám naskýtají 2 možnosti. Buď můžeme uložit čísla do proměnných nebo vypisovat znaky z čísel bez použití proměnných. Na obrázku vidíme např. znak á a u něj číslo 160. S použitím proměnných by to vypadalo:
cout << "Zpr" << aa << "va";
A bez proměnných:
V obou případech uvidíte Zpráva. V prvním kódu bude v proměnné aa znak á. Jaké jsou pro a proti?
S proměnnými
PRO
- Nemusíte si pamatovat čísla
- Při použití velkého množství diakritiky bude kód přehlednější a menší
PROTI
- Použijí se proměnné
Bez proměnných
PRO
- Nepoužíváte proměnné
PROTI
- Musíte si pamatovat čísla
- Kód je nepřehledný a větší
Proto doporučuji použít proměnné, ale jak chcete. Pomocí posuvníku vpravo můžete hledat znaky, které potřebujete. Potom podle ukázkových kódu vložte diakritiku.
Tady je seznam české diakritiky u malých písmen:
char cc=159; /* č */
char dd=212; /* ď */
char eec=130; /* é */
char eeh=216; /* ě */
char ii=161; /* í */
char nn=229; /* ň */
char oo=162; /* ó */
char rr=253; /* ř */
char ss=231; /* š */
char tt=156; /* ť */
char uuc=163; /* ú */
char uuk=133; /* ů */
char yy=236; /* ý */
char zz=167; /* ž */
Takto vypadá nyní náš kód:
#include <windows.h>
using namespace std;
HANDLE hCon;
enum Color { DARKBLUE = 1, DARKGREEN, DARKTEAL, DARKRED, DARKPINK, DARKYELLOW, GRAY, DARKGRAY, BLUE, GREEN, TEAL, RED, PINK, YELLOW, WHITE };
void Col(Color c){
if(hCon == NULL)
hCon = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hCon, c);
}
void Center(string text){
for(int a=0; a<40-(text.length()/2); a++){
cout << " ";
}
cout << text;
}
char aa=160;
char cc=159;
int main(){
Col(GREEN);
cout << "Ja jsem zeleny text.\n";
Col(GRAY);
cout << "Ja jsem normalni text s ";
Col(DARKBLUE);
cout << "tmavemodrou";
Col(GRAY);
cout << " naplni.\n";
Col(RED);
Center("Halo, hlasi se vam cerveny vycentrovany text!");
cout << "\n";
Col(YELLOW);
Center("A zluty taky!");
cout << "\n";
Col(DARKTEAL);
cout << "Stiskni ENTER pro ukonceni.\n";
Col(PINK);
cout << "A j" << aa << " m" << aa << "m h" << aa << cc << "ky a " << cc << aa << "rky!\n";
cin.get();
return 0;
}
Výstup:
Zdroják: KLIK
Postupné vypisování textu
Hodí se třeba k příběhu. Text se nezobrazí hned ale postupně se vypíše. Cyklem vypíšeme písmenko, na chvilku program zastavíme, potom vypíšeme další písmenko a tak dokola. K zastavení slouží příkaz Sleep(cas v milisekundach); a potřebujete pro něj hlavíčku windows.h, v našem příkladu ji už vloženou máme. K zjištění konkrétního písmena ve stringové proměnné slouží at(), používá se string vystup = stringova_promenna.at(cislo_znaku); a zjištění počtu písmen zajišťuje length().
Skript, ve kterém máme 2 argumenty (text a rychlost) vypadá takto:
for(int a=0; a<text.length(); a++){
cout << text.at(a);
Sleep(slp);
}
}
Druhý argument, rychlost je doba v milisekundách jak dlouho se před vypsáním dalšího znaku bude čekat. Pro rychlý výpis se hodí hodnota 50, pro méně rychlý 75 a pomalý 100. Můžete udělat výběr rychlosti. Ovšem, my ještě můžeme skript rozšířit tak, že při držení mezerníku bude výpis textu rychlý. Pro zjištění stisknutí klávesy slouží GetAsyncKeyState(klavesa) a potřebujete pro ni windows.h. Mezerník je VK_SPACE, po menší úpravě skript vypadá takto:
for(int a=0; a<text.length(); a++){
cout << text.at(a);
if (GetAsyncKeyState(VK_SPACE)){
Sleep(40);
}
else{
Sleep(slp);
}
}
}
Můžete i přidat třetí argument, který bude určovat jestli se může zrychlit text mezerníkem. Pokud by to byla proměnná typu boolean, měli byste pěknou různorodou rodinku (string,int,bool) :)). Takto vypadá skript zakomponovaný do našeho zdrojáku:
#include <windows.h>
using namespace std;
HANDLE hCon;
enum Color { DARKBLUE = 1, DARKGREEN, DARKTEAL, DARKRED, DARKPINK, DARKYELLOW, GRAY, DARKGRAY, BLUE, GREEN, TEAL, RED, PINK, YELLOW, WHITE };
void Col(Color c){
if(hCon == NULL)
hCon = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hCon, c);
}
void Center(string text){
for(int a=0; a<40-(text.length()/2); a++){
cout << " ";
}
cout << text;
}
void Vypis(string text,int slp){
for(int a=0; a<text.length(); a++){
cout << text.at(a);
if (GetAsyncKeyState(VK_SPACE)){
Sleep(40);
}
else{
Sleep(slp);
}
}
}
char aa=160;
char cc=159;
int main(){
Col(GREEN);
cout << "Ja jsem zeleny text.\n";
Col(GRAY);
cout << "Ja jsem normalni text s ";
Col(DARKBLUE);
cout << "tmavemodrou";
Col(GRAY);
cout << " naplni.\n";
Col(RED);
Center("Halo, hlasi se vam cerveny vycentrovany text!");
cout << "\n";
Col(YELLOW);
Center("A zluty taky!");
cout << "\n";
Col(DARKTEAL);
cout << "Stiskni ENTER pro ukonceni.\n";
Col(PINK);
cout << "A j" << aa << " m" << aa << "m h" << aa << cc << "ky a " << cc << aa << "rky!\n";
Col(DARKRED);
Vypis("Ja sice nejsem centrovany ani nemam hacky a carky ale vypisuju se postupne.",60);
cout << "\n";
Vypis("Ja se vypisuju pomalu!",100);
cout << "\n";
Vypis("Pokud chces, aby se text vypisoval rychleji, drz mezernik!",200);
cin.get();
return 0;
}
Výstup:
Zdroják: KLIK
Tipy (nejen) pro textovku
Oddělil jsem tipy, protože ty následující se hodí spíš víc pro textovku, teda alespoň podle mě. Pokud vám tohle vysvětlení nesedí, tak jsem to rozdělil aby to bylo přehlednější a to nejtěžší (ukládání a načítání) dal nakonec, nebo protože nyní vytvoříme nový zdrojový soubor. :). Nezačneme ale s ukládáním a načítáním, ale s něčím jako záložky nebo štítky (labely).
Záložky/Štítky
Pomocí nich se můžete přesouvat na různé místa v kódu. Vytvoříme nový soubor .cpp nebo celý projekt, podle možností v programu kde kód píšete. Začal jsem tvořit jednoduchou adventurku. Jak se ale přesunovat na různé místa? Štítky! Předvedu ukázku (obsah main):
prvni:
cout << "Jsi na prvnim stitku. Kam pujdes?\n";
cout << "0: Druhy stitek\n1: Treti stitek\n2: Pryc\n";
cout << "Kam pujdes: ";
cin >> vyber;
system("cls");
switch(vyber){
case 0: goto druhy; break;
case 1: goto treti; break;
case 2: goto konec; break;
default: goto prvni;
}
druhy:
cout << "Jsi na druhem stitku. Kam pujdes ted?\n";
cout << "0: Prvni stitek\n1: Treti stitek\n2: Pryc\n";
cout << "Kam pujdes: ";
cin >> vyber;
system("cls");
switch(vyber){
case 0: goto prvni; break;
case 1: goto treti; break;
case 2: goto konec; break;
default: goto druhy;
}
treti:
cout << "Jsi na tretim stitku. Kam pujdes ted?\n";
cout << "0: Prvni stitek\n1: Druhy stitek\n2: Pryc\n";
cout << "Kam pujdes: ";
cin >> vyber;
system("cls");
switch(vyber){
case 0: goto prvni; break;
case 1: goto druhy; break;
case 2: goto konec; break;
default: goto treti;
}
konec:
return 0;
Jak jste si jistě všimli, štítky jsou prvni, druhy, treti a konec. Štítek si můžete pojmenovat i jinak. Při vytvoření musíte za názvem štítku mít dvojtečku. Pro přechod na štítek se používá goto nazev_stitku;. Malý detail, system("cls"); smaže text který je v okně (cls jako clean screen), příkaz system() spustí DOSový příkaz. Udělal jsem menší hru a i když je malá, ukážeme si na ní ukládání a načítání.
Zdroják: KLIK
Ukládání a načítání
Nejtěžší věc jsem si nechal na konec. Pro práci se soubory použijeme fstream (file stream), takže na začátek souboru vložte:
Vytvořte si funkci, která zobrazí text na zvolení uložení/načtení, funkci na zjištění jestli jsme chtěli hru uložit/načíst a funkce na uložení a načtení :). Nejdříve uložení:
ofstream file;
file.open("save.sav");
file << cast << "\n" << penize;
file.close();
}
Proměnná file nyní slouží pro otevření souboru save.sav, zapíšou se do ní proměnné cast a penize (číselné proměnné) a \n pro nový řádek v souboru a nakonec se soubor ukončí. Teď načtení. Vytvoříme stringové proměnné do kterých uložíme obsah souboru a převedeme na číselné:
string scast;
string spenize;
ifstream file;
file.open("save.sav");
getline(file,scast);
getline(file,spenize);
file.close();
cast=atoi(scast.c_str());
penize=atoi(spenize.c_str());
}
Ifstream nastaví proměnnou file na otevření souboru pro čtení, getline() přečte řádek a uloží do proměnné a atoi() převede string na integer. c_str() je zapotřebí, jinak by funkce měla špatný argument a kompilátor by hlásil chybu. Přišla řada na kontrolu, jestli hru chceme uložit nebo načíst:
switch(vyber){
case 98: Save(); break;
case 99: Load(); return 1; break;
default: return 0;
}
}
Takto vypadá volání:
if (SLCheck(vyber)==1){ goto presun; }
/* switch na jiné akce */
Proměnná vyber je integer a vkládá se do ní číslo akce, které jsme zadali. V záložce presun která je na konci main() máme switch na různé záložky. Při každém vstupu na záložku se nastaví proměnná cast (integer) na určitou hodnotu podle čísla lokace a v tom switchi v záložce presun se kontroluje. Když uložíte hru v laboratoři která má číslo 10, musíte se vrátit do laboratoře a tudíž v souboru musí být číslo 10 které se do proměnné cast uloží. Jestli to nechápete, podívejte se do ukázkové hry, určitě to pochopíte lépe než z textu.
Jako ukázku jsem vytvořil menší hru, můžete si na ni vyzkoušet jak štítky, tak ukládání a načítání. Jestli chcete, vytvořte nějakou minihru kde využijete všechny rady a tipy, o kterých jste se v článku dočetli, určitě to budou zajímavé výtvory :).
Screen:
Zdroják: KLIK
Kompletní balíček
Na závěr dodávám kompletní balíček se zdrojovými soubory, obrázky, aplikacemi a souborem s obsahem článku, ovšem protože poznámkový blok nepřevádí obsah tagů [i] na kurzívu nebo [h2] na nadpisy, budete si muset designovou stránku představit :).
Stahuj: KLIK
Komentáře
Přidat nový
Pro přispívání musíte být přihlášen
Zapsal Firejs - 12.04.2011 21:23
Já zas nechápu, proč to tobě nefunguje...
Zapsal Dfire - 12.04.2011 17:07
nechápu jak se vám může spustit v tom zdrojáku vycentrování textu když tam chybí #include <string>
Zapsal chylex - 24.07.2010 15:09
Opraveno, ale v souboru ke stažení ta chyba pořád je, tak na to pozor ;).
Zapsal chylex - 24.07.2010 15:05
Heh, mě by zajímalo co jsem dělal, když jsem to psal O_o. Díky za upozornění, opravím.
Zapsal Firejs - 23.07.2010 20:55
Myslím, že se Chylex jen upsal... ale opravit by to mohl ;)
Zapsal 1UK45 - 21.07.2010 17:13
Jedna věc mě úplně bije do očí... a to
"void TretiMocnina(int cislo){
/*do promenne cislo se vlozi prvni argument*/
return cislo*cislo*cislo;
/*return vrací hodnotu*/
}".
Pokud je tam return, void se nepoužívá! V tomhle případě by bylo nejlepší použít int...
Zapsal chylex - 22.04.2010 09:42
Díky, zkusím to ve wxDev-C++ někde najít, zas vím něco nového :).
Zapsal Peping - 21.04.2010 12:35
IMHO na tu diakritiku je mnohem lepší řešení jednoduše změnit kódování kompilovaného souboru na Windowsovský konzolový (cp852). Jenom zjistit jak se to dělá ve vašem vývojovém prostředí. Ve Visual Studiu je to File>Advanced Save Options..



