Programování pro hračičky/Andělé/Lekce 3: Porovnání verzí

Z Wikiverzity
Smazaný obsah Přidaný obsah
→‎Používáme virtuální objekty: a přece jen ještě odstaveček
Řádek 90: Řádek 90:


==Klonování objektů v místnostech==
==Klonování objektů v místnostech==

Jakmile jsme zvládli udělat prvních pár virtuálních detailů, můžeme se se získanými zkušenostmi vrhnout do klonování skutečných programátorských objektů. I ty budeme vkládat do místností (což je, podobně jako u virtuálních detailů, zdaleka nejčastější způsob jejich použití).

Nejprve si ve složce <code>/obj</code> a v jejích podsložkách vybereme, který z již předpřipravených objektů chceme použít. Pak si ze svých místností zvolíme tu, do které má být objekt umístěn.

...

<source lang="c" >
void reset()
{
if (!batoh || !present(batoh))
{
batoh=clone_object("/obj/batoh");
batoh->move(this_object());
}
}
</source>

...


Do funkce <code>create()</code> pak přidáme zavolání této funkce <code>reset()</code>, aby se objekt vytvořil hned při vytvoření místnosti:

<source lang="c" >
void create()
{
...
reset();
}
</source>


...
...
Řádek 119: Řádek 149:
</source>
</source>


Do funkce <code>create()</code> pak přidáme zavolání této funkce <code>reset()</code>, aby se objekt vytvořil hned při vytvoření místnosti:


<source lang="c" >
void create()
{
...
reset();
}
</source>


...
...

Verze z 31. 10. 2012, 00:08

Tato stránka není ještě hotová.

Opakování a probrání domácího úkolu

Projděme si místnosti, které jsme kdo vytvořili (zejména máme-li něco, co bychom rádi ukázali ostatním).

Podívejme se, jaký herní předmět hodlá kdo vytvořit. (Dnes se do tohoto tvoření dáme.)

Základní programátorské rozlišení objektů

Objekty, s nimiž se setkáváme ve hře, mohou být trojího základního druhu: Mohou to být jednak jedinečné objekty, které se dále neklonují a ve hře proto vystupuje přímo jejich prototyp, jednak klonované objekty, jejichž prototyp zůstává mimo hru, zatímco ve hře se vyskytují jeho klony, jednak virtuální objekty, které se hráčům jako objekty jeví, ale z programátorského hlediska nejsou objekty, nýbrž víceméně jen soubory hlášek, jimiž se má reagovat na určité hráčské příkazy.

Jedinečné objekty

Některé objekty se ve hře z logiky věcí mají vyskytovat jen jednou a jsou natolik složité, že se vyplatí mít jejich program uložen ve zvláštním souboru. Týká se to jednak všech místností, které nejsou generovány automaticky podle map (například celý Dům, a za prvním Prahem téměř všechny místnosti ve městech, mimořádná zákoutí atd.), jednak nehráčských postav majících nějakou osobnost (například Josef nebo Lída, které můžeme potkat hned na začátku hry), jednak předmětů nadaných mimořádnými možnostmi, jejichž častější výskyt ve hře by mohl dost změnit její náladu (například buřič trempů Kundrápa a Žahoura, který může být velmi mocnou zbraní). K těmto objektům vystupujícím přímo ve hře pak můžeme připočítat též objekty, které nějakou část hry spravují nebo koordinují, aniž by byly pro hráče přímo viditelné (tzv. mastery neboli řídicí objekty, například řídicí objekt počasí pro tu či onu doménu, řídicí objekt legionářských hlídek v Oikúmené atd.).

Takovéto objekty jsou pak přímým obrazem svého programového souboru, který se načte do paměti buď v rámci programu funkcí touch(), nebo ve hře andělským příkazem probudiž. Tím vznikne prototyp, ze kterého se ovšem už nevyrábějí žádné další klony, nýbrž který sám účinkuje ve hře.

Aby byly jedinečné objekty odlišeny od klonovatelných, umisťujeme je v mudové knihovně zpravidla do podsložek touch (v hráčské oblasti tedy třeba /d/oikumene/jeruzalem/touch, ve vlastní programátorské složce třeba /w/mojejmeno/touch nebo /w/mojejmeno/bludiste/touch).

Klonované objekty

Jiné objekty se ve hře vyskytují opakovaně. Typicky jsou to běžné předměty (batoh, pochodeň, meč), ale také druhové bytosti (vlk, skřet, hlídkující legionář) a mapové místnosti (tedy například jednotlivé vzájemně podobné místnosti v určité krajině). Takovéto objekty pak mají společný programový soubor a z něho vytvořený prototyp, který ovšem sám ve hře nevystupuje, nýbrž se z něho vždy nejprve vyrobí klon, který se pak přemístí jako objekt do hry.

Klon objektu vyrobíme v rámci programu funkcí clone_object(), ve hře pak andělským příkazem budiž. Jedná se vlastně o paměťovou kopii všech proměnných, v nichž jsou uloženy vlastnosti objektu, zatímco metody objektu jsou zapsány jedinečně v prototypu. Z toho plyne, že vlastnosti jednotlivého naklonovaného objektu můžeme po naklonování nadále měnit, zatímco množina použitelných metod je pevně dána společným prototypem.

Aby se klonovatelné objekty nepletly s jinými, ukládáme jejich soubory buď do složky /obj a jejích podsložek (jako třeba /obj/nabytek nebo /obj/voda), nebo do podsložek obj v příslušné části hry (například /d/stredozeme/moria/obj) nebo ve vlastním programátorském adresáři (například /w/mojejmeno/obj).

Virtuální objekty

Některé objekty se vyskytují ve hře jen jako doplňky či detaily jiných objektů a jsou na tyto jiné objekty pevně vázané. Typicky se jedná součásti popisu místností, které je možno si zvlášť prohlédnout (stěny, strop, nebe, tráva), méně často o popisové detaily na předmětech (cenovka na svetru, držadlo u kbelíku) nebo na nehráčských postavách (vlasy, zuby).

Takovéto herní objekty pak z programátorského hlediska nejsou objekty, nýbrž jen v jiných objektech uložené seznamy základních vlastností a hlášek, které se projeví při jejich prohlížení či jiných základních úkonech. Chceme-li o takovýchto objektech-neobjektech mluvit, používáme označení virtuální objekty nebo virtuální detaily, nebo podle angličtiny vzniklé zkratky v-items.

Virtuální objekt tedy nemá žádný svůj soubor na disku ani prototyp v paměti, ale je uložen jako obsah nějaké proměnné v jiném objektu. Můžeme si už říci, že se jedná o proměnnou typu mapping, tedy tzv. asociativní pole, i když přesné vysvětlení tohoto pojmu si necháme na později.

Používáme virtuální objekty

Ze tří zmíněných druhů objektů už jsme programovali objekty jedinečné, když jsme vytvářeli první vlastní místnost, ovšem zatím to bylo spíše jen drobné předělávání podle hotového vzoru. Pro samostatnou tvorbu začneme virtuálními objekty.

Virtuální objekt můžeme přidat do jakéhokoli objektu, ale nejjednodušší bude začít jejich přidáváním do místností. (Ve své andělské pracovně máme ostatně ohnivá písmena, která jsou takovým přidaným objektem, takže i nyní se budeme moci opřít o určitý vzor.) Zvolme si tedy místnost, do níž chceme nějaký virtuální objekt přidat, a otevřme si její soubor.

Protože Prahy se odehrávají v češtině, budeme při vytváření objektů muset dbát též na správné skloňování jejich jmen. K tomu potřebujeme někde v úvodu souboru mít vloženu řádku:

#include <sklon.h>

Pokud jsme dotyčnou místnost vytvořili okopírováním workroom.c a následným předěláním, pak takovou řádku nejspíše někde na začátku souboru už máme. Pokud ne, tak ji vložíme buď na úplný začátek, nebo za rovněž někde na začátku se nacházející řádky, které začínají slovem nebo obsahují slovo inherit (o těch budeme také podrobně mluvit až později).

Do těla funkce create(), která se automaticky spouští při vytvoření objektu (v případě jednotlivé místnosti při jejím načtení do paměti), vložíme nyní volání funkce add_v_item(), jejímž jediným parametrem bude asociativní pole popisující virtuální objekt. Za vzor si můžeme vzít třeba poháry z Horepovy krčmy:

void create()
{
  ...
  add_v_item(([
    "name":"pohár",
    "plural":CISLO_MN,
    "gender":ROD_MI,
    "vzor":VZOR_STAN,
    "id":({"pohár","pohár","číše","číše","sklenice","sklenice"}),
    "vzor_id":({VZOR_STAN,VZOR_STAN,VZOR_NUSE,VZOR_NUSE,
      VZOR_ULICE,VZOR_ULICE}),
    "plural_id":({CISLO_J,CISLO_MN,CISLO_J,CISLO_MN,CISLO_J,CISLO_MN}),
    "long":"Poháry, kterých se v této krčmě užívá, jsou zhotoveny ze skla, "
      "zajímavého materiálu, oblíbeného právě v Egyptě. "
      "Mají jednoduchý válcový tvar a dole zesílenou podstavu.",
    "smell":"Přes všepronikající vůni egyptského dýmu cítíš z použitých "
      "pohárů vůně nápojů, které v nich ještě před chvilkou byly.",
  ]));
  ...
}

Identifikátory psané velkými písmeny jsou konstanty definované v souboru /sys/sklon.h, který jsme načetli oním řádkem #include <sklon.h>. Jsou to vlastně interní čísla různých rodů, čísel a vzorů, ale protože s čísly by se pracovalo podstatně hůř, jsou takto nahrazena aspoň přibližně zapamatovatelnými slovy. ROD_F, ROD_MA, ROD_MI, ROD_N znamenají po řadě rod ženský, mužský životný, mužský neživotný a střední, CISLO_J, CISLO_MN, CISLO_POMN, CISLO_HROM číslo jednotné, číslo množné, jméno pomnožné a jméno hromadné, identifikátory začínající na VZOR_ znamenají jednotlivé skloňovací vzory. Protože skloňovacích vzorů je v češtině ve skutečnosti mnohem více, než se běžně učí ve škole (například slova „hrad“, „stan“ a „padák“ se všechna řadí ke školskému vzoru „hrad“, ale při skloňování se v některých pádech liší), budeme se muset občas kouknout buď do souboru /sys/sklon.h (jde to například ze hry andělským příkazem more /sys/sklon.h), nebo si postupně zapamatovat možné vzory při zacházení s již hotovými virtuálními objekty.

Jednotlivé položky asociativního pole pak nastavují jednotlivé vlastnosti virtuálního objektu. Poměrně jasný nám je asi význam položek "long" a "smell" (obdobně bychom mohli definovat ještě položky "noise", "feel" a řadu dalších, které najdeme popsány v Podprahové encyklopedii v sekci Jak to funguje, podsekci Virtuální detaily). Položka "name" definuje, pod jakým hlavním jménem bude objekt vystupovat, tedy pod jakým se bude třeba objevovat v hláškách typu „Michael si prohlíží poháry.“ (jméno píšeme malými písmeny, případné velké písmeno u jmen vlastních řešíme jinak), "gender", "plural" a "vzor" udávají, jak se bude toto jméno skloňovat. Mohli bychom definovat ještě "adjektiv" pro přívlastek shodný a "attribut" pro přívlastek neshodný:

    "adjektiv":({"použitý","skleněný"}),
    "attribut":"na pultě",

Takové nastavení by pak způsobilo, že výše uvedená hláška by měla podobu „Michael si prohlíží použité skleněné poháry na pultě.“

Položky "id", "vzor_id" a "plural_id" definují, pod jakými jinými jmény může hráč na daný předmět odkazovat, přičemž jednotlivé položky všech tří seznamů (či přesněji tzv. polí) k sobě patří. V daném případě je nastaveno, že hráč si může prohlížet „poháry“, „pohár“, „číše“, „číši“, „sklenice“ i „sklenici“ (zopakované „poháry“ v množném čísle ve skutečnosti nejsou zapotřebí, protože ty zajišťuje už položka "name", ale pro některého programátora může být takovéto zopakování přehlednější a praktičtější pro případ, že by se najednou rozhodl nastavit jako hlavní jméno místo "pohár" třeba "číše"). Pokud jsou nastaveny položky "adjektiv" a "attribut", je možno je používat i se všemi těmito vedlejšími identifikátory (tedy třeba „prohlédni si použitou sklenici“). Kromě toho je možno nastavit další použitelná přídavná jména položkou "plus_adjektiv".

Podle tohoto vzoru můžeme nyní všechny své místnosti ozdobit spoustou virtuálních detailů. Při tom nejspíše narazíme na různé nejasnosti a problémy, které pak můžeme řešit ve hře s ostatními anděly, nebo na diskusní stránce této lekce nebo letošního kurzu.

Klonování objektů v místnostech

Jakmile jsme zvládli udělat prvních pár virtuálních detailů, můžeme se se získanými zkušenostmi vrhnout do klonování skutečných programátorských objektů. I ty budeme vkládat do místností (což je, podobně jako u virtuálních detailů, zdaleka nejčastější způsob jejich použití).

Nejprve si ve složce /obj a v jejích podsložkách vybereme, který z již předpřipravených objektů chceme použít. Pak si ze svých místností zvolíme tu, do které má být objekt umístěn.

...

void reset()
{
  if (!batoh || !present(batoh))
    {
      batoh=clone_object("/obj/batoh");
      batoh->move(this_object());
    }
}

...


Do funkce create() pak přidáme zavolání této funkce reset(), aby se objekt vytvořil hned při vytvoření místnosti:

void create()
{
  ...
  reset();
}

...

void reset()
{
  if (!stud)
    {
      stud=clone_object("/obj/voda/studna");
      stud->set_name("kašna");
      stud->set_gender(ROD_F);
      stud->set_vzor(VZOR_PANNA);
      stud->add_id(({"skruž","sloupek","socha","nymfa","víla","džbán",
          "ornament","ornament"}),
        ({VZOR_JABLON,VZOR_STOLEK,VZOR_ZENA,VZOR_ZENA,VZOR_ZENA,VZOR_HRAD,
          VZOR_STAN,VZOR_STAN}),
        ({CISLO_J,CISLO_J,CISLO_J,CISLO_J,CISLO_J,CISLO_J,
          CISLO_J,CISLO_MN}));
      stud->set_adjektiv("kamenný");
      stud->set_long("Kašna, kterou vidíš před sebou, sestává z velké "
        "kamenné skruže, uprostřed níž se tyčí právětak kamenný sloupek, "
        "nesoucí sochu nymfy, tedy vodní víly. Víla drží v rukou veliký "
        "džbán, z něhož vytéká voda a naplňuje kašnu. Sloupek i skruž "
        "jsou zdobeny tesanými ornamenty.");
      stud->move(this_object());
    }
}


...

Práce na vlastním objektu

...

Pomocné stránky