VYSOKÁ ŠKOLA POLYTECHNICKÁ JIHLAVA Katedra elektrotechniky a informatiky
Vy t v o ř e n í a p l i k a c e p ro k o m p l e x n í n á v r h postavy v herním systému DRD+ bakalářská práce
Autor: Petr Obrdlík Vedoucí práce: PaeDr. František Smrčka, Ph.D. Jihlava 2012
Anotace V této práci je řešena problematika vytvoření aplikace pro automatickou a manuální genezi herní postavy v systému DRD+ a jednoduché databáze některých herních reálií. První část této práce obsahuje analýzu procesů používaných při návrhu postavy, výběr implementačního prostředí a návrh struktury aplikace. V druhé části jsou popsány některé funkce C#.Net, použité v aplikaci a představen dotazovací jazyk LINQ. Dále následuje popis struktury, funkce programu a popis některých důležitých tříd. Nakonec je krátce zmíněna databázová část aplikace. Ukázalo se, že zvolené implementační prostředí a navrhnutá struktura aplikace byla příhodná pro tento typ problému. Aplikace samotná se nachází na přiloženém datovém médiu jak ve formě zdrojového kódu, tak i instalačních souborů.
Klíčová slova DRD+, herní postava, dovednosti, schopnosti, C#.Net, LINQ
Annotation This work deals with a dilemma how to create an accurate application for automatic and manual genesis of the particular game-character in the DRD+ system and creation of some simple game realia databases. The first part of this work contains process analysis used for character drawing, the choice of surrounding implementation and a drawing of application structure. Within the second part there are specifications of certain C#.Net functions used in the application and the query language LINQ is also introduced. Thereafter there is the structure specification the system function and a description of some of the notable categories. Finally, the database part of application is mentioned briefly. It is clearly understandable that the chosen surrounding implementation and the drawing of application structure were selected correctly for this type of problem. The application itself can be found on the enclosed data-media not only in the form of source code but also in the form of installation files.
Key words DRD+, game-character, skills, abilities, C#.Net, LINQ
Poděkování Na tomto místě bych chtěl poděkovat PaeDr. Františkovi Smrčkovi, PhD., vedoucímu mé bakalářské práce, za pomoc a rady, které mi poskytl při konzultacích.
Prohlášení Prohlašuji, že předložená bakalářská práce je původní a zpracoval/a jsem ji samostatně. Prohlašuji, že citace použitých pramenů je úplná, že jsem v práci neporušil/a autorská práva (ve smyslu zákona č. 121/2000 Sb., o právu autorském, o právech souvisejících s právem autorským a o změně některých zákonů, v platném znění, dále též „AZ“). Souhlasím s umístěním bakalářské práce v knihovně VŠPJ a s jejím užitím k výuce nebo k vlastní vnitřní potřebě VŠPJ . Byl/a jsem seznámen/a s tím, že na mou bakalářskou práci se plně vztahuje AZ, zejména § 60 (školní dílo). Beru na vědomí, že VŠPJ má právo na uzavření licenční smlouvy o užití mé bakalářské práce a prohlašuji, že s o u h l a s í m s případným užitím mé bakalářské práce (prodej, zapůjčení apod.). Jsem si vědom/a toho, že užít své bakalářské práce či poskytnout licenci k jejímu využití mohu jen se souhlasem VŠPJ, která má právo ode mne požadovat přiměřený příspěvek na úhradu nákladů, vynaložených vysokou školou na vytvoření díla (až do jejich skutečné výše), z výdělku dosaženého v souvislosti s užitím díla či poskytnutím licence. V Jihlavě dne 30. 5. 2012 ...................................................... Podpis
Obsah 1
Úvod.......................................................................................................................... 8
2
Existují aplikace řešící problém složitého návrhu postavy v herním systému
DRD+? ............................................................................................................................ 10 3
Analýza a definice problému .................................................................................. 11 3.1
Specifikace požadavků ................................................................................... 11
3.2
Zmapování stávajících procesů návrhu postavy ............................................. 13
3.2.1
Hrubé schéma procesu ................................................................................ 13
3.2.2
Schéma návrhu postavy na 1. úrovni .......................................................... 14
3.2.3
Schéma inkrementace úrovně herní postavy .............................................. 17
3.2.4
ER Diagram geneze herní postavy.............................................................. 18 Návrh řešení .................................................................................................... 20
3.3
4
3.3.1
Volba implementačního prostředí ............................................................... 20
3.3.2
Volba databázového stroje .......................................................................... 21
3.3.3
Návrh řešení problémů vyplývajících z analýzy procesu ........................... 21
3.4
Návrh úpravy procesu geneze postavy ........................................................... 24
3.5
Návrh základní struktury programu ................................................................ 25
Popis řešení ............................................................................................................. 27 4.1
Některé použité funkce a nástroje z prostředí .NET Framework ................... 27
4.1.1
Prvky novějších verzí jazyka C# použité v aplikaci a vysvětlení jejich
funkcionality ........................................................................................................... 27 4.1.2
Dotazovací jazyk LINQ .............................................................................. 30
4.1.2.1
Co je to LINQ? .................................................................................. 30
4.1.2.2
Syntaxe LINQ .................................................................................... 31
4.1.2.3
LINQ to SQL ..................................................................................... 32
4.1.2.4
Datové entity ..................................................................................... 33
5
4.1.2.5
Dotazy a jejich provádění .................................................................. 34
4.1.2.6
Úprava záznamů v databázi ............................................................... 35
4.1.2.7
Zápis a mazání ................................................................................... 36
4.1.2.8
Úprava záznamu ................................................................................ 36
4.1.2.9
Dotazovací jazyk LINQ - shrnutí ...................................................... 36
4.2
Schéma struktury programu ............................................................................ 37
4.3
Popis úvodní obrazovky – Windows Form Class FHlavní ............................. 38
4.4
Statická třída Seznamy.................................................................................... 39
4.5
Zobrazení postavy – Windows Form Class FPostava .................................... 41
4.6
Abstraktní třída tpostava ................................................................................. 42
4.7
Třída povolání tbojovnik ................................................................................ 44
4.8
Vlastní dialogy, formulářové třídy pro obsluhu rozhraní databáze ................ 45
4.9
Komunikace mezi objekty .............................................................................. 45
4.10
Popis databázové části .................................................................................... 47
Testování aplikace .................................................................................................. 49 5.1
Stabilita a funkčnost aplikace ......................................................................... 49
5.2
Výkon aplikace ............................................................................................... 49
6
Srovnání s existujícími řešeními ............................................................................. 53
7
Závěr ....................................................................................................................... 54 Seznam použité literatury a elektronických zdrojů......................................... 56 Seznam obrázků .............................................................................................. 58 Přílohy............................................................................................................. 59
1
Úvod
Hra Dračí doupě plus1 (dále jen DRD+) je jednou z nemnoha původních českých her na hrdiny2. Kompletní příručka této hry se skládá z pěti knih a obsahuje poměrně detailní a svazující soubor pravidel, jejichž aplikace vede k vytvoření vskutku reálného dojmu z fiktivního herního světa a chování herních postav, ve srovnání s jinými systémy her na hrdiny. Tato detailnost pravidel sebou přináší několik zcela zásadních negativ, přičemž mezi největší z nich patří náročnost a zdlouhavost tvorby nové herní postavy. Avšak mezi silná pozitiva systému DRD+ lze zařadit soubor pravidel pro interakci mezi postavami. Tvůrci jednotlivých dobrodružství jsou tak nuceni ke dvěma extrémům při vytváření svých herních postav. Buď mohou strávit až několik hodin vytvářením detailní a uvěřitelné herní postavy dle pravidel DRD+, a pak budou schopni při hře využít skutečně veškerý herní potenciál takové postavy, anebo mohou postavu vytvořit odhadem jejích základních atributů a dovedností, což bývá častější způsob. Avšak při jiné, než slovní interakci takovéto postavy s hráči většinou dochází k tomu, že tvůrce hry3 je nucen začít listovat pravidly a dotvářet schopnosti postavy přímo při hře. Nejenže pak nedokáže využít všechny schopnosti, které takovéto postavě určují pravidla DRD+, ale hra samotná se hledáním v pravidlech zdržuje a působí rušivě na všechny účastníky hry. Cílem mé bakalářské práce je vytvoření aplikace, která napomůže k odstranění právě onoho zdlouhavého vytváření postavy pro DRD+ a zároveň umožní generování komplexní postavy na libovolné úrovni během pár vteřin4 a několika kliknutí myši, kdy drtivá většina informací potřebných pro tvorbu postavy je sice vytvářena čistě náhodně, avšak bude zde zachována i možnost potřebné informace vybrat ručně, a tím do značné míry eliminovat vliv náhody v návrhu herní postavy. V této aplikaci je možné taktéž 1
HOLUB Zbyněk et al. Dračí doupě Plus: Příručka Pána jeskyně. Ostrava, 2005. ISBN 80-85979-49-7. BUCHTA Jiří et al. Dračí doupě Plus: Příručka pro hráče. Ostrava, 2006. ISBN 80-85979-45-4. 2 Hra na hrdiny „… je druh hry, kde hráči zaujímají role fiktivních postav (role-playing – hraní rolí), které si podle daných pravidel vytvoří a za které v samotné hře jednají. Někdy je používán výraz charaktery podle anglického character, nejpoužívanější český překlad je asi postava.“ Wikipedie [online]. [cit. 2012-05-10]. URL:
. 3 Tvůrce hry DRD+ (označovaný jako Pán jeskyně) je člověk, který vytváří a dohlíží na herní svět, zajišťuje jeho dynamiku a rozhoduje o následcích činů vykonaných hráči. Mimo jiné také usměrňuje, kontroluje a přejímá zodpovědnost za chování postav, které do světa sám vkládá jako protivníky, nebo přátele postav hráčů. Wikipedie [online]. [cit. 2012-05-10]. URL: . 4 Rychlost automatického generování postavy záleží na několika různých faktorech. Více v kapitole o testování aplikace.
8
vytvořit postavu zcela ručně, s tím, že uživatel má nad tvorbou postavy téměř stoprocentní kontrolu a aplikace poskytuje jen podporu pro rychlejší tvorbu postavy bez listování tištěnými pravidly. Dále je možné vytvořenou postavu uložit do databáze postav a také vyexportovat do textového souboru. Aplikace dále obsahuje i jednoduchou databázi některých dalších herních reálií,5 jako jsou rostliny, knihy a zbraně. Tyto reálie je možné do databáze přidávat, mazat, upravovat či exportovat do textového souboru. Hlavní motivací pro výběr tohoto tématu byla hlavně snaha o rozšíření mých vědomostí v oblasti programování a o zvládnutí některého z moderních programovacích jazyků. V teoretické části mé bakalářské práce nejprve krátce nastíním stávající řešení jiných autorů, pak provedu krátkou analýzu návrhu postavy, dále učiním porovnání algoritmů návrhu postavy podle pravidel DRD+ a postupů použitých v mé aplikaci. Dále bude následovat krátký popis některých nástrojů nových funkcí programovacího jazyka C# a prostředí .NET Framework, popis samotné struktury programu, a budou zde také uvedeny i příklady a popis některých funkcí a metod použitých v mé aplikaci. Teoretická část bude zakončena uvedením několika poznatků z praktického využití mé aplikace.
5
Herní reálie – součást vymyšleného světa DRD+, zde použito ve smyslu fiktivních předmětů, rostlin.
9
2
Existují aplikace řešící problém složitého návrhu
postavy v herním systému DRD+? Takto zněla jedna z prvních otázek, kterou jsem si položil po prvním přečtení pravidel této hry. Po odpovědi na tuto otázku jsem intenzívně pátral na Internetu a na různých fórech skupin hráčů her na hrdiny. Výsledkem mého pátrání byl program s obligátním názvem DRD+,6 který umožňuje jen základní generování postavy bez dovedností a bez schopností povolání. Existuje několik dalších webových aplikací,7 které slouží pro podporu tvůrce hry při přípravě světa, jedná se většinou o generátory náhodných jmen, databázi postav nebo jiných herních reálií. Všechny tyto aplikace jsou volně šiřitelné, vytvořené v převážně většině samotnými hráči DRD+. Pro tvorbu komerční aplikace je cílová skupina hráčů této hry příliš malá (dle mých odhadů se bude jednat řádově o pár tisíc hráčů), a to je také jedním z hlavních důvodů, proč nebyla žádná jiná aplikace vytvořena.
6
Autorem aplikace je Michal Holub, rok posledního update aplikace je 2005. [cit. 2012-05-15]. Dostupné z: . 7 Pro příklad: Dračí doupě [online]. [cit. 2012-05-15]. URL: http://draci-doupe.timqui.net/jmena.html >. Tamurie — Dračí doupě [online]. [cit. 2012-05-15]. URL: .
10
3
Analýza a definice problému
Tvorbě mého programu předcházela důkladná analýza problémů, k jejichž řešení má daný program sloužit. Velkou výhodou je, že v tomto případě jsem zadavatelem, uživatelem a vývojářem software současně, čímž jsou zcela vyloučeny problémy s neurčitě definovaným zadáním či s dalšími možnými nedorozuměními.
3.1
Specifikace požadavků
Úplnou definici pro specifikaci požadavků na vyvíjený software najdeme mimo jiné v normě IEEE 830-1998.8 Avšak domnívám se, že vzhledem k rozsahu této normy, k požadované funkcionalitě software a k velikosti vývojového týmu, nebude nutné dodržet všechny požadavky této normy a rád bych ji použil pouze jako rámec, ze kterého vyberu některá hlediska pro dostatečnou specifikaci návrhu zadaného software. 1. Účelem navrhovaného systému je -
umožnit tvůrci hry v herním systému DRD+ operativně navrhnout a vygenerovat herní postavu zvolené rasy a pohlaví, na libovolné úrovni včetně dovedností a schopností povolání, tak aby splňovala pravidla herního systému DRD+,
-
umožnit ruční návrh takové postavy,
-
poskytovat informační podporu databází některých herních reálií.
2. Definice, zkratky a akronyma: -
herní postava – smyšlená osoba vytvořená dle pravidel herního systému DRD+,
-
úroveň postavy – určuje stupeň a množství znalostí postavy, obecně platí úměra mezi úrovní postavy a množstvím dovedností a schopností které jsou k ní přiřazena,
-
dovednosti, schopnosti postavy – soubor vlastností popisujících postavu, definovaných pravidly DRD+, dovednosti jsou obecné, například jízda na kole, schopnosti jsou speciální dovednosti typické pro určitá povolání, například programování.
8
Znění normy IEEE 830-1998 [online]. [cit. 2012-05-17]. URL:< http://www.slideshare.net/ahmedhasan/ieee-830-1998-software-requirements-specifications>.
11
3. Způsob použití Program bude používán na osobním počítači zpravidla bez přístupu k Internetu. 4. Uživatelské rozhraní – design Software musí být přehledný, není možné hledat v rozsáhlém menu, či nastavovat velké množství parametrů. Měl by implementovat grafické rozhraní podobné GUI9 operačního systému MS Windows. 5. Požadavky na výkon Je nutné, aby maximální čas nutný pro výpočet komplexní postavy včetně schopností povolání nepřesáhl jednu minutu. 6. Požadavky na software/hardware Program musí běžet na operačním systému MS Windows XP a MS Windows 7 32/64bit. Požadavky na hardware jsou omezeny jen operačním systémem. 7. Požadavky na zabezpečení Bez zvláštních požadavků na zabezpečení. 8. Požadavky na výstup Je požadován export vygenerované postavy do textového souboru a její uložení do databáze. Stejně tak i u ostatních herních reálií. 9. Požadavky na kvalifikaci obsluhy Základní
znalost
operačního
systému
MS
Windows,
orientace
v pravidlech DRD+. Odpověďmi na těchto pár základních otázek byly zřetelně nastaveny mantinely, ve kterých se budu pohybovat při dalších krocích této analýzy. Již teď je zřetelné, že zadání účelu navrhovaného software je příliš komplexní a bude nejlépe ho rozdělit na několik částí. Jednoduchá databáze herních reálií bude, s největší pravděpodobností, jednou z těchto možných, samostatně řešitelných úloh tohoto zadání. Domnívám se, že další analýza této části zadání není nutná, neboť řešení této úlohy je zcela zjevné. Rád bych se tedy v dalších oddílech této kapitoly věnoval analýze geneze herní postavy, pochopení procesů nutných k jejímu vytvoření, jejich zjednodušení a ke komputerizaci 9
Graphics user interface – grafické uživatelské rozhraní.
12
celého procesu. Předpokládám, že přesné hranice rozdělení jednotlivých částí tohoto problému budou zřejmé až v příštích oddílech této kapitoly.
3.2
Zmapování stávajících procesů návrhu postavy
Pro návrh jakéhokoliv software je nutná detailní znalost stávajících procesů a datových toků v té části problémové domény, kterou hodláme komputerizovat. Nejdříve je nutné vytvořit schéma procesu v tom nejhrubším možném rozlišení a teprve pak, bude-li to potřeba, pohled postupně zjemňovat, až dosáhneme takového stupně detailu, kdy bude nejen celý proces, ale i jeho menší části zřetelně identifikovatelné.
3.2.1 Hrubé schéma procesu
Obr. 1: Diagram procesu – Vytvoření herní postavy systému DRD+ na x-té úrovni
Z uvedeného procesního diagramu je jasně patrné, že na té nejvyšší možné úrovni se celý proces vytvoření postavy dělí na dvě základní části, přičemž první z nich je postup vedoucí k vytvoření kompletní herní postavy na 1. úrovni, druhou částí je pak proces zvednutí úrovně postavy, který je iterován tak dlouho, dokud hodnota úrovně postavy nedosáhne požadované výše. Rád bych tedy dále prozkoumal oba procesy odděleně, snad budou zřejmá další možná zjednodušení postupu geneze postavy. 13
3.2.2 Schéma návrhu postavy na 1. úrovni
Obr. 2: Diagram procesu – Vytvoření herní postavy systému DRD+ RD+ na 1. úrovni
Schéma tohoto procesu sice nejde do naprostého detailu, ale je již mnohem podrobnější. podrobn Přii bližším zkoumání začne za být zřejmé, ejmé, že i tento postup se dá s určitými obtížemi 14
rozdělit do několika navzájem souvisejících logických celků, tak jak je vidět na obrázku výše. Krátce tedy zhodnotím každý z těchto částí procesu: 1. Část procesu návrhu postavy V této části jsou jasné uživatelské vstupy týkající se volby rasy, pohlaví a povolání, tak jak je to definované v předchozí podkapitole v části, týkající se účelu navrhovaného software. Další informace potřebné pro vytvoření postavy budou získány z databázových tabulek převzatých z pravidel DRD+. 2. Část procesu návrhu postavy Tato část procesu obsahuje výběr tzv. zázemí postavy, proměnné, která určuje podíl jednotlivých složek atributů postavy. Zázemí by mělo být povinným uživatelským vstupem pro ruční návrh postavy, pro automatický návrh už jen pak volitelným. Dále následují jen výpočty hodnot
proměnných
dle
vzorců
obsažených
v pravidlech.
Naprogramování této části by mělo být poměrně snadné, jediný problém spatřuji ve způsobu volby přidělení oprav k vlastnostem, neboť zde bude nutné vybrat napevno jeden ze způsobů přidělování oprav, nebo oba způsoby nějakým vhodným způsobem zkombinovat. 3. Část procesu návrhu postavy V této části je obsaženo rozdělení bodů zázemí, pravidla tohoto rozdělení jsou naznačena ve schématu. Pro ruční návrh postavy bude nutné opět umožnit uživatelskou volbu tohoto rozdělení, přičemž pro automatický návrh postavy by mohly být tyto volby opět jen volitelné. Velkým problémem v této části procesu se jeví následné přidělování dovedností, které se má provádět s přihlédnutím k minulosti a původu smyšlené postavy. Pro automatický návrh postavy bude tedy nutné, vygenerovat minulost postavy, nebo najít jiné řešení pro logické přidělování jednotlivých dovedností postavy. Pro ruční návrh postavy se automaticky předpokládá, že jednotlivé dovednosti postavy budou vybírány uživatelem. 4. Část procesu návrhu postavy
15
Poslední oddíl v návrhu postavy by se v ještě podrobnějším pohledu dal rozdělit do dvou dalších částí, v první by byl obsažen výběr schopností povolání. Tyto schopnosti většinou pak závisí na úrovni, vlastnostech a dovednostech postavy, a právě také na předchozím výběru schopností povolání. V automatickém módu geneze postavy budou tyto vybírány programově, v ručním módu pak uživatelem. Úprava vlastností dle schopností povolání již proběhne automaticky v obou případech. Druhá část tohoto oddílu obsahuje nákup vybavení, což pro účely našeho návrhu postavy lze zredukovat na vybavení, které má nějaký vliv na atributy postavy, což jsou zbraně a zbroje. Je nutné, při automatickém přidělování jednotlivých položek vybavení, zohlednit majetek postavy a její dovednosti a schopnosti povolání. Pro ruční návrh postavy není potřeba klást žádná omezení. Věk postavy je částečně daný pravidly jen s malým možným rozptylem, lze ho také generovat automaticky. Ovšem jméno, jako identifikátor postavy, bude nutné zadat uživatelem, přičemž psychické vlastnosti postavy, ačkoliv je pravidla definují jako nedílnou součást návrhu postavy pro hráče, jsou pro náš účel návrhu postavy jako herní reálie bezpředmětné. Obecně lze zkonstatovat, že proces návrhu postavy se dá v obou podobách, jak ruční, tak i automatické, bez větších problémů převzít i do schématu programu, avšak s dvěma výjimkami, a to automatického přiřazení dovedností postavy a automatického nákupu vybavení. Tyto dva problémy spolu souvisí a já bych se k nástinu jejich možného řešení vrátil v některé z dalších kapitol.
16
3.2.3 Schéma inkrementace úrovně herní postavy
Obr. 3: Diagram procesu – Vytvoření herní postavy systému DRD+ o jednu úroveň
17
Schéma postupu postavy o úroveň je na první pohled jednodušší, než schéma procesu vytvoření postavy. V jeho horní polovině se nachází snadno řešitelná inkrementace hlavních a vedlejších vlastností, kterou by neměl být problém technicky přepsat do kódu programu. Při automatickém návrhu postavy, by se ovšem mohlo jevit jako obtížné právě určení vlastnosti, která se bude inkrementovat. V dalším kroku se nachází opět výběr dovedností postavy, stejně jako v předchozím schématu by měly mít automaticky vybrané dovednosti návaznost na minulost a původ postavy. Rád bych se k návrhu řešení tohoto problému vrátil v dalších kapitolách. V případě ručního návrhu budou vlastnosti inkrementovány ručně s automatickou aplikací omezení vyplývajících z pravidel herního systému, stejně tak bude ošetřen i ruční výběr dovedností. Dále se nachází opět jen prosté uplatnění mechanismů pravidel DRD+, které jsou poměrně snadno převoditelné do podoby programu. Jen v případě ručního návrhu bude opět výběr schopností povolání proveden uživatelem za současného uplatnění herních pravidel.
3.2.4 ER Diagram geneze herní postavy Pravidla DRD+ obsahují poměrně velké množství různých tabulek, které se používají při tvorbě postavy a postupu po úrovních. A zároveň se domnívám, že stále není zjevná budoucí struktura části programu sloužícího k návrhu herní postavy. Rozhodl jsem se tedy vytvořit ze všech tabulek obsahujících informace potřebné k jejímu vytvoření Entity Relationship diagram.10 Tyto tabulky bude nutné převést do digitální podoby a aplikovat v navrhovaném programu. Při tvorbě ER diagramu jsem došel k závěru, že některé tabulky, které obsahují pravidla, jsou ve stávající podobě nepřevoditelné do datových tabulek databázového stroje a budou muset být upraveny. Mnoho z nich obsahuje velké množství atributů,
10
Entity-relationship model (ERM) lze v softwarovém inženýrství využít právě pro abstraktní a konceptuální znázornění dat. Wikipedie [online].[cit. 2012-05-17] URL: .
18
které jsou pro přehled struktury datových entit irelevantní, a proto jsem je nahradil jedním atributem s třemi tečkami.
Obr. 4: Entity – relationship diagram tvorby postavy včetně povolání.
Jak je z uvedeného diagramu patrné, datová entita postava je základním kamenem pro komplexní návrh postavy v DRD+. K ní se pak logicky pojí ostatní entity. Vzhledem 19
k množství různých povolání a jejich vlastností by bylo velice obtížné zobrazit v tomto diagramu všechna ostatní povolání, a proto vybral povolání bojovník, které budu jako jediné realizovat v plné míře.
Důvod tohoto rozhodnutí objasním samozřejmě
v příštích kapitolách.
3.3
Návrh řešení
3.3.1 Volba implementačního prostředí Na moji volbu implementačního prostředí se dá aplikovat několik různých hledisek: 1. Hledisko vycházející ze specifikace požadavků na vyvíjený software11 -
programové rozhraní by mělo být podobné GUI MS Windows,
-
aplikace musí být kompatibilní s MS Windows XP a MS Windows 7 32/64bit,
-
aplikace bude provozována na osobním počítači bez připojení k Internetu.
2.
Ceny prostředí a licence naprogramované aplikace -
co nejnižší, pokud možno nulové náklady na pořízení implementačního prostředí s plnou funkcionalitou výsledného software a bez omezení případného poskytování licence navrhovaného software třetím stranám.
3. Snadnost přístupu k datovým zdrojům -
implementační prostředí by mělo v ideálním případě obsahovat silnou podporu některého z běžných databázových strojů, s pokud možno jednoduchým přístupem k datům.
4. Mé vlastní vědomosti a znalosti -
v prostoru nabídek jednotlivých implementačních prostředí jsem byl nucen se zorientovat, přičemž bylo zcela evidentní, že programovacím jazykem bude muset být některý z následujících: C,C++, Visual C++, PHP nebo Visual Basic.
Pokud shrnu všechna tato hlediska, tak v první řadě jsem vyloučil programovací jazyk C, jelikož nepodporuje OOP12 a podpora GUI je u něj velice problematická, stejně tak je poměrně složitý i přístup k databázovým strojům. Z velice podobných důvodů nebylo 11 12
viz kapitola 2.1 Specifikace požadavků. Object-oriented programming - Objektově Orientované programování
20
vhodné ani použití nativního C++. Vzhledem k tomu, že k provozu aplikace nebude k dispozici Internet, zavrhl jsem PHP i ASP.NET. Zbyly tedy Visual C++ a Visual Basic, pokud zohledníme všechna hlediska, tak je jasnou volbou implementační prostředí Microsoft Visual Studio v Express Edition verzi. Z programovacích jazyků nabízených tímto implementačním prostředím jsem si nakonec překvapivě vybral Visual C# Express. Je v určitých ohledech jednodušší než Visual C++ Express a má silnou nativní podporu OOP.
3.3.2 Volba databázového stroje Vzhledem k tomu, že Microsoft Visual C# Express podporuje nativně jen Microsoft Access Database File, SQL Server Compact Edition a SQL Server Database File, podpora ostatních databázových strojů je možná při použití knihoven třetích stran, nebo pokud se jedná o vzdálený SQL server, při naprogramování rozhraní SQL serveru v IDE13 Microsoft Visual Web Developer,14 kde i v Express verzi je přímá podpora vzdáleného SQL serveru. Ovšem vzhledem k tomu, že databázové rozhraní SQL Server Database File obsahuje dostatečnou funkcionalitu pro implementaci mého programu, a navíc umožňuje v případě potřeby připojení i do jiných nástrojů umožňujících komunikaci s Microsoft SQL Serverem, byl mnou tedy vybrán jako datové úložiště SQL Server Database File.
3.3.3 Návrh řešení problémů vyplývajících z analýzy procesu Většina jednotlivých kroků v procesu návrhu herní postavy i v procesu postupu postavy o úroveň se dá vyřešit prostou aplikací mechanismů herních pravidel, případně mírnou modifikací některých kroků. Ovšem některé z částí tohoto procesu při automatické genezi postavy jsou odlišného charakteru a vyžadují další zkoumání, neboť jejich řešení musí být jasné před tím, než se přikročí k samotnému psaní kódu aplikace.
13
Integrated Development Enviroment – integrované vývojové prostředí Visual Web Developer Express [online]. [cit. 2012-05-17]. Dostupné z: URL: .
14
21
Jedná se o: 1. Způsob přičítání oprav k vlastnostem v 2. části schématu procesu návrhu postavy. Zde jsou v pravidlech k dispozici dva způsoby přičtení oprav k základním vlastnostem. První z nich spočívá v přičtení hodnot k jednotlivým vlastnostem úvahou člověka, který postavu vytváří, a druhý je zcela podřízen náhodě. Oba způsoby dávají přibližně stejné hodnoty, náhodný způsob má samozřejmě větší odchylky přidělených bodů oběma směry, což může být na nižších úrovních postavy problémem pro hru v případě interakce s některou z hráčských postav. Proto jsem se rozhodl oba způsoby zkombinovat, přičemž je stále přičítán stejný počet bodů v závislosti na zázemí postavy, avšak s tou podmínkou, že vlastnosti, do kterých budou body přiřazeny, jsou určovány víceméně náhodně. Mechanismy pravidel touto volbou neporušuji, protože dostávám stejné nebo velice podobné výsledky jako u přiřazení oprav úvahou hráče. Navíc jsou postavy vznikající tímto způsobem poměrně vyrovnané, bez velkých výkyvů hodnoty vlastností. 2. Způsob určení, která ze základních vlastností bude inkrementována, se týká 2. části schématu procesu návrhu postavy i schématu postupu o úroveň. V tomto případě jsem, stejně jako v minulém, použil náhodné přidělení pro vlastnosti, které nejsou důležité pro povolání postavy. Důležité, tzv. hlavní vlastnosti, se přidělují na základě výběru schopnosti příslušného povolání. 3. Automatické přiřazení dovedností postavy tvoří 3. část schématu návrhu postavy a ve schématu postupu postavy o úroveň. Vzhledem k tomu, že přidělení dovedností postavy musí brát v úvahu minulost té konkrétní postavy a její původ, tak řešení tohoto problému nebylo od počátku zcela jasné. Jelikož je svět, pro který se postavy generují zcela fiktivní, s vlastními přírodními a fyzikálními zákony, stejně tak i státní zřízení a sociální skladba společnosti se mnoho nepodobá realitě, tak je těžko možné aplikovat na populaci tohoto fiktivního světa, byť i upravené, sociodemografické15charakteristiky světa reálného. Navíc ani to by neřešilo problém s návazností přiřazených dovedností na historii postavy. 15
K této problematice více: Wikipedia [online]. [cit. 2012-05-17]. URL< http://en.wikipedia.org/wiki/Demographics>.
22
Ovšem, protože se jedná o genezi čistě fiktivní postavy v čistě fiktivním světě, rozhodl jsem se tento problém vyřešit tak, že do procesu geneze postavy přidám i její historii. Přičemž jsem vycházel z myšlenky, že jedním z hlavních faktorů určujícího míru socializace postavy a tím i naučených dovedností s ní spojených je prostředí, ve kterém se pohybuje. Proto bude možné na hlavním formuláři návrhu postavy vybrat prostředí, ve kterém se postava pohybovala a jakou poměrnou část svého života v tom konkrétním prostředí strávila. S přihlédnutím k tomu, zda šlo o městskou aglomeraci nebo venkov. Pokud nebude prostředí vybráno ručně, bude se generovat automaticky náhodně a na jeho základě pak proběhne opět náhodné přidělení jednotlivých dovedností. Poslední částí řešení tohoto problému je propojení jednotlivých dovedností s určitým prostředím. Jako první možnost mě napadla seskupit dovednosti do několika oblastí a pro každou z nich vytvořit právě takovou sociodemografickou charakteristiku, která by zohledňovala výskyt dané skupiny dovedností u fiktivní populace v konkrétním prostředí s přihlédnutím k původu postavy. Bohužel, jak se později ukázalo, nezohledňovalo toto uspořádání míru obtížnosti získání vyšších stupňů dovedností a poskytovalo jen malou variabilitu při budoucím přidávání dalších dovedností. Proto byla sociodemografická charakteristika vytvořena pro každou dovednost a každý její stupeň zvlášť. 4. Nákup a výběr vybavení – zbraní a zbrojí, poslední část schématu návrhu. Nákup vybavení souvisí s majetkem, neboť každá postava získá vždy nějaký hned při svém vytvoření, pro lepší uvěřitelnost postavy je nutné, aby byl majetek generován i při přestupu na vyšší úroveň a zbraně a zbroje byly „nakupovány“ až na konci geneze postavy. Vzhledem k tomu, že v systému DRD+ existuje několik různých typů zbraní a zbrojí tak i pro automatickou volbu druhu zbraně bude nutné jejich výběr nechat až na konec celého vytvoření herní postavy, protože při výběru zbraně hraje roli to, zda s ní postava umí zacházet – tedy výběr příslušné dovednosti – a zda ji podporují schopnosti povolání. Bude tedy nutné vytvořit proměnnou, 23
kam se bude ukládat preference druhu zbraně a zbroje na základě schopností povolání a dovedností. Poté, dle této proměnné, bude vybíráno náhodně z daného typu zbraně. Všechny tyto problémy zmíněné výše mají jednoho společného jmenovatele, tak jak je definují pravidla. Tímto společným jmenovatelem jsou věci, které by měl volit člověk při vytváření postavy. Z toho je jasné, že jakékoliv řešení automatického návrhu postavy, při které nebude možné použít lidskou, či umělou inteligenci, bude nějakým způsobem nedokonalé. Mým cílem je tedy tyto nedokonalosti zamaskovat takovým způsobem, aby postava automaticky vygenerovaná navrhovanou aplikací byla stále pro ostatní hráče uvěřitelná a neobsahovala logické chyby.
3.4
Návrh úpravy procesu geneze postavy
Obr. 5: Schéma úpravy procesu pro návrh aplikace
Jak již bylo uvedeno v předchozí kapitole, některé části návrhu postavy jsou silně závislé na lidské úvaze a pro jejich automatické generování bylo nutné upravit celý proces geneze postavy. 24
Očekávanou výhodou této změny je to, že automaticky vygenerovaná postava nebude obsahovat nelogické volby dovedností, schopností a vybavení, a pravděpodobně se jedná o podstatné zjednodušení při výběru zbraní a zbroje postavy. Předpokládanou nevýhodou tohoto uspořádání bude větší komplikovanost návrhu povolání a také to, že bude nutné vytvořit velkou část funkcí zvlášť pro ruční a automatický návrh postavy. Vzhledem k požadovanému účelu navrhované aplikace je tato změna jasnou volbou.
3.5
Návrh základní struktury programu
Jelikož vybrané implementační prostředí obsahuje silnou nativní podporu OOP, využiji toho a navrhnu strukturu programu jako soustavu jednotlivých tříd objektů. Pokud se podívám zpět do kapitoly 2.2.4 na ER diagram geneze herní postavy, tak je jasně patrné, že datová entita postava je, logicky, klíčovým bodem pro všechny informace potřebné pro genezi nové postavy. V návaznosti na tuto skutečnost by třída postava měla být i základním stavebním kamenem mé aplikace, abstraktní třídou, která bude nést všechny informace společné pro všechna povolání a metody potřebné pro vytvoření postavy a postup po úrovních. Třídy jednotlivých povolání budou jejími potomky a budou aplikovat převážně jen genezi schopností povolání a zpětně modifikovat atributy postavy. Co se týče ostatních tříd potřebných pro obsluhu jednotlivých databází herních reálií, tak ty budou samostatné a budou obsluhovat databázové operace a export dat do textového souboru. Nicméně plánované schéma aplikace je názorně uvedeno na obrázku níže:
25
Obr. 6: Návrh struktury programu
Na schématu jsou uvedeny také základní formulářové třídy, hlavní formulář pro obsluhu programu a formulář zobrazující vygenerovanou postavu, nebo umožňující ruční návrh postavy. Přerušované čáry vedoucí od a k těmto formulářovým třídám naznačují logickou strukturu programu, kde budou instancionovány jednotlivé objekty. Z důvodu přehlednosti schématu jsem se zde dopustil jedné nepřesnosti – abstraktní třída nemůže již z principu věci vytvářet instance, a proto by ona přerušovaná čára měla být vedena ke všem postavě podřízeným třídám. Co se týče ukládání postavy včetně povolání do databáze a jejího exportu do textového souboru, což je požadované v zadání, nepředpokládám, že bude nutné vytvořit speciální třídu pro tyto účely.
26
4
Popis řešení
V této části mé bakalářské práce bych chtěl nejprve představit několik poměrně nových funkcí jazyka C# používaných v mé aplikaci a představit dotazovací jazyk LINQ, který ve svém řešení také používám. Mohlo by se zdát, že tyto informace o programovacích prostředcích s uvedením některých funkcí, nejsou pro popis mého řešení zadaného problému nijak důležité, ale domnívám se, že díky pochopení některých vlastností dotazovacího jazyka LINQ bude důvod odlišnosti struktury mé aplikace od jejího návrhu zcela zjevný. Poté teprve bude následovat vysvětlení struktury mého programu a její porovnání s návrhem, dále zde bude uveden popis hlavních formulářů používaných v mé aplikaci, krátký popis hlavních tříd a nakonec bude následovat část popisující některé datové tabulky používané v mé aplikaci.
4.1
Některé použité funkce a nástroje z prostředí .NET Framework
V této kapitole bych se rád vyhnul obligátnímu popisování prostředí Microsoft .NET Framework či MS SQL Server Express, stejně tak jako standardním třídám a funkcím používaných již v předchozích verzích (1.0 a 2.0) jazyka C#, neboť se domnívám, že tato problematika je dostatečně známá a zpracovaná. Rád bych ovšem uvedl některé případy, kdy ve svém kódu používám vymoženosti verzí jazyka C# 3.0 až 4.0 a také bych se rád zmínil o poměrně nové součásti programovacích jazyků C# a Visual Basic, a to o dotazovacím jazyku LINQ.
4.1.1 Prvky novějších verzí jazyka C# použité v aplikaci a vysvětlení jejich funkcionality Jednou z novinek ve funkcionalitě programovacího jazyka C# je lokální odvozování typů, což znamená, že lze na lokální úrovni použít nespecifický typ proměnné s klíčovým slovem var. Použití na lokální úrovni znamená, že nelze tuto proměnnou aplikovat jako člen nebo parametr metody. Ve své práci tento typ proměnné používám většinou při ukládání výsledků databázových dotazů. var x = this.retezec_vybaveni(parametry, 0, omezeni, 0);
ukázka použití nespecifikovaného typu
27
Mohlo by se zdát, že použití typu var je ekvivalentní s použitím typu object, ale opak je pravdou. Při použití typu object musí dojít k zabalení instance dané proměnné (boxing) a při jejím použití zase k rozbalení (unboxing), přičemž navíc při jejím opětovném použití je v případě typu object nutné proměnnou přetypovat, pokud je vyžadována práce s konkrétním typem.16 Ve verzi jazyka C# 3.0 se také objevila implementace zkrácené syntaxe anonymních metod, tzv. lambda výrazů. Jedná se v podstatě jen o „kosmetickou“ změnu, která opět zefektivnila psaní kódu v jazyce C#.17 var nablizko = Seznamy.dc.Zbrane_nablizkos.Single(x => x.Nazev.Trim() == zbran);
ukázka použití lambda výrazu ve formě tzv. predikátu
Lambda výraz ve výše uvedené ukázce kódu je reprezentován výrazem x => x.Nazev.Trim() == zbran, dal by se přeložit jako každé x, jehož hodnota metody Nazev se rovná proměnné s názvem zbran. Je to jeden ze dvou speciálních případů lambda výrazu, tzv. predikát, který má za úkol filtrovat prvky. Druhé speciální použití lambda funkce je projekce, což je lambda funkce, která vrací typ odlišný od typu svého parametru.18 x=>x.Count; ukázka lambda výrazu ve formě projekce
Nejčastější použití lambda výrazů je při volání metody, kdy lambda výraz předává, mění, nebo filtruje jeden z parametrů metody, jak je to vidět v předposlední ukázce kódu.19 Ve verzi jazyka 3.0 došlo mimo jiné také k zavedení kratší syntaxe inicializace objektu, jehož výhodou je to, že lze psát inicializační řetězec třídy přímo do výrazu, aniž by bylo nutno používat odlišné příkazy.20 Herbs_table herb = new Herbs_table { Nazev = TBNazev.Text.Trim(), Obdobi_kvetu = TBObdobi.Text.Trim(), Popis = RTBPopis.Text.Trim()};
ukázka zkrácené inicializace objektu
16
PIALORSI, Paolo-RUSSO, Marco. Microsoft LINQ: Kompletní průvodce programátora. Brno, 2009. ISBN 978-80-251-2735-3, s. 557. (Dále jen: PIALORSI-RUSSO. Microsoft LINQ.) 17 Tamtéž, s. 559. 18 Tamtéž, s. 562. 19 Tamtéž, s. 562. 20 Tamtéž, s. 571.
28
Při takovém způsobu inicializace objektu, jaká je uvedena v ukázce se nejprve volá implicitní konstruktor, poté se přiřazují hodnoty jednotlivým vlastnostem třídy. Celé to probíhá tak, že se nejprve vytvoří dočasná proměnná objektu a teprve po dokončení inicializace je její obsah zkopírován do příslušné proměnné, přičemž se objekt stává dostupným až po tomto procesu. Tento způsob by mohl teoreticky vytvářet problémy v případě iniciování velkého množství proměnných najednou, je totiž díky kopírování nepatrně pomalejší, než tradiční způsob. Na druhou stranu, je ovšem tento zápis mimo jiné i velkým přínosem pro přehlednost kódu.21 Pokud bychom chtěli při zkrácené inicializaci volat jiný, než implicitní bezparametrický konstruktor, tak je zapotřebí jej zavolat před uvedením ostatních parametrů ve složených závorkách,22 jako například: Herbs_table herb = new Herbs_table(TBNazev.Text.Trim()) {Obdobi_kvetu = TBObdobi.Text.Trim(), Popis = RTBPopis.Text.Trim()};
ukázka inicializace objektu s použitím ne výchozího konstruktoru
Stejnou syntaxi je možné použít i pro generické kolekce: public static Dictionary<string, int> Default = new Dictionary<string, int>{ {"Nic", -1 }};
ukázka inicializace kolekce
V tomto případě je sice inicializační element jen jeden, ale princip inicializace zůstává pro jejich libovolný počet stejný. Pro každý z elementů ve složených závorkách se zavolá metoda Add dané kolekce, přičemž jedinou nutnou podmínkou je, aby daná třída implementovala IEnumerable.
rozhraní
System.Collections.Generic.ICollection
nebo
23
Stejný princip inicializace lze použít i pro anonymní typy: var zbran_nablizko = (from…
...select new { bz.Nazev, bz.Cena }).Distinct();
ukázka inicializace anonymního typu
V tomto případě překladač vygeneruje novou třídu s názvem zbran_nablizko, jejímiž členy budou dvě proměnné, jejichž název a typ bude odvozen z inicializátoru objektu. 21
PIALORSI-RUSSO. Microsoft LINQ, s. 571. Tamtéž, s. 571. 23 Tamtéž, s. 573. 22
29
Již z principu věci je jasné, že takto vytvořená instance třídy bude neměnná, její proměnné budou poskytovat přístup jen pro čtení.24
4.1.2 Dotazovací jazyk LINQ 4.1.2.1 Co je to LINQ? Dotazovací jazyk - LINQ25 byl poprvé představen v roce 2005, tvoří tedy součást Microsoft .NET od verze 3.5. Přesná definice tohoto pojmu zní: „LINQ je programovací model, který zavádí dotazy jako prvořadý princip do všech jazyků Microsoft .NET. LINQ nabízí metodologii, která zjednodušuje a sjednocuje implementaci libovolného přístupu k datům.“26 Úplná podpora LINQ však vyžaduje určitá rozšíření jazyka, z nichž nejčastěji používaná jsem představil v minulé kapitole. To, že je dotazovací jazyk LINQ opravdu téměř všestranný a že moc nezáleží na tom, kde se uložená data nacházejí, dokazuje tento výčet základních implementací jazyka LINQ od Microsoftu, které slouží pro přístup k několika datovým zdrojům:27 LINQ pro objekty LINQ pro ADO.NET
LINQ pro SQL
LINQ pro datové sady
LINQ pro entity
LINQ pro XML Z tohoto výčtu je zcela jasné, že v jazyce C# snad neexistuje oblast, kde by nebylo možné použít dotazovací jazyk LINQ. Při dodržení určitých pravidel se může zdrojem dat pro LINQ stát i uživatelská třída, stačí jenom, když implementuje rozhraní System.Collections.IEnumerable
nebo
System.Collections.Generic.IEnumerable,
rozhraní
odvozená,
jako
jsou
System.Collection.ICollection
nebo
System.Collections.Generic.ICollection.28
24
PIALORSI-RUSSO. Microsoft LINQ, s. 575-576. LINQ je zkratkou slova Language Integrated Query. Tamtéž, s. 23. 26 Tamtéž, s. 23. 27 Tamtéž, s. 24. 28 VIRIUS, Miroslav. C# 2010: Hotová řešení. Brno, 2012. ISBN 978-80-251-3730-7, s. 362. (Dále jen: VIRIUS. C# 2010.) 25
30
4.1.2.2 Syntaxe LINQ Syntaxe dotazů jazyka LINQ se nazývá dotazovací výraz, a dá se velmi zjednodušeně přirovnat k syntaxi SQL dotazů, jak je vidět na tomto kódu: from x in Seznamy.dc.Dovednosti_fulls where x.Nazev != null select x.Nazev.Trim()
ukázka syntaxe LINQ dotazu
Zcela zásadním rozdílem, který je patrný na první pohled, je to, že operátor select je proti zvyklostem syntaxe SQL dotazů na samém konci dotazovacího výrazu. Je to dané tím, že LINQ funguje už z principu na jiné bázi než SQL dotazy. Tato problematika bude jasnější poté, co vysvětlím ostatní operátory dotazovacího výrazu. První klíčové slovo je klauzule from, jež představuje deklaraci pomocné proměnné. Pokud bude uveden pouze identifikátor této proměnné bez typu, pak překladač typ dovodí z typu zdroje uvedeného za klíčovým slovem in tak, jak je to vidět v uvedeném příkladu.29 Klíčové slovo where udává filtrovací podmínku, která je použita na datový zdroj. Výraz za klíčovým slovem where je právě oním predikátem, podle kterého se z datového zdroje vyfiltrují jen ty položky, které splňují podmínku uvedenou v predikátu. Jako poslední následuje klauzule select, která určuje, co bude vybráno z množiny výsledků předchozích výrazů a podmínek.30 Jak bylo uvedeno v předchozí kapitole, je možné za pomoci LINQu dotazovat všechny objekty, které implementují rozhraní IEnumerable nebo ICollection. Zde se podmínka where překládá na volání rozšiřující metody Where třídy IEnumerable, stejně tak se klauzule select překládá na rozšiřující metodu stejné třídy nazvanou Select, a proto je možný i tento zápis výrazu dotazu:31 (Seznamy.dc.Dovednosti_fulls.Where(x=>x.Druh=='F').Select(x=> x.Nazev.Trim())
Ukázka LINQ dotazu pomocí rozšiřujících metod
Mohlo by se tedy zdát, že použití dotazu skládajícího se z rozšiřujících metod je jednodušší a dokonce snad i rychlejší, jelikož kompilátor C#, stejně jako kompilátor
29
VIRIUS. C# 2010, s. 362. PIALORSI-RUSSO. Microsoft LINQ, s. 45-49. 31 Tamtéž, s. 43-44. 30
31
Visual Basicu, překládá dotazové výrazy LINQ zapsané pomocí klíčových slov na dotazy zapsané pomocí rozšiřujících metod.32 Toto tvrzení bude platit, ale jen pro jednoduché výrazy. Pokud budeme například potřebovat získat data ze dvou různých zdrojů, tak napsat odpovídající výraz pomocí rozšiřujících metod by bylo opravdu zdlouhavé a náročné, kdežto použítí více klauzulí from definující proměnné z více různých zdrojů dat, je dle mého mínění elegantnější a časově méně náročné. Uvedená klíčová slova nejsou, samozřejmě, kompletním výčtem možností jazyka LINQ. Tvoří jen opravdový základ, bez jehož znalosti nelze LINQ vůbec použít. Jen pro příklad lze jako další klíčová slova uvést klauzule join, orderby, let, group nebo into.33 Syntaxe pro všechny moduly jazyka LINQ je velmi podobná, respektive liší se jen přítomností, či nepřítomností několika funkcí. Ovšem výše uvedený základ by měl platit pro všechny aplikace jazyka LINQ. 4.1.2.3 LINQ to SQL Ve své práci používám zejména modul LINQ to SQL, a proto bych se o něm rád zmínil podrobněji. LINQ to SQL nabízí, jak už jeho název napovídá, funkcionalitu dotazování do relační databáze MS SQL Server a objektový model vycházející z dostupných entit. V podstatě se jedná o jakousi tenkou vrstvu objektů nad relačními daty. Dotazy v jazyce LINQ směřující do relační databáze jsou provedeny nejprve nad touto vrstvou objektů, odkud je pak stroj LINQ pro SQL převádí na dotazy SQL. Je podporován MS SQL Server od verze 2000 a MS SQL Server Compact počínaje verzí 3.5.34
32
PIALORSI-RUSSO. Microsoft LINQ, s. 45. Tamtéž, s. 49-56. 34 Tamtéž, s. 115. 33
32
4.1.2.4 Datové entity Všechny datové tabulky z relační databáze, nad kterými chceme provádět operace, je z důvodů zřejmých z obsahu minulých kapitol „…nutné popsat příslušnými metadaty, navázanými na definice tříd.“35 Třída v tomto kontextu popisuje jen jeden jediný řádek příslušné tabulky, jejíž datové členy jsou jednotlivé sloupce příslušné tabulky. Pro dotazy LINQ je možné používat pouze popsaná pole.36 public System.Data.Linq.Table<Majetek> Majeteks [global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.Majetek")] public partial class Majetek : INotifyPropertyChanging, INotifyPropertyChanged { private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty); private int _Body; private int _Majetek1; #region Extensibility Method Definitions public Majetek() { OnCreated(); } [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Body", DbType="Int NOT NULL", IsPrimaryKey=true)] public int Body { get set } [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Majetek1", DbType="Int NOT NULL")] public int Majetek1 { get set } public event PropertyChangingEventHandler PropertyChanging; public event PropertyChangedEventHandler PropertyChanged; protected virtual void SendPropertyChanging() protected virtual void SendPropertyChanged(String propertyName) }
Ukázka deklarace třídy tabulky majetek (zkráceno)
V předchozích kapitolách bylo řečeno, že pro dotazy prováděné v jazyce LINQ je potřeba, aby daný objekt podporoval rozhraní IEnumerable, nicméně LINQ pro
35 36
PIALORSI-RUSSO. Microsoft LINQ, s. 116 Tamtéž, s. 116.
33
SQL potřebuje implementace rozšiřujících metod v jiné podobě, a tak je nutné použít objekt s rozhraním IQueryable, a právě toto rozhraní třída Table obsahuje.37 Je zjevné, že při dotazování se na data prezentované objektem, je potřeba mít k dispozici instanci tohoto objektu. K tomu účelu slouží instance třídy DataContext, která zajišťuje spojení mezi prostředím LINQ a relační databází.38 DataClasses1DataContext dc = new DataClasses1DataContext();
Ukázka založení instance třídy DataContext
Je tedy zřejmé, že bez instance třídy DataContext není možný přístup k entitám tabulek, a je dobrou praxí zakládat novou instanci třídy DataContext při každém požadavku na spojení do databáze.39 4.1.2.5 Dotazy a jejich provádění LINQ používá tzv. odložené provádění dotazů, což znamená, že dotaz není proveden v okamžiku sestavení jeho definice, ale až v tom okamžiku, kdy jsou data použita v právě prováděném kódu. Výhodou této vlastnosti je možnost jedné definice dotazu a jeho následné použití při několika různých operacích bez opětovné definice. Ovšem nevýhoda této funkcionality se projeví v okamžiku, kdy chceme procházet výsledky dotazu pomocí programových cyklů, neboť při každém opakování cyklu dochází k opětovnému provedení dotazu. Z hlediska výkonu aplikace je tedy mnohem lepší použít některé z tzv. převodních operátorů, které dokážou výsledek dotazu převést na generickou kolekci, např. To.Array(), To.List(). Ovšem to je výhodné jen v tom případě, pokud nám nezáleží na aktuálnosti dat, nebo pokud nehrozí, že by data mohla být během provádění cyklu v databázi změněna jiným uživatelem nebo vláknem programu.40 (Seznamy.dc.Dovednosti_fulls.Where(x=>x.Druh=='F').Select(x=> x.Nazev.Trim())).ToList()
Ukázka použití převodního operátoru
37
PIALORSI-RUSSO. Microsoft LINQ, s. 115-116. Tamtéž, s. 117. 39 Tamtéž, s. 184. 40 Tamtéž, s. 58. 38
34
Vzhledem k odlišné implementaci rozšiřujících metod pro dotazy v LINQ to SQL bych rád představil metodu Single, kterou taktéž velice často používám ve své bakalářské práci: Seznamy.dc.Tabulka_postihu_za_strelnou_zbrans.Single(x => x.Chybejici_sila == stupen);
Ukázka použití syntaxe rozšiřující metody Single Funkcionalita rozšiřující metody Single spočívá v tom, že z tabulky vybere právě jeden řádek, který vyhovuje zadané podmínce, která je v tomto případě předaná jako lambda výraz v parametru volání metody. Pokud tomuto predikátu vyhovuje více záznamů než jeden, bude vytvořena chybová výjimka. Výhodou této metody je, že vrací vlastně instanci třídy tabulky představující právě jeden řádek, a proto je poměrně jednoduché s takovým silně typovým výsledkem dotazu pracovat. 4.1.2.6 Úprava záznamů v databázi Základní operace zahrnující vytvoření, mazání nebo úpravu záznamu v tabulce jsou poměrně jednoduché a to zejména díky tomu, že každý řádek tabulky je reprezentován instancí třídy daného typu: Herbs_table herb = new Herbs_table(); herb.Nazev = TBNazev.Text.Trim(); herb.Obdobi_kvetu = TBObdobi.Text.Trim(); herb.Popis = RTBPopis.Text.Trim(); herb.Obrazek=imago; herb.Prostredi = TBProstredi.Text; herb.Ucinek = RTBUcinek.Text; herb.Ucinna_cast = TBUcinna.Text;
Ukázka založení nové instance třídy Herbs table, která reprezentuje řádek v tabulce Herbs table
Jednotlivé členy třídy, jako jsou Nazev, Obdobi_kvetu apod. jsou vlastně jednotlivé sloupce tabulky, jejich datový typ je reprezentován převedením datového typu sloupce příslušné tabulky z SQL serveru. A ve všech operacích typu CUD (Create, Update, Delete) se pracuje právě jen s takovýmito instancemi tříd reprezentujících jeden řádek tabulky. Zásadní věcí pro úpravu záznamů v databázi je to, že nelze upravovat tabulku, která nemá nastaven primární klíč. Taková tabulka bude umožňovat jen čtení dat.41
41
PIALORSI-RUSSO. Microsoft LINQ, s. 160.
35
4.1.2.7 Zápis a mazání Zápis nové položky do tabulky databáze probíhá ve třech krocích: 1. Vytvoření instance třídy reprezentující řádek tabulky viz výše. 2. Provedení patřičné změny v instanci třídy DataContext, lze provést třeba takto: dt.Herbs_tables.InsertOnSubmit(herb);
Ukázka použití příkazu InsertONSubmit, dt v tomto případě představuje instanci třídy DataContext
3. Zavolání metody SubmitChanges, která pro tyto změny vygeneruje SQL příkaz a pošle ho SQL Serveru. Smazání položky probíhá velice podobně, jen místo příkazu InsertOnSubmit je potřeba použít příkaz DeleteOnSubmit. V případě kaskádového mazání a mazání záznamů s cizími klíči je vhodné použít příkaz DeleteAllOnSubmit(). Smazání podřízených položek je nutné zavolat ručně. Bohužel v LINQ to SQL není podpora kaskádových operací, pokud je v relační databázi cizí klíč deklarován s volbou ON DELETE CASCADE, nebo ON UPDATE CASCADE, změny automaticky provedené v databázi se nepromítnou do objektového modelu LINQ to SQL, pokud již tyto entity byly načtené do paměti.42 4.1.2.8 Úprava záznamu Úprava záznamu je v LINQ to SQL podobně jednoduchá jako jsou předchozí operace, opět je ovšem potřeba vytvořit instanci třídy představující příslušný řádek tabulky, vložit nové hodnoty do členů této třídy, které chceme aktualizovat, a opět zapsat zavoláním metody SubmitChanges. Pokud není duplicita primárního klíče hlídána v programu, dojde při pokusu o změnu hodnoty primárního klíče na hodnotu již v tabulce označenou k vyvolání výjimka DuplicateKeyEception.43 4.1.2.9 Dotazovací jazyk LINQ - shrnutí LINQ ve všech svých podobách je velice mocným nástrojem, z jehož funkcí jsem zde uvedl skutečně jen základy. Mezi jeho největší přednosti patří, zcela nepochybně, 42 43
PIALORSI-RUSSO. Microsoft LINQ, s. 164. Tamtéž, s. 176.
36
podstatné zpřehlednění kódu. Mezi další přednosti patří také konzistentnost syntaxe při dotazování se k různým datovým zdrojům a zjednodušení práce s SQL dotazy v případě LINQ to SQL, kdy není třeba dbát na pořadí jednotlivých součástí dotazu, jelikož si stroj LINQu pořadí součástí vygenerovaných dotazů pro SQL server určí sám.44 Avšak daní za tyto výhody v případě LINQ to SQL je určité zpomalení práce s databází.45
4.2
Schéma struktury programu
Obr. 7: Schéma struktury programu
Pokud schéma struktury programu srovnáme se schématem návrhu struktury programu, obsažené v kapitole 2.3.5, tak jsou na první pohled patrné rozdíly. Nejnápadnějším rozdílem je ten, že ve struktuře programu přibyla statická třída Seznamy, ta obsahuje globální konstanty, seznamy potřebné k tvorbě postavy a metody, které používám jako obecné funkce přístupné z ostatních částí programu. Pro úpravu databázových záznamů herních reálií používám formulářové třídy Herbsdialog, Booksdialog a Weapondialog, místo klasických tříd. Hlavní rozdíl spočívá 44
PIALORSI-RUSSO. Microsoft LINQ, s. 167. PITZ, Joe. LINQ to SQL Performance Considerations, 1 April 2010 [cit. 2012-05-23]. URL: < http://www.codeproject.com/Articles/70169/LINQ-to-SQL-Performance-Considerations >.
45
37
v tom, že pro zobrazení dat využiji, místo původně zamýšlené formulářové komponenty DataGridView, komponentu ListView. Ačkoliv vlastnosti a metody používané komponentou DataGridView znám již z prostředí MS Web Developeru ASP.Net celkem podrobně, tak v MS Visual C#.Net je DataGridView úplně jinou třídou,kde jsou potřeba použít trochu jiné postupy než v prostředí ASP.NET.46 Zbytek schématu již plně odpovídá návrhu.
4.3
Popis úvodní obrazovky – Windows Form Class FHlavní
Formulářová třída FHlavní je základem celé aplikace. Protože jeden z hlavních požadavků na funkčnost programu se týkal jeho přehlednosti, snažil jsem se všechna rozhraní programu udělat co nejpřehlednější bez zbytečných a rušivých elementů. Úvodní formulář obsahuje rozhraní pro automatickou genezi herní postavy, s možností volby ručního návrhu postavy, dále pak databázi postav, databázi rostlin, knih a zbraní. Vzhledem k požadavkům na přehlednost a jednoduchost grafického rozhraní nacházejí se jednotlivé základní funkce programu na jednotlivých záložkách, tak jak je vidět na přiloženém obrázku:
Obr. 8: Úvodní obrazovka programu
46
How to populate DataGridView, GridView with SQL statement in C#, 26 May 2006 [online]. [cit. 201205-23]. URL:.
38
Pro
výběr
jednotlivých
položek
používám
komponenty
typu
ComboBox,
v databázových záložkách potom ještě ListView. Ve velké míře používám vlastnosti komponent vypnutí a viditelnost (Disabled a Visible) pro snazší orientaci v návrhu postavy. Základem návrhu jsou položky rasa a povolání – implicitně nastaveno Bojovník – s tím, že postava je implicitně mužského pohlaví a cílová úroveň je nastavena na 1. Teprve když jsou vybrány tyto základní položky, tak je možné vybírat položky prostředí, úrovně a další. Ovšem další možností je stisknout tlačítko s popisem „Generuj!“, přičemž poté bude zahájena automatická geneze postavy. S tím, že nevybrané atributy potřebné k vytvoření postavy jsou ve třídě FHlavní generovány náhodně. Pro ruční návrh postavy slouží komponenta CheckBox s popisem „Ruční návrh“, při jehož zaškrtnutí je vyžadováno, aby byly zvoleny ještě další položky. Teprve až jsou všechny nutné položky zvoleny uživatelem, je možné opět za pomoci tlačítka „Generuj!“ spustit ruční návrh postavy. Třída FHlavní obsahuje tedy nejen metody pro obsluhu komponent formuláře a jejich událostí, ale i několik dalších metod zajišťující náhodné vybrání potřebných informací pro návrh postavy. Všechny metody a proměnné této třídy jsou definovány s maximálním zabezpečením, tedy kódovým slovem private. Po vygenerování nové postavy je obsah části formuláře, týkající se návrhu postavy, opět uveden do původního stavu, všechny volby jsou vymazány a formulář je opět připraven pro návrh další postavy. Omezení počtu takto vygenerovaných postav by mělo být dáno jen dostupnou pamětí počítače, na kterém program běží. Více k této problematice naleznete v kapitole o testování aplikace.
4.4
Statická třída Seznamy
Tato třída byla vytvořena proto, že jediná cesta umožňující přístup v programovacím prostředí MS Visual C# ke globálním konstantám a funkcím, přístupným z jakéhokoliv objektu v programu, vede přes statickou třídu. Třída Seznamy tedy obsahuje, jak už její název napovídá, veřejné proměnné a funkce, které jsou nezbytné pro běh programu. Některé z malých tabulek obsažených 39
v pravidlech bylo zcela zbytečné složitě přepisovat do tabulek v SQL databázi, a tak se z nich staly proměnné generického typu List nebo Dictionary. Dále tato třída obsahuje funkce často používané v ostatních třídách programu, jako jeden z příkladů takovéto funkce bych rád uvedl metodu Nahoda: public static int Nahoda(int dolni, int horni) { int koeficient=0; if (dolni < 0 && horni > 0) { koeficient = 0 - dolni; horni += koeficient; dolni = 0; } if (dolni < 0 && horni < 0) { koeficient = horni + dolni; horni = Math.Abs(dolni); dolni = Math.Abs(horni); } if (dolni > horni) { int pom; pom = dolni; dolni = horni; horni = pom; } Random rand=new Random(); return (rand.Next(horni+1-dolni)+dolni+koeficient); }
Metoda Seznamy.Nahoda
Hlavním účelem této metody je návrat náhodného čísla v zadaných mezích, první tři podmínky slouží jen k tomu, aby eliminovaly chyby zadání, samotné pseudonáhodné číslo se generuje až na samém konci této metody jako výstup metody Next třídy Random. Vzhledem k tomu, že ve svém programu nekladu velké požadavky na opravdovou náhodnost generovaných čísel, jaké by vznikly například při šifrování, a zároveň tato metoda není volána v rychlém časovém sledu (kdy by mohly vzniknout chyby s opakováním stejného generovaného čísla, z důvodu požívání taktu vnitřních hodin touto třídou), je její funkčnost zcela dostatečná.
40
4.5
Zobrazení postavy – Windows Form Class FPostava
Obr. 9: Zobrazení vygenerované postavy
Formulářová třída FPostava slouží k zobrazení vygenerované postavy a k základním operacím s ní, jako je uložení do databáze, export do textového souboru a ruční postup postavy o úroveň. Zobrazení všech vlastností postavy je rozděleno pro větší přehlednost do 4 záložek. Na první, úvodní straně, jsou všechny obecné vlastnosti postavy, na druhé jsou pak její bojové atributy a seznamy zbraní, které vlastní. Další záložka je věnována obecným dovednostem a majetku, a poslední záložka slouží pro zobrazení schopností specifických pro povolání. Při vytváření tohoto zobrazení za použití komponenty TabPages jsem narazil na problém spočívající v tom, že potřebuji zobrazit jen jednu záložku pro jedno určité povolání a ostatní nechat schované. Hned od začátku byly jasné dvě cesty jak tohoto stavu dosáhnout, první spočívala v tom, že by každá třída povolání přidávala další záložku do komponenty TabPages, což by znamenalo, že veškerý kód pro vytvoření a kontrolu záložky by musela obsluhovat daná třída povolání. Druhá možnost spočívala
41
ve vypnutí zbývajících, nepotřebných záložek, čehož jsem nakonec dosáhl odebráním všech záložek povolání přímo v konstruktoru třídy FPostava: this.TCPostava_atributy.TabPages.Remove(TCPSchopnosti_carodej); this.TCPostava_atributy.TabPages.Remove(TCPSchopnosti_hranicar); this.TCPostava_atributy.TabPages.Remove(TCPSchopnosti_knez); this.TCPostava_atributy.TabPages.Remove(TCPSchopnosti_theurg); this.TCPostava_atributy.TabPages.Remove(TCPSchopnosti_Zlodej);
Odebrání nepotřebných záložek z komponenty TabPages
S tím, že příslušné povolání opět přidá příslušnou záložku opačným způsobem. Podobný problém vyvstal i s tím, že bylo potřeba zabránit uživateli, aby mohl vybrat nové dovednosti nebo zbraně během přidávání vlastností při přestupu postavy. Bohužel, třída TabPages nedisponuje vlastností Visible či Enable, což vyřešilo až přetypování na typ Control a použití zděděných vlastností tohoto typu, jak dokládá následující kód: foreach (TabPage tp in this.TCPostava_atributy.TabPages) if (tp != TCPostava_atributy.SelectedTab) ((Control)tp).Enabled = false;
Ukázka použití zděděné metody Enabled u komponenty TabPages
Dále třída FPostava disponuje metodami, které kontrolují proces přidání bodů do vlastností postavy, při postupu na vyšší úroveň pomocí polí komponent typu NumericUpDown, které obsahují hodnoty základních vlastností. Dále metody převodu generického typu List a Dictionary na typ Item a SubItems, členy třídy ListView a vložení těchto informací do příslušné komponenty ListView. Samozřejmě také metody pro uložení postavy do databáze a pro export do textového souboru, stejně jako metody pro obsluhu jednotlivých komponent. Nebudu zde uvádět výpisy těchto metod, z důvodu jejich rozsahu, neboť zdrojový kód je k dispozici na přiloženém CD.
4.6
Abstraktní třída tpostava
Abstraktní třída tpostava je základním stavebním kamenem této aplikace, obsahuje data herní postavy společná pro všechna povolání. Skládá se celkem ze tří parametrických konstruktorů. Prvním z nich je konstruktor pro načtení postavy z databáze, druhý pak pro ruční genezi postavy a třetí slouží pro automatickou genezi postavy. Všechny tyto konstruktory implementují metodu s názvem Registrace_udalosti, která obsahuje přiřazení všech delegátů událostí k metodám.
42
Tato třída také zahrnuje metody pro zobrazení postavy na formuláři FPostava, pro automatické generování dovedností a výběr zbraní, stejně jako deklaraci abstraktní metody Boj, kterou musí implementovat všichni potomci. A to z toho důvodu, že každé jednotlivé povolání má jiný postup výpočtu této odvozené vlastnosti. Všechny vlastnosti postavy jsou uložené v proměnné vlastnosti, která je tvořena dvourozměrným polem proměnných typu int. Toto pole obsahuje hodnoty všech základních i odvozených vlastností, a to z toho důvodu, aby neustále nemusely probíhat výpočty hodnot odvozených vlastností. Dále pojímá všechny postihy a bonusy k vlastnostem dané pohlavím postavy nebo jinými mechanismy pravidel. V neposlední řadě má toto pole i atribut inkrementace vlastnosti při postupu postavy o úroveň, na jehož základě poté dojde k vyloučení těchto vlastností z inkrementace při dalším přestupu, a to při obou způsobech návrhu postavy. Orientace v jednotlivých položkách tohoto pole je usnadněna výčtovým typem vlastnost, který obsahuje statická třída Seznamy, index zkratky v této výčtové proměnné určuje odpovídající index dané vlastnosti v proměnné vlastnosti třídy tpostava. Třída tpostava vytváří také v konstruktoru instanci formulářové třídy FPostava, která má příznak protected, a je tedy přístupná i z potomka třídy tpostava. Rád bych zde uvedl ukázku mého řešení náhodného přiřazení hodnot k základním vlastnostem na základě hodnoty Zázemí postavy: if (hlvlastnosti[0]==preference_hv) { indhigh=0; indlow=1; } else { indhigh=1; indlow=0; } int v; int[] pom=new int[]{0,0,0,0,0,0}; if (hodnota_zazemi==5) { for (int i = 1; i <= 6; i++) { if (i % 2 == 0) { if (Seznamy.Nahoda(0, 100) <= 80)vlastnosti[hlvlastnosti[indhigh], 0]++; else vlastnosti[hlvlastnosti[indlow], 0]++; } do { do {
43
v = Seznamy.Nahoda(0, 5); pom[v]++; } while (pom[v]>3); if (!hlvlastnosti.Contains(v)) { vlastnosti[v, 0]++; break; } } while(true); } }
Část kódu metody Na_prvni_uroven_nahoda, přiřazení vlastností v závislosti na Zázemí postavy
Jak je z výše uvedeného kódu patrné, téměř veškeré přidělování bodů do vlastností probíhá náhodně, pomocí náhodných čísel generovaných metodou Seznamy.Nahoda. Ovšem výjimku tvoří hlavní vlastnosti postavy, které jsou určené povoláním postavy, tedy potomkem této třídy, který také danou metodu volá. Ale i přes to, jak je vidět v kódu, je osmdesátiprocentní pravděpodobnost, že bude zvolena i jiná z hlavních vlastností, než bylo určeno povoláním postavy, tedy potomkem. Způsob komunikace této třídy s instancí třídy FPostava a s potomkem je popsáno v kapitole 3.3.6.
4.7
Třída povolání tbojovnik
Jeden z mých cílů při návrhu programu byl ten, aby co největší množství informací a metod bylo implementováno v rodičovské třídě tpostava a třídy povolání již implementovaly jen to nejnutnější potřebné k automatické a ruční genezi postavy, k zobrazení a uložení postavy do databáze a textového souboru. I přes tuto moji snahu obsahuje třída tbojovník dvacet metod potřebných k výše zmíněným úkonům. Stejně jako její rodič, třída tpostava obsahuje i tato třída tři různé parametrické konstruktory, a to z důvodů různých způsobů vytváření instance této třídy. Datové proměnné obsažené v této třídě zahrnují schopnosti povolání, proměnné nutné k aplikaci pravidel DRD+ při tvorbě postavy a statickou proměnnou obsahující pole určující hlavní vlastnosti. Stejně jako její předek, i tato třída používá služeb databázového rozhraní LINQ, kde jsou uloženy všechny schopnosti tohoto povolání a při automatické genezi postavy i třídu Seznamy a její metodu pro genezi náhodných čísel Nahoda. 44
4.8
Vlastní dialogy, formulářové třídy pro obsluhu rozhraní
databáze Kromě
přednastavených
základních
dialogových
oken
třídy
System.Windows.Forms.MessageBox, lze v prostředí C# vytvářet, poměrně jednoduše, dialogy vlastní. Jedná se o potomka třídy System.Windows.Forms, jen s tou úpravou, že výstupům formuláře se přiřadí odpovídající proměnné třídy DialogResult, jak je vidět níže. this.BUloz.DialogResult = System.Windows.Forms.DialogResult.OK; this.BUloz.Location = new System.Drawing.Point(129, 402); this.BUloz.Name = "BUloz";
Ukázka tvorby vlastního dialogu, třída Weaponsdialog
Takto vytvořené vlastní dialogy používám pro přidávání a úpravu záznamů v databázové části mé aplikace. Jedná se zejména o třídy Herbsdialog, Booksdialog a Weaponsdialog. Většina z nich obsahuje přidaný parametrický konstruktor z důvodu možnosti úpravy záznamu v databázi. Při vytváření vlastních dialogů v této části aplikace jsem narazil na problém, který by se dal interpretovat jako chyba v rozhraní C#.Net. Pokud jsem v takovéto vlastní dialogové třídě vytvořil instanci dalšího dialogu, třeba i generické třídy MessageBox, došlo při ukončení tohoto dialogu k automatickému ukončení i vlastního dialogu, ze kterého byla tato instance vytvořena. Tento problém jsem nakonec vyřešil přiřazením proměnné DialogResult hodnotu DialogResult.NONE, po každém volání dalšího dialogu, jak je vidět níže: MessageBox.Show("Název, …jsou povinná pole.", "", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); this.DialogResult = DialogResult.None;
Ukázka kódu z třídy Herbsdialog Důvody pro výše zmíněné chování se mi nepodařilo najít. Při tomto způsobu zavření vlastního dialogu není volána ani metoda Close třídy System.Windows.Form.
4.9
Komunikace mezi objekty
Komunikace mezi jednotlivými objekty v aplikaci je nutná zejména pro iniciaci odpovídající reakce na akci uživatele. 45
Pro komunikaci mezi jednotlivými instancemi různých tříd používám několik způsobů. Nejjednodušším způsobem komunikace je vyhodnocení výsledku dialogu, tak jak je to použito u rozhraní databáze herních reálií, kdy se při vkládání nebo úpravě záznamu volá třída příslušného vlastního dialogu a při úpravě záznamu výsledek dialogu určuje, zda bude uložen upravený záznam či původní záznam. Ovšem nutnost komunikace mezi objekty nastala až s realizací třídy FPostava, sloužící k zobrazení postavy a k jejímu ručnímu návrhu. Jak již bylo uvedeno dříve, instance třídy FPostava je vytvořena konstruktorem abstraktní třídy tpostava a při nutnosti zobrazení postavy je tato instance formulářové třídy zobrazena pomocí metody Show(). Je zcela jasné, že následkem tohoto uspořádání je poměrně silná vazba mezi instancí potomka třídy tpostava a instancí formulářové třídy FPostava. Vzhledem k tomu, že jsem se zejména z bezpečnostních důvodů chtěl vyhnout úrovni public při zabezpečení jednotlivých členů tříd programu, tak by bylo obtížné a snižovalo by logickou přehlednost programu, kdyby stejně silná vazba vznikla i mezi formulářovou třídou FPostava a instancí potomka třídy tpostava. Proto třída tpostava implementuje několik delegátů metod, které jsou registrované pro odezvu na události v třídě FPostava. internal event tpostava.Prestup prestoupeno;
Registrace události ve třídě FPostava if (prestoupeno != null) prestoupeno();
Volání události ve třídě FPostava internal delegate void Prestup();
Deklarace delegáta ve třídě tpostava form.prestoupeno += new Prestup(Nastav_parametry_prestupu);
Registrace obsluhy události ve třídě tpostava
Jak je zřetelné z ukázky uvedené výše, tak tvorba události začíná vytvořením delegáta metody v naslouchající třídě (čtenář) a vytvořením události, přiřazené k tomuto delegátu ve třídě zdrojové (písař). Třída čtenář pak musí implementovat přiřazení události nějaké z metod příslušných cílové třídě a po zavolání této události je proveden kód obsažený v obslužné metodě této události.
46
Podmínka if použitá při volání události má funkci kontroly registrace události v cílové třídě. Pokud by událost nebyla registrována k nějaké konkrétní metodě, k volání události nedojde a běh programu neskončí v této větvi v pomyslném vzduchoprázdnu.
4.10 Popis databázové části V aplikaci je použito dvacet datových tabulek vycházejících z pravidel DRD+. Struktura některých z těchto tabulek musela být upravena z důvodu nevyhovující podoby pro využití v databázovém stroji. Například tabulka základních dovedností:
Obr. 10: Původní podoba tabulky základních dovedností
Obr. 11: Upravená tabulka základních dovedností
Zbylá část tabulek herních reálií, které jsou v aplikaci použity, tedy knihy a rostliny, jsou jednoduché tabulky bez složitých vazeb, takže jedinou databázovou strukturou, která si zaslouží hlubší popis v této práci, je struktura tabulek používaných pro uložení navrhnuté herní postavy do databáze. Jak je vidět na obrázku níže, struktura tabulek pro uložení herní postavy prakticky kopíruje rozložení datových entit v ER diagramu návrhu postavy uvedeném v kapitole 3.2.4. Tabulka postav obsahuje všechny atributy potřebné k otevření postavy z databáze s tím, že její schopnosti, dovednosti a vybavení jsou uloženy v dalších tabulkách, které používají cizí klíč k identifikaci objektu v tabulce postav. V tabulce postav je primárním klíčem jméno postavy, v ostatních tabulkách je ke jménu postavy ještě přidán další identifikátor – název dovednosti, schopnosti nebo vybavení, s tím, že jméno postavy je definováno jako cizí klíč z tabulky postav.
47
Obr. 12: Část struktury databáze, tabulky pro uložení herní postavy
48
5
Testování aplikace
5.1
Stabilita a funkčnost aplikace
Aplikace byla, vzhledem k použité inkrementální metodě tvorby aplikace, testována po celou dobu svého vývoje a případné vzniklé chyby byly opravovány okamžitě po jejich objevení. Vzhledem k tomu, že aplikaci vytvářím zejména pro osobní použití, bude její testování s případnou další opravou chyb probíhat i v budoucnu. Pří ladění aplikace jsem narazil na zajímavý problém, jehož popis a řešení jsem nebyl schopen nikde najít. Jakmile jsem ve svém projektu v režimu ladění použil funkci LINQ DataContext.SubmitChanges pro potvrzení vložení nebo úpravu záznamu v databázi, vše proběhlo tak jak mělo, avšak při dalším dotazu do databáze byla uložená data načtena, ovšem v samotné databázi nebyla patrná žádná změna. Při uzavření a opětném otevření vývojového prostředí byla vložená data ztracena. Takže bylo zjevné, že celý příkaz ponechává vkládaná data jen ve vrstvě entit DataContext, přitom při výpisu vygenerovaného SQL dotazu se zdálo vše v pořádku. Strávil jsem mnoho času prohledáváním internetových stránek, zda někde nenajdu popis mého problému a jeho řešení. Pokud jsem našel popis, chybělo k němu řešení, nebo dané řešení nebylo aplikovatelné na můj problém. Nakonec jsem našel řešení v podobě opuštění DEBUG módu a vypublikování aplikace. Poté bylo již vše v pořádku a data byla správně zapisována do databází.
5.2
Výkon aplikace
Při testování aplikace mě ovšem nezajímala pouze stabilita, ale i výkon. V kapitole zabývající se definicí základních požadavků na navrhovaný software je jedním z definovaných požadavků i maximální čas, trvání automatické geneze postavy. Rozhodl jsem se tedy změřit, kolik času zabere geneze postavy na nejvyšší a nejnižší úrovni. Měření času jsem prováděl pomocí instance třídy System.Diagnostics.Stopwatch. Jedna instance této třídy byla vytvořena v konstruktoru hlavního formuláře aplikace třídy FHlavni, druhá instance byla vytvořena v konstruktoru třídy tbojovnik. Zde je zapnuto měření času prvním příkazem, takže míra nepřesnosti, tedy času kdy měření neprobíhá, bude maximálně v jednotkách milisekund (ms). Další nepřesnost vzniká při součtu 49
časového údaje a zobrazení tohoto údaje ve formuláři postavy, dle mého odhadu se bude jednat také o jednotky ms. Postava
1. úroveň
1. úroveň, žena 1387 515 686 1226 651 465 665 729 635 919 787,8
10. úroveň 2707 1702 2031 2284 2149 1774 2072 2033 2410 1681 2084,3
10. úroveň, žena 2536 1923 2625 2615 1628 1693 1693 2361 1947 1893 2091,4
21. úroveň 5678 3474 4298 3554 3996 5628 4078 4631 4032 4160 4352,9
1. 1467 2. 889 3. 851 4. 673 5. 1242 6. 606 7. 769 8. 671 9. 599 10. 613 Průměrný čas 838 (ms) Obr. 13: Tabulka dosažených časů při automatickém návrhu postavy
V prvním sloupci tabulky je uvedeno, kolikátá postava již byla vygenerována, ostatní pak zůstávaly v paměti, aby se projevil jejich případný vliv na rychlost geneze dalších postav. Druhý a třetí sloupec zachycují čas geneze jednotlivých postav, s tím rozdílem, že v třetím sloupci je geneze postavy ženského pohlaví, zde testuji také, jestli se projeví na výsledné rychlosti používání oprav za pohlaví postavy. Další dva sloupce jsou stejné jako předchozí, jen s tím rozdílem, že se jedná o postavu na 10. úrovni. Poslední sloupec je vyplněn časy návrhu postavy na nejvyšší, tedy 21. úrovni. Zde je již vynechán test rozdílu geneze pohlaví, protože se v předchozích datech žádný signifikantní vliv neprojevil. Zajímavý je první řádek tabulky, kde jsou u první z postav téměř ve všech případech maximální časy geneze z daného sloupce. Vysvětluji si je tím, že se vždy jednalo o nové spuštění aplikace a první genezi, a tak se čas potřebný pro generování postavy prodloužil o načítání potřebných tabulek z databáze do vrstvy DataContext. Je tedy zcela zřejmé, že s ohromnou časovou rezervou program splňuje požadavek na maximální čas geneze postavy, který byl stanoven na 1 minutu a je jisté, že i při návrhu případných složitějších povolání nebude tento maximální čas překročen.
50
Otázkou ale stále zůstává, která část programu má na výkon aplikace větší vliv, a to geneze informací nutných pro následný automatický návrh postavy nebo samotná geneze postavy? Postava
Úplné Jediné zadání prostředí 554 732 571 682 665 618 578 682 548 679 583,2 678,6
1. 2. 3. 4. 5. Průměrný čas (ms) Obr. 14: Návrh postavy na 1. úrovni
Postava
Úplné Jediné zadání prostředí 3527 5527 3897 5163 3591 4786 4373 5283 4210 3988 3919,6 4949,4
1. 2. 3. 4. 5. Průměrný čas (ms) Obr. 15: Návrh postavy na 21. úrovni
Obě tyto tabulky přináší odpověď na danou otázku, neboť obě obsahují dva sloupce, jeden představuje čas návrhu postavy na dané úrovni s vyplněnými všemi volbami včetně maximální volby pěti různých prostředí, druhý sloupec pak představuje opět vyplnění všech voleb geneze postavy na hlavním formuláři aplikace, ovšem teď již s navoleným jediným prostředím. Delší čas nutný pro automatický návrh postavy pro jediné prostředí neomylně nasvědčuje tomu, že majoritní vliv na čas generování postavy má náhodný výběr dovedností, kdy při jediném prostředí se generuje maximální počet dovedností postavy v jediném cyklu. Kdežto při více vybraných prostředí je tento cyklus roztrhán do několika menších částí. Fluktuace časových údajů v tabulkách jsou z největší části dané právě náhodností geneze postavy, kdy se některé volby dovedností a vlastností musí zopakovat, protože daný cyklus neprojde filtrem pravděpodobnosti pro danou dovednost. Minoritní a dle mého soudu zanedbatelný vliv budou mít ostatní spuštěné procesy a aplikace v počítači použitém k testování. Vzhledem k tomu, že se dosažené časy budou lišit i v závislosti na výkonnosti hardware použitého počítače, uvádím zde základní konfiguraci počítače, na kterém proběhlo testování:
51
Obr. 16: Konfigurace počítače použitého k testování
52
6
Srovnání s existujícími řešeními
Pokud provedu srovnání z hlediska funkčnosti mnou vytvořené aplikace s již dříve zmíněným
programem
s názvem
DRD+,
jako
jediné
aplikace
s podobnou
funkcionalitou, která je mi známa, je zjevné, že program DRD+ poskytuje mnohem širší funkcionalitu z hlediska herních tabulek a převodů hodnot z těchto tabulek. Obsahuje i databázovou část, kde jsou obsaženy evidence zbrojí, zbraní a štítů s jednoduchým rozhraním pro přidávání položek do těchto tabulek. Také obsahuje již v základu generátor herních postav na úrovni jejich základních vlastností, s tím, že jeho variabilita je obrovská a je možné dle libosti navrhovat jakákoliv povolání s různým poměrem jednotlivých vlastností. Výpočet odvozených vlastností a vybavení postavy je pak realizováno na úrovni ručního vyplnění připraveného formuláře, kde jsou potřebné hodnoty automaticky dopočítány. Ovšem aplikace DRD+ umožňuje jen export postavy do textového souboru. Přidělení schopností a dovedností postavy aplikace DRD+ vůbec neobsahuje, lze ji tedy chápat jen jako podporu pro tvůrce hry při ručním vytváření postavy s pomocí pravidel. Mnou vytvořená aplikace je mnohem úžeji zaměřená na návrh herní postavy a při jejím vytváření striktně aplikuje herní pravidla, ovšem návrh postavy pojímám mnohem komplexněji. Také databáze postav a určení jejich místa pobytu, stejně jako pomocné databáze knih a rostlin jsou zaměřeny spíše na okamžitou podporu tvůrce hry při samotném herním sezení. Co se týče grafické stránky obou aplikací, je plně srovnatelná, u obou se jedná o strohou a přehlednou grafickou úpravu bez rušivých prvků. Je tedy zjevné, že co se funkcionality týče, jsou obě aplikace určeny pro použití v mírně odlišných situacích, s tím, že mnou vytvořená aplikace poskytuje komfort komplexní geneze postavy a evidence takto vytvořených postav v databázi.
53
7
Závěr
Cílem mé bakalářské práce bylo vytvořit aplikaci, která by umožňovala automatickou a ruční genezi herní postavy v systému DRD+, včetně dovedností, některého vybavení a schopností povolání. Aplikace splňuje zadání této práce jen pro povolání bojovník, třídy ostatních povolání jsou v programu jen deklarovány, včetně některých proměnných a povinné metody boj, ovšem výběr ostatních povolání je již v základním rozhraní vypnut a je umožněna geneze pouze postavy s povoláním bojovník. Hlavní důvod tohoto stavu lze spatřovat v tom, že v době tvorby aplikace nebyly k dispozici pravidla herního systému DRD+ v elektronické podobě, což znamenalo, i v případě implementace jen jednoho povolání, ručně přepsat velkou část pravidel do tabulek databáze. Vzhledem k plánovanému vydání pravidel v elektronické podobě v letních měsících bylo od realizace ostatních povolání upuštěno s tím, že budou implementovány až se znalostí finální podoby pravidel v digitální formě. I když je hotova nejobsáhlejší a nejsložitější část programu, tak samotná aplikace stále ještě není zcela dokončena, i pro mé osobní použití, což byl primární důvod vzniku aplikace. Bude nutné dokončit návrh ostatních povolání postavy, rád bych program rozšířil i o automatickou genezi dalších předmětů vybavení postavy a rozšířil odpovídajícím způsobem i databázovou část. Pro pozdější plánované uvolnění k použití širokou hráčskou obcí bude nutné upravit vzhled
programu,
přidat
rozhraní
pro
úpravu
jednotlivých
dovedností
a pravděpodobností jejich výběru, a přidat do hlavního okna aplikace i záložku s možností nastavení některých dalších parametrů aplikace. Aplikace je totiž plně přizpůsobena mému fiktivnímu světu herního systému DRD+. Co se týče další rozšiřitelnosti o povolání, která nejsou v základních pravidlech DRD+, není možné, z důvodu zvolené architektury programu přidat další volbu povolání bez větší úpravy několika tříd. Během vytváření aplikace se ukázalo, že zvolené implementační prostředí je zcela vhodné pro řešení této problematiky, a stal se tedy optimální volbou pro zvolenou podobu výsledného programu. Myslím si, že jsem se přiblížil k hranicím možností dotazovacího jazyka LINQ, který je vskutku příhodným pro samostatnou desktopovou
54
aplikaci, ale v jeho použití pro případnou síťovou verzi tohoto programu bych velmi váhal, a to z důvodu principu odpojeného prostředí tohoto výrazového jazyka. Hlavním motivem pro výběr tohoto tématu mé bakalářské práce byl úmysl naučit se programovat v některém z moderních jazyků v prostředí MS Windows a je zjevné, že tento cíl byl naplněn. Což je zřetelné i ze zdrojového kódu programu, kdy se kultura kódu a množství použitých tříd prostředí .Net postupně zefektivňují. I když jsem, samozřejmě, nedosáhl mistrovství v tomto programovacím jazyce, budu již schopen rychle a efektivně navrhnout a naprogramovat menší aplikaci, což bude znamenat přínos v mém profesním životě. Nikterak jsem nebyl překvapen objevením některých záhadných funkcionalit v implementačním prostředí Microsoft Visual C# 2010 Express Edition, jako je již dříve zmíněný problém s dialogy nebo záhadným chováním zápisu do databáze při debug módu aplikace. Doufám, že tyto chyby budou opraveny v právě vycházející verzi tohoto prostředí.
55
Seznam použité literatury a elektronických zdrojů 1. BUCHTA Jiří et al. Dračí doupě Plus: Příručka pro hráče. Ostrava, 2006. ISBN 80-85979-45-4. 2. HANÁK, Ján. Praktické objektové programování v jazyce C# 4.0. Brno, 2009, ISBN 978-80-87017-07-4. 3. HANÁK, Ján. Praktické paralelné programovanie v jazykoch C# 4.0 a C++. Brno, 2009, ISBN 978-80-87017-06-7. 4. HOLUB Zbyněk et al. Dračí doupě Plus: Příručka Pána jeskyně. Ostrava, 2005. ISBN 80-85979-49-7. 5. MAREŠ, Amadeo. 1001tipů a triků pro C#. Brno, 2008. ISBN 978-80-2512125-2. 6. PIALORSI, Paolo-RUSSO, Marco. Microsoft LINQ: Kompletní průvodce programátora. Brno, 2009. ISBN 978-80-251-2735-3. 7. VIRIUS, Miroslav. C# 2010: Hotová řešení. Brno, 2012. ISBN 978-80-2513730-7.
8. Wikipedie [online]. [cit. 2012-05-10]. URL: . 9. Wikipedie [online]. [cit. 2012-05-10]. URL: . 10. Wikipedie [online].[cit. 2012-05-17]. URL: . 11. Wikipedie [online]. [cit. 2012-05-17]. URL: < http://en.wikipedia.org/wiki/Demographics>. 12. How to populate DataGridView, GridView with SQL statement in C#, 26 May 2006 [online]. [cit. 2012-05-23]. URL:.
56
13. IEEE 830-1998 [online]. [cit. 2012-05-17]. URL:.
14. Visual Web Developer Express [online]. [cit. 2012-05-17]. URL:.
57
Seznam obrázků Obr. 1: Diagram procesu – Vytvoření herní postavy systému DRD+ na x-té úrovni .... 13 Obr. 2: Diagram procesu – Vytvoření herní postavy systému DRD+ na 1. úrovni ....... 14 Obr. 3: Diagram procesu – Vytvoření herní postavy systému DRD+ o jednu úroveň .. 17 Obr. 4: Entity – relationship diagram tvorby postavy včetně povolání. ........................ 19 Obr. 5: Schéma úpravy procesu pro návrh aplikace ...................................................... 24 Obr. 6: Návrh struktury programu ................................................................................. 26 Obr. 7: Schéma struktury programu............................................................................... 37 Obr. 8: Úvodní obrazovka programu ............................................................................. 38 Obr. 9: Zobrazení vygenerované postavy ...................................................................... 41 Obr. 10: Původní podoba tabulky základních dovedností ............................................. 47 Obr. 11: Upravená tabulka základních dovedností ........................................................ 47 Obr. 12: Část struktury databáze, tabulky pro uložení herní postavy ............................ 48 Obr. 13: Tabulka dosažených časů při automatickém návrhu postavy .......................... 50 Obr. 14: Návrh postavy na 1. úrovni.............................................................................. 51 Obr. 15: Návrh postavy na 21. úrovni............................................................................ 51 Obr. 16: Konfigurace počítače použitého k testování .................................................... 52
58
Přílohy 1.
Seznam objektových tříd
a) Formulářové třídy -
DrDplus.Weapondialog - vlastní dialog pro uložení nebo úpravu záznamu zbraně v databázi.
-
DrDplus.Authorsdialog - vlastní dialog pro vložení záznamu autora v databázi knih.
-
DrDplus.Booksdialog - vlastní dialog pro vložení nebo úpravu záznamu knihy v databázi.
-
DrDplus.FHlavni - hlavní okno aplikace, obsahuje rozhraní pro genezi postav a rozhraní databázové části aplikace.
-
DrDplus.FPostava - formulář, ve kterém se zobrazuje vygenerovaná postava, umožňuje základní operace s entitou postava.
-
DrDplus.Herbsdialog - vlastní dialog pro vložení nebo úpravu záznamu rostliny v databázi.
b) abstraktní třída -
DrDplus.tpostava - předek všech tříd povolání, obsahuje metody a proměnné nutné pro genezi postavy.
c) třídy povolání -
DrDplus.tbojovnik - třída povolání, potomek třídy tpostava, obsahuje metody a proměnné pro povolání Bojovník, jediná plně implementovaná třída povolání v aplikaci.
-
DrDplus.tcarodej - třída povolání, potomek třídy tpostava, obsahuje metody a proměnné pro povolání Čaroděj. Není plně implementována.
-
DrDplus.thranicar - třída povolání, potomek třídy tpostava, obsahuje metody a proměnné pro povolání Hraničář. Není plně implementována.
-
DrDplus.tknez - třída povolání, potomek třídy tpostava, obsahuje metody a proměnné pro povolání Kněz. Není plně implementována.
-
DrDplus.ttheurg - třída povolání, potomek třídy tpostava, obsahuje metody a proměnné pro povolání Theurg. Není plně implementována.
-
DrDplus.tzlodej - třída povolání, potomek třídy tpostava, obsahuje metody a proměnné pro povolání Zloděj. Není plně implementována.
59
d) veřejná statická třída -
DrDplus.Seznamy - třída obsahující globální konstanty a globálně přístupné funkce.
2.
Seznam databázových tabulek
a) tabulky převzaté z pravidel DRD+ Bojovnik_finty Bojovnik_schopnosti Dovednosti_basic Dovednosti_full Hlvlastnosti Majetek Puvod Rasy Tabulka_postihu_za_dovednost Tabulka_postihu_za_strelnou_zbran Tabulka_postihu_za_zbran
Tabulka_prileb Tabulka_stitu Tabulka_strelnych_zbrani Tabulka_zbroji Tabulka_zraneni_unavy Tabulka_Zz Velikost_hmotnost_ras Vyznacny_smysl Zbrane_nablizko Zena
b) tabulky používané pro uložení postavy Bojovnik_finty_postav Bojovnik_tabulka_archetypu_postav Tabulka_dovednosti_postav Tabulka_postav
Tabulka_prileb_postav Tabulka_stitu_postav Tabulka_zbrani_postav Tabulka_zbroji_postav
c) datové tabulky databázové části Herbs_table Knihovna_autori Knihovna_knihy
60