Ako programovať počítačové hry?
Máte nápad na počítačovú hru a chcete ju uskutočniť? Alebo ste sa niekedy zamýšľali nad tým, ako sú počítačové hry napísané? Alebo dokonca uvažujete o práci vo vývoji hier? Táto príručka vám ukáže, ako písať rôzne typy počítačových hier, s konkrétnymi príkladmi, ako začať. Táto stránka sa zameriava na skutočné programovanie, ale ak dávate prednosť širšiemu prehľadu, prečítajte si článok Ako vyrábať počítačové hry.
Časť 1 zo 4: Vytvorenie textovej hry
- 1Vyberte programovací jazyk. Všetky programovacie jazyky sú rôzne, takže sa budete musieť rozhodnúť, ktorý použijete na napísanie hry. Každý hlavný programovací jazyk podporuje zadávanie textu, textový výstup a konštrukcie if (hlavné veci, ktoré potrebujete pre jednoduchú textovú hru), takže sa môžete rozhodnúť sami. Tu je niekoľko faktorov, ktoré je potrebné zvážiť:
- Oblasť použitia: niektoré programovacie jazyky, ako napríklad JavaScript, sú navrhnuté na použitie na webových stránkach, iné ako Python, C alebo C ++ sú navrhnuté tak, aby fungovali na počítači. Niektoré jazyky majú jeden konkrétny účel, napríklad R, ktorý sa používa hlavne na štatistickú analýzu. Pre svoju hru by ste mali používať jazyk so širším poľom aplikácie (Python, C, C ++, JavaScript, mnoho ďalších).
- Jednoduché použitie: napriek tomu, že písanie programu by malo byť dostatočne jednoduché po cvičení v akomkoľvek normálnom programovacom jazyku (tj. Nie v jazyku, ktorý by bol špeciálne navrhnutý tak, aby bol mätúci a nepoužiteľný ako Malbolge), niektoré sú pre začiatočníkov priateľskejšie ako ostatné. Java a C napríklad vyžadujú, aby programátor porozumel viac konceptom programovania ako Python. Tiež, Python chybové správy sú zrozumiteľnejšie pre začiatočníkov, než, napríklad C chybové správy.
- Kompatibilita s platformou: Pravdepodobne chcete, aby vašu hru mohli hrať ľudia v rôznych systémoch, ako sú Linux, Mac alebo Windows. Nemali by ste preto používať jazyk, ktorý je podporovaný iba v niekoľkých systémoch, napríklad Visual Basic, ktorý je podporovaný iba v systéme Windows. To je tiež dobrý dôvod, prečo nekódovať svoju hru v Assembleri, ktorý je špecifický pre systém a procesor a taktiež sa s ním dosť ťažko programuje.
Tento článok použije Python na príklady textovej hry, ale môžete sa pozrieť na to, ako sa koncepty vykonávajú v akomkoľvek inom programovacom jazyku.
- 2Nainštalujte potrebné nástroje. Potrebujete niečo, s čím by ste mohli skompilovať alebo interpretovať svoj program, a niečo, s čím ho chcete napísať/upraviť. Ak chcete nasledovať príklad v tomto článku, mali by ste si nainštalovať Python a naučiť sa spúšťať programy. Ak chcete, môžete si nastaviť nejaké IDE alebo použiť taký, ktorý poskytuje Python (nazýva sa IDLE), ale môžete použiť aj svoj obľúbený textový editor, ktorý podporuje obyčajný text.
- 3Vytlačte nejaký text. Hráč bude chcieť vedieť, čo sa deje a čo má robiť, preto by ste mu mali vytlačiť nejaký text.
- To sa deje pomocou print() funkcie v Pythone. Ak to chcete vyskúšať, otvorte nový súbor s príponou.py, zadajte doň nasledujúci kód, uložte ho a spustite:
vytlačiť („Vitajte v hre na hádanie čísel!“) vytlačiť („Zadajte celé číslo od 1 do 1 000:“)
- To sa deje pomocou print() funkcie v Pythone. Ak to chcete vyskúšať, otvorte nový súbor s príponou.py, zadajte doň nasledujúci kód, uložte ho a spustite:
- 4Vneste do hry určitú náhodnosť. Ak nič nie je náhodné, hra bude zakaždým úplne rovnaká a hráč sa rýchlo začne nudiť.
- V takom prípade by malo byť číslo náhodne zvolené na začiatku programu, aby hráč vždy nehádal rovnaké číslo. Pretože by malo zostať rovnaké v celom programe, náhodné číslo by ste mali uložiť do premennej.
- Python vo svojom jadre neposkytuje funkciu náhodných čísel. Má však štandardnú knižnicu (to znamená, že používateľ nebude musieť inštalovať nič extra), ktorá ho má. Prejdite teda na začiatok kódu (predvytlačiť ()funkcie) a napíšte riadok import random.
- Použite funkciu náhodného výberu. To sa nazývarandint (), je v náhodnýknižnica, ktorú ste práve importovali, a ako argument berie minimálnu a maximálnu hodnotu, ktorú číslo môže mať. Vráťte sa teda na koniec kódu a zadajte nasledujúci riadok:
rightNum = random.randint (0,1000)
- 5Získajte vstup od hráča. V hre chce hráč niečo urobiť alebo s niečím komunikovať. V textovej hre je to možné zadaním textu.
- Pretože kód, ktorý ste zadali, vytlačí hráčovi pokyn na zadanie čísla, mal by tiež čítať číslo, ktoré zadá. To sa deje input() v jazyku Python 3 a raw_input() v jazyku Python 2. Mali by ste písať v jazyku Python 3, pretože Python 2 bude čoskoro zastaraný. Pridajte do svojho kódu nasledujúci riadok, aby sa vstup hráča uložil do premennej s názvomčíslo:
userNum = vstup ()
- Pretože kód, ktorý ste zadali, vytlačí hráčovi pokyn na zadanie čísla, mal by tiež čítať číslo, ktoré zadá. To sa deje input() v jazyku Python 3 a raw_input() v jazyku Python 2. Mali by ste písať v jazyku Python 3, pretože Python 2 bude čoskoro zastaraný. Pridajte do svojho kódu nasledujúci riadok, aby sa vstup hráča uložil do premennej s názvomčíslo:
- 6Premeňte vstup používateľa na použiteľný typ údajov.
- Urobte z vstupu hráča číslo. Teraz sa to môže zdať mätúce, pretože práve zadali číslo. Existuje však dobrý dôvod: Python predpokladá, že celý vstup je text alebo ako sa v programovaní nazýva reťazec. A tento text obsahuje číslo, ktoré chcete získať. Python poskytuje funkciu na prevod reťazca, ktorý obsahuje iba číslo, na číslo vo vnútri. Typ:
userNum = int (userNum)
- Urobte z vstupu hráča číslo. Teraz sa to môže zdať mätúce, pretože práve zadali číslo. Existuje však dobrý dôvod: Python predpokladá, že celý vstup je text alebo ako sa v programovaní nazýva reťazec. A tento text obsahuje číslo, ktoré chcete získať. Python poskytuje funkciu na prevod reťazca, ktorý obsahuje iba číslo, na číslo vo vnútri. Typ:
- 7Spracujte vstup používateľa. Bolo by nezmyselné požiadať hráča o zadanie náhodných vecí. V skutočnosti by ste mali niečo urobiť s informáciami, ktoré používateľ zadal.
- Porovnajte číslo používateľa so správnym číslom. Aj keď čísla nie sú rovnaké, malo by to spôsobiť, že používateľ zadá ďalšie číslo. Keď sa čísla zhodujú, malo by prestať dostávať nové vstupy, povedať používateľovi, že uhádol správne, a ukončiť program. To sa vykonáva pomocou nasledujúceho kódu:
zatiaľ čo userNum! = rightNum: userNum = int (input ())
- Porovnajte číslo používateľa so správnym číslom. Aj keď čísla nie sú rovnaké, malo by to spôsobiť, že používateľ zadá ďalšie číslo. Keď sa čísla zhodujú, malo by prestať dostávať nové vstupy, povedať používateľovi, že uhádol správne, a ukončiť program. To sa vykonáva pomocou nasledujúceho kódu:
- 8Dajte hráčovi spätnú väzbu. Aj keď ste vstup už spracovali, používateľ to nevidí. Výsledok musíte skutočne vytlačiť používateľovi, aby porozumel tomu, čo sa deje.
- Iste by ste mohli používateľovi len povedať, či je jeho číslo správne alebo nesprávne. Ale s týmto prístupom by hráč musel v najhoršom prípade hádať 1000 -krát, čo by bolo veľmi nudné.
- Povedzte hráčovi, či je ich počet príliš malý alebo príliš veľký. Tým sa výrazne zníži počet hádaní: Ak napríklad používateľ uhádne najskôr 500 a oznámi mu, že je príliš veľký, teraz je k dispozícii iba 500 možných čísel namiesto 1 000. To sa robí s konštrukciami if, nahraďtevytlačiť („Nesprávne. Skúste to znova.“) s jedným.
- Uvedomte si, že kontrola, či sú dve čísla rovnaké, sa robí s ==, nie s =. = priradí hodnotu napravo od premennej naľavo od nej!
if userNum <rightNum: print ("Too small. Try again:") if userNum> rightNum: print ("Too big. Try again:")
- 9Otestujte si kód. Ako programátor by ste si mali byť istí, že váš kód funguje vo všetkých prípadoch, než ho budete považovať za dokončený.
- Pri programovaní v pythone dbajte na to, aby boli odsadenia správne. Váš kód by mal vyzerať takto:
import random print („Vitajte v hre na hádanie čísel!“) print („Zadajte celé číslo od 1 do 1000:“) rightNum = random.randint (0,1000) userNum = input () userNum = int (userNum) while userNum! = rightNum: if userNum <rightNum: print ("Too small. Try again:") if userNum> rightNum: print ("Too big. Try again:") userNum = int (input ()) print ("Hádali ste správne. ")
- Pri programovaní v pythone dbajte na to, aby boli odsadenia správne. Váš kód by mal vyzerať takto:
- 10Overte zadanie. Užívateľ by nemal byť schopný zlomiť váš program jednoduchými akciami, ako je zadanie nesprávnej veci. Overenie zadania znamená, či používateľ zadal správnu vec pred jej spracovaním.
- Otvorte hru znova a skúste zadať čokoľvek, čo nie je číslo. Hra sa skončí aValueError. Aby ste tomu zabránili, mali by ste implementovať spôsob, ako skontrolovať, či bolo zadané číslo.
- Definujte funkciu. Pretože validácia vstupu je pomerne dlhá a musíte to urobiť viackrát, mali by ste definovať funkciu. Nevyžaduje žiadne argumenty a vráti číslo. Najprv napíšte def numInput(): do hornej časti kódu, priamo pod príponuimport náhodný.
- Získajte vstup používateľa raz. Použite input() funkciu a priraďte výsledok premennej inp.
- Aj keď používateľ zadá nie číslo, požiadajte ho, aby zadal číslo. Kontrola, či je reťazec číslom, sa vykonáva pomocou isdigit() funkcií, ktoré umožňujú iba celé číslo, takže to nebudete musieť kontrolovať osobitne.
- Keď je vstupom číslo, konvertujte ho z reťazca na číslo a vráťte výsledok. Túto int() funkciu použite na prevod reťazca na celé číslo. Vďaka tomu nebude konverzia v hlavnom kóde potrebná a mali by ste ju odtiaľ odstrániť.
- Nahradiť všetky hovory na vstup () v hlavnom kóde s volaním na numInput ().
- Kód súboru numInput () funkcia bude vyzerať takto:
def numInput (): inp = input () while not inp.isdigit (): print ("Bolo vám povedané zadať celé číslo! Zadajte celé číslo:") inp = input () return int (inp)
- 11Skúste hru znova. Zvlášť dávajte pozor na to, či vaše overenie vstupu funguje, pretože účelovo zadáte niečo nesprávne.
- Skúste zadať text, keď vás program požiada o číslo. Teraz, namiesto toho, aby vás program opustil s chybovým hlásením, vás znova požiada o číslo.
- 12Po skončení hry navrhnite reštart. Hráč tak mohol hrať vašu hru dlhší čas bez toho, aby ju musel neustále reštartovať.
- Vložte celý kód okrem importu a definície funkcie do cyklu cyklu. Nastaviť True ako podmienku: toto bude vždy platiť, takže slučka bude pokračovať navždy.
- Po správnom uhádnutí čísla sa hráča opýtajte, či chce hrať znova. Použite print() funkciu.
- Ak odpovedia „nie“, vypadnite z pohľadu. Ak odpovedajú na čokoľvek iné, pokračujte. Vylúčenie zo slučky sa deje s break príkazom.
- Presuňte „Vitajte v hre na hádanie čísel“ mimo cyklus while. Hráč pravdepodobne nechce byť vítaný pri každom hraní hry. Posuňte inštrukciuvytlačiť („Vitajte v hre na hádanie čísel!“ nad kým je pravda:, takže sa vytlačí iba raz, keď používateľ spustí prvú hru.
- 13Otestujte hru. Musíte si byť istí, že vaša hra funguje aj po implementácii nových funkcií.
- Nezabudnite odpovedať aspoň raz „áno“ aj „nie“, aby ste sa presvedčili, že obe možnosti fungujú. Váš kód by mal vyzerať takto:
import random def numInput (): inp = input () while not inp.isdigit (): print ("Bolo vám povedané zadať celé číslo! Zadajte celé číslo:") inp = input () return int (inp) print („Vitajte v hre na hádanie čísel!“) Pri True: print („Zadajte celé číslo od 1 do 1000:“) rightNum = random.randint (0,1000) userNum = numInput () while userNum! = RightNum: if userNum <rightNum: print ("Príliš malé. Skúste to znova:") ak userNum> rightNum: print ("Príliš veľké. Skúste to znova:") userNum = numInput () print ("Uhádli ste správne.") print ("Myslíte si chcete hrať znova? Ak chcete ukončiť, zadajte Nie. ") ak vstup () ==" Nie ": prestávka
- Nezabudnite odpovedať aspoň raz „áno“ aj „nie“, aby ste sa presvedčili, že obe možnosti fungujú. Váš kód by mal vyzerať takto:
- 14Napíšte ďalšie textové hry. Čo tak napísať textovú adventúru ďalej? Alebo kvízová hra? Buď kreatívny.
Tip: Niekedy je užitočné nahliadnuť do dokumentácie, ak si nie ste istí, ako sa niečo robí alebo ako sa používa funkcia. Dokumentácia k Pythonu 3 sa nachádza na https://docs.python.org/3/. Dobré výsledky niekedy prináša aj hľadanie toho, čo chcete na internete robiť.
Časť 2 zo 4: Vytvorenie hry s 2D grafikou
- 1Vyberte si knižnicu. Vytváranie grafiky je veľmi komplikované a väčšina programovacích jazykov (vrátane Pythonu, C ++, C, JavaScript) poskytuje iba minimálnu alebo dokonca žiadnu podporu grafiky v jadre alebo štandardných knižniciach. Na vytváranie grafiky, napríklad Pygame pre Python, budete teda musieť použiť externú knižnicu.
- Aj s grafickou knižnicou si budete musieť veľa robiť s vecami na nízkej úrovni, ako je napríklad zobrazenie ponuky, ako skontrolovať, či na ňu používateľ klikol, ako zobraziť dlaždice a podobne. Ak sa chcete zamerať na vývoj skutočnej hry a obzvlášť ak je hra, ktorú chcete vytvoriť, komplexná, mali by ste použiť knižnicu herného enginu, ktorá také veci implementuje.
Tento článok použije Python s Cocos2d a ukáže vám, ako vytvoriť jednoduchú 2D plošinovku. Niektoré zo spomínaných konceptov nemusia existovať v iných herných engine. Ďalšie informácie nájdete v ich dokumentácii.
- 2Nainštalujte knižnicu, ktorú ste si vybrali. Cocos2D pre Python sa jednoducho inštaluje pomocou sudo pip3 install cocos2d.
- 3Vytvorte nový adresár. Vo svojej hre budete používať veci ako obrázky a zvuky. Tieto veci by ste mali uchovávať v rovnakom adresári ako program a adresár by nemal obsahovať nič iné, aby ste mohli ľahko vidieť, aké prostriedky v hre máte.
- 4Prejdite do nového adresára a vytvorte nový súbor s kódom. Malo by byť pomenované Hlavná, s príponou súboru vášho programovacieho jazyka. Ak píšete veľký a komplexný program, v ktorom má zmysel mať viac programových súborov, ukáže sa, ktorý je hlavný.
- V tomto prípade tento súbor, ktorý by sa mal volať main.py, bude obsahovať všetok váš kód. Adresár, ktorý ste vytvorili, však bude stále užitočný pre ostatné mediálne súbory.
- 5Vytvorte okno. To je základný predpoklad pre hru s grafikou. Teraz môžete pridať najjednoduchší obsah, napríklad farbu pozadia.
- Importujte potrebné podmoduly cocos2d: cocos.direktor, cocos.scene a cocos.layer. To sa vykoná pomocou from subModuleName import * príkazu, kde subModuleName je submodul, ktorý chcete importovať. Rozdiel medziz... import * a import... je, že nemusíte dávať názov modulu pred všetko, čo používate z toho modulu s prvým.
- Definovať podtriedy MainMenuBgr zColorLayer. To v zásade znamená, že akékoľvek pozadie hlavnej ponuky, ktoré vytvoríte, sa pri niektorých zmenách, ktoré urobíte, bude správať ako farebná vrstva.
- Inicializujte riaditeľa cocos. Tým sa vám otvorí nové okno. Ak nenastavíte nejaký popis, okno bude mať rovnaký nadpis ako názov súboru (main.py), čo nevyzerá veľmi profesionálne. Nastavením povoľte zmenu veľkosti oknameniť veľkosť do Pravda.
- Definujte funkciu showMainMenu. Kód na zobrazenie hlavnej ponuky by ste mali vložiť do funkcie, pretože vám to umožní ľahký návrat do hlavnej ponuky opätovným volaním funkcie.
- Vytvorte scénu. Scéna zatiaľ pozostáva z jednej vrstvy, ktorá je predmetomHlavné menuBgr trieda, ktorú ste definovali.
- Spustite túto scénu v okne.
z cocos.director import * from cocos.scene import * from cocos.layer import * class MainMenuBgr (ColorLayer): def _init_ (self): super (MainMenu, self)._ init_ (0,200,255,255) def showMainMenu (): menuSc = Scene (MainMenuBgr ()) director.run (menuSc) director.init (caption = "IcyPlat - a simple platformer", resizable = True) showMainMenu ()
- 6Vytvorte hlavné menu. Okrem samotnej hry by ste mali mať možnosť hru aj ukončiť. Kredity budete pridávať aj neskôr, ale zatiaľ ich ignorujte. Hlavná ponuka zabráni tomu, aby bol vstup do hry príliš nečakaný.
- Importujte potrebné moduly. Musíte importovaťcocos.menu (opäť s od inštrukcia) a pyglet.app (tentokrát s import).
- Definujte MainMenu ako podtriedu Menu.
- Nastavte zarovnanie hlavnej ponuky. Vertikálne a horizontálne zarovnanie musíte nastaviť oddelene.
- Vytvorte zoznam položiek ponuky a vytvorte skutočné menu. Mali by ste mať položky ponuky „Spustiť hru“ a „Ukončiť“. Uistite sa, že ste každú vytvorenú položku ponuky vložili do zátvoriek. Položka ponuky má štítok a funkciu spätného volania, keď na ňu kliknete. Pri položke „Spustiť hru“ použite startGame funkciu (čoskoro ju napíšete), pri položke „Ukončiť“ použite „pyglet.app.exit“ (už existuje). Aktuálne menu vytvoríte zavolaním self.create_menu(menuItems).
- Definovať startGame(). Zatiaľ vložte pass definíciu a nahradíte ju pri písaní skutočnej hry.
- Prejdite na miesto v kóde, kde ste vytvorili príponu menuSc scénu a pridajte k nej objekt MainMenu.
- Celý váš kód by teraz mal vyzerať nasledovne:
z cocos.director import * from cocos.menu import * from cocos.scene import * from cocos.layer import * import pyglet.app class MainMenuBgr (ColorLayer): def _init_ (self): super (MainMenuBgr, self)._ init_ (0,200,255,255) class MainMenu (Menu): def _init_ (self): super (MainMenu, self)._ init_ ("") self.menu_valign = CENTER self.menu_halign = CENTER menuItems = [(MenuItem ("Start Game", startGame)),, (MenuItem ("Quit", pyglet.app.exit))] self.create_menu (menuItems) def startGame (): pass def showMainMenu (): menuSc = Scene (MainMenuBgr ()) menuSc.add (MainMenu ()) director. spustite (menuSc) director.init (caption = "IcyPlat - a simple platformer", resizable = True) showMainMenu ()
- 7Otestujte si kód. Je dôležité otestovať váš kód v takom ranom štádiu, hoci je stále krátky a relatívne jednoduchý: týmto spôsobom poznáte všetky chyby v základnej štruktúre a môžete ich opraviť skôr, ako spôsobia ďalšie problémy.
- Kód z pokynov by mal otvoriť okno s titulkom „IcyPlat - jednoduchá plošinovka“, ktorého veľkosť môžete zmeniť a ktoré má svetlo modré pozadie. Malo by mať menu s dvoma položkami: keď kliknete na „Spustiť hru“, nič sa nestane; keď kliknete na „Ukončiť“, program sa ukončí.
- 8Zobrazte sprite v hre. Sprite je ako „herný objekt“. Napríklad v plošinovke by to mala byť hlavná postava, ktorú môže hráč ovládať (v tomto kroku sa však iba zobrazí). Veci ako dekorácia pozadia alebo predmet, s ktorým môže hráč komunikovať, môžu byť tiež škriatkovia, ale najskôr by ste mali pridať iba jednu, aby ste porozumeli konceptu, a potom môžete pridať čokoľvek, čo chcete.
- Importujte súbor cocos.sprite submodul s výrazom from-import-expression.
- Nájdite obrázok. Škriatka nemôžete zobraziť, ak k nemu nemáte obrázok. Môžete si ho nakresliť alebo si ho môžete získať z internetu (dávajte si však pozor na licenciu, ak plánujete vydať svoju hru), napríklad odtiaľto (orežte obrázok, aby ste mali iba jedného bežiaceho tučniaka). Uistite sa, že vložíte obrázok do rovnakého adresára ako program.
- Vytvorte vrstvu sprite a sprite. Vytvorte vrstvu ako nový objekt súboruRolovateľná vrstvatrieda. Vytvorte sprite ako aSpriteobjekt a nastavte jeho polohu na (8, 250). Pre referenciu je bod (0, 0) v ľavom dolnom rohu. To je dosť vysoké, ale postará sa o to, aby tučniak nezostal uviaznutý v ľade.
- Pridajte škriatka do vrstvy sprite.
- Vytvorte novú scénu z vrstvy sprite a spustite ju.
def startGame (): figLayer = ScrollableLayer () fig = Sprite ('pingu.png') fig.position = (75, 100) figLayer.add (obr) # gameSc = Scene (figLayer) director.run (gameSc)
- Ak chcete, môžete teraz spustiť svoj kód. Uvidíte malý tučniak postavu (alebo čo ste čerpal) na čiernom pozadí po kliknutí na "Start Game".
- 9Rozhodnite sa, z čoho bude vaša krajina pozostávať. Vo väčšine hier by sa vaši škriatkovia nemali len vznášať v prázdnote. V skutočnosti by mali stáť na nejakom povrchu s niečím okolo nich. V 2D hrách sa to často robí pomocou sady dlaždíc a mapy dlaždíc. Set dlaždice v podstate hovorí, aký druh povrchu námestia a pozadia štvorca existujú, a ako vyzerajú.
- Vytvorte sadu dlaždíc. Sada dlaždíc pre túto hru bude veľmi základná: jedna dlaždica na ľad a jedna dlaždica na oblohu. Ľadové dlaždice použité v tomto prípade sú odtiaľto, pod CC-BY-SA 3,0.
- Vytvorte obrázok sady dlaždíc. Toto je obrázok všetkých dlaždíc, ktoré musia mať všetky rovnakú veľkosť (ak nie sú, upravte ich) a musia mať takú veľkosť, akú chcete v hre vidieť, vedľa seba. Uložte svoj obrázok ako icyTiles.png.
- Vytvorte popis sady dlaždíc. Je to súbor XML. Súbor XML obsahuje informácie o tom, aké veľké sú dlaždice na obrázku sady dlaždíc, ktorý obrázok sa má použiť a kde sa nachádza dlaždica. Vytvorte súbor XML icyTiles.xml s nasledujúcim kódom:
<? xml version = "1,0"?> <resource> <imageatlas size = "16x16" file = "icyTiles.png"> <image id = "i-ice" offset = "00" /> <image id = "i-sky" offset = "160" /> </imageatlas> <tileset> <tile id = "ice"> <image ref = "i-ice" /> </tile> <tile id = "sky"> <image ref = "i-sky"/> </tile> </tileset> </resource>
- 10Vytvorte skutočnú štruktúru z prvkov vašej krajiny. Ak ste vyrobili sadu dlaždíc, malo by to byť vykonané vo forme mapy dlaždíc. Dlaždičková mapa je ako mapa, ktorá definuje, ktorá dlaždica sa nachádza na ktorej pozícii na vašej úrovni. V tomto prípade by ste mali definovať funkciu generovania máp, pretože ručné navrhovanie máp je veľmi únavné. Pokročilejšia hra by zvyčajne mala nejaký editor úrovní, ale na zoznámenie sa s vývojom 2D hier môže algoritmus poskytnúť dostatočne dobré úrovne.
- Zistite, koľko riadkov a stĺpcov je potrebných. Za týmto účelom rozdeľte veľkosť obrazovky na veľkosť dlaždíc horizontálne (stĺpce) a vertikálne (riadky). Zaokrúhlite číslo nahor; Na to potrebujete funkciu matematického modulu, takže pridajte k importom v hornej časti kódu.from math import ceil
- Otvorte súbor na zápis. Týmto vymažete všetok predchádzajúci obsah súboru, preto zvoľte názov, ktorý zatiaľ nemá žiadny súbor v adresári, napríklad levelMap.xml.
- Do súboru napíšte úvodné značky.
- Vygenerujte mapu dlaždíc podľa algoritmu. Ten použijete v nižšie uvedenom kóde, alebo si naň môžete prísť sami. Nezabudnite importovať súborrandint funkciu z modulu náhodný: Aby kód uvedený nižšie fungoval, je potrebný a čokoľvek, s čím prídete, bude pravdepodobne potrebovať aj náhodné celé čísla. Nezabudnite tiež dať obklady a ľadové dlaždice do rôznych vrstiev: ľad je pevný, obloha nie.
- Zapíšte záverečné značky do súboru a zatvorte súbor.
def generateTilemap (): colAmount = ceil (800 /16) * 3 # (šírka obrazovky / veľkosť dlaždice) * 3 rowAmount = ceil (600 /16) # výška obrazovky / veľkosť dlaždice tileFile = otvorený ("levelMap.xml", " w ") tileFile.write ('<zdroj> \ n <vyžaduje súbor =" icyTiles.xml " /> \ n <rectmap id =" solid "origin =" 00,1" tile_size =" 16x16" > \ n') iceHeight = randint (1,10) pre i v rozsahu (0, colAmount): tileFile.write ('<column>') makeHole = False if randint (0,50) == 10 a i! = 0: # don ' t povoliť otvory v mieste spawn makeHole = True pre j v rozsahu (0, rowAmount): if makeHole: tileFile.write ('<cell /> \ n') else: if j <= iceHeight: tileFile.write ('<bunka tile = "ice" /> \ n ') else: tileFile.write (' <cell /> \ n ') iceHeight = randint (iceHeight-5,iceHeight+5) if iceHeight <0: # limit tiles from goes too low iceHeight = randint (1,5) if iceHeight> rowAmount: # limit tiles from goes too high iceHeight = randint (int (rowAmount/2) -5, int (rowAmount/2) +5) tileFile.write ('</column> \ n') tileFile.write ('</rectmap> \ n <rectmap id = "not_solid" origin = "00,0" tile_size = "16x16" > \ n ') pre i v rozsahu (0, colAmount): tileFile.write (' <column> ') pre j v rozsahu (0, rowAmount): tileFile.write (' <cell tile =" sky " /> \ n ') tileFile.write (' </column> \ n ') tileFile.write (' </rectmap> \ n </resource> \ n ') tileFile.close ()# obmedziť počet dlaždíc, aby neprekročili ľad > \ n <rectmap id = "not_solid" origin = "00,0" tile_size = "16x16"> \ n ') pre i v rozsahu (0, colAmount): tileFile.write (' <column> ') pre j in rozsah (0, rowAmount): tileFile.write ('<cell tile = "sky"/> \ n') tileFile.write ('</column> \ n') tileFile.write ('</rectmap> \ n < /resource> \ n ') tileFile.close ()# obmedziť počet dlaždíc, aby neprekročili ľad > \ n <rectmap id = "not_solid" origin = "00,0" tile_size = "16x16"> \ n ') pre i v rozsahu (0, colAmount): tileFile.write (' <column> ') pre j in rozsah (0, rowAmount): tileFile.write ('<cell tile = "sky"/> \ n') tileFile.write ('</column> \ n') tileFile.write ('</rectmap> \ n < /resource> \ n ') tileFile.close ()) pre j v rozsahu (0, rowAmount): tileFile.write ('<cell tile = "sky"/> \ n') tileFile.write ('</column> \ n') tileFile.write ('</rectmap > \ n </resource> \ n ') tileFile.close ()) pre j v rozsahu (0, rowAmount): tileFile.write ('<cell tile = "sky"/> \ n') tileFile.write ('</column> \ n') tileFile.write ('</rectmap > \ n </resource> \ n ') tileFile.close ()
- 11Zobrazte mapu dlaždíc. Importujte všetko z cocos.tiles a potom prejdite do priečinka začať hru funkciu na to.
- Na začiatku vášho začať hru funkciu, vygenerujte mapu dlaždíc pomocou funkcie, ktorú ste pre to definovali.
- Vytvorte nového správcu posúvania. Vykonajte to priamo pod čiarou, do ktorej pridáte sprite do jeho vrstvy.
- Vytvorte novú vrstvu obsahujúcu dlaždice, ktoré sa načítajú z levelMap.xml dlaždicová mapa vášho generateTilemap generovaná funkcia.
- Pridajte nepevnú vrstvu, plnú vrstvu a vrstvu sprite do správcu posúvania, presne v tomto poradí. Ak chcete, môžete pridať pozíciu z.
- Namiesto vytvárania scény z vrstvy sprite ju vytvorte v správcovi posúvania.
- Tvoj začať hru funkcia by teraz mala vyzerať takto:
def startGame (): generateTilemap () # fig = Sprite ('pingu.png') fig.position = (8, 500) figLayer = ScrollableLayer () figLayer.add (obr) # tileLayer = load ('levelMap.xml') solidTiles = tileLayer ['solid'] nsoliTiles = tileLayer ['not_solid'] # scrMang = ScrollingManager () scrMang.add (nsoliTiles, z = -1) scrMang.add (solidTiles, z = 0) scrMang.add (figLayer, z = 1) # gameSc = scéna (scrMang) director.run (gameSc)
- 12Otestujte si kód. Kód by ste mali často testovať, aby ste sa presvedčili, že nové funkcie, ktoré ste implementovali, skutočne fungujú.
- Kód v príklade by teraz mal zobrazovať ľadovú krajinu za tučniakom. Ak tučniak vyzerá, že sa vznáša ďaleko nad ľadom, neurobili ste nič zlé a v nasledujúcom kroku to bude napravené.
- 13Pridajte ovládacie prvky. Hráč má oveľa viac spôsobov interakcie s programom v 2D hre ako v textovej hre. Bežný obsahuje pohyb ich figúrky po stlačení správneho klávesu.
- Importujte všetko z cocos.mapcolliders a z cocos.actions. Importovať aj key z pyglet.window.
- „Deklarujte“ niektoré globálne premenné. Globálne premenné sú zdieľané medzi funkciami. V Pythone nemôžete skutočne deklarovať premenné, ale musíte povedať, že pred použitím ho v hlavnom kóde existuje globálna premenná. Ako hodnotu môžete priradiť 0, pretože funkcia sa neskôr postará o priradenie správnej hodnoty. Pridajte teda pod výrazy importu:
# klávesnica globálnych premenných „deklaruje“ = 0 scrMang = 0
- Upravte svoje začať hru funkcia:
- Povedzme, že používate globálne premenné klávesnica a scrMang. Vykonajte to napísaním global keyboard, scrMang v hornej časti funkcie.
- Nechajte okno počúvať udalosti klávesnice.
- Povedzte figúre, aby konala na základe a PlatformerController. Budete to implementovaťPlatformerController čoskoro.
- Vytvorte mapový urýchľovač, ktorý zvládne kolízie medzi plnými dlaždicami a figúrkou.
def startGame (): globálna klávesnica, scrMang generateTilemap () # fig = Sprite ('pingu.png') fig.position = (8, 250) figLayer = ScrollableLayer () figLayer.add (obr) # tileLayer = načítať ('levelMap.xml ') solidTiles = tileLayer [' solid '] nsoliTiles = tileLayer [' not_solid '] # keyboard = key.KeyStateHandler () director.window.push_handlers (keyboard) # fig.do (PlatformerController ()) mapcollider = RectMapCollider (velocity_on_bump = 'slide') fig.collision_handler = make_collision_handler (mapcollider, solidTiles) # scrMang = ScrollingManager () scrMang.add (nsoliTiles, z = -1) scrMang.add (solidTiles, z = 0) scrMang.add (figLayer, z = 1) # gameSc = scéna (scrMang) director.run (gameSc)
- Vytvorte ovládač plošinovky. Práve to posunie figúrku podľa vašich stlačení klávesov.
- Definujte ovládač plošinovky ako podtriedu Akcia.
- Definujte rýchlosť pohybu, rýchlosť skoku a gravitáciu.
- Definujte začaťfunkciu. Táto funkcia sa volá raz, keď je ovládač plošinovky pripojený k obrázku. Mala by nastaviť svoju rýchlosť na 0 v smere x aj v smere y.
- Definujte krokfunkciu. Bude sa to opakovať, kým bude scéna bežať.
- Povedz krok funkciu na používanie globálnych premenných klávesnica a scrMang.
- Získajte a zmeňte rýchlosť. Uložte rýchlosť x a y do oddelených premenných. Nastavte rýchlosť x buď na 1 alebo -1 (v závislosti od toho, či bolo stlačené ľavé alebo pravé tlačidlo) vynásobené rýchlosťou pohybu. Pridajte k rýchlosti y gravitáciu. Vynásobte to prestojmi, aby to fungovalo rovnako na pomalších zariadeniach. Ak stlačíte medzerník a postava stojí na zemi, skočte zmenou rýchlosti y na rýchlosť skoku.
- Vypočítajte, kam sa má figúrka posunúť. Potom nechajte obsluhu kolízie upraviť túto polohu, ak je vo vnútri pevnej dlaždice. Nakoniec figúrku presuňte do novej upravenej polohy.
- Nastavte zameranie správcu posúvania na obrázok. To spôsobuje, že sa fotoaparát pohybuje rozumným spôsobom, keď sa postava pohybuje.
class PlatformerController (Action): global keyboard, scrMang on_ground = True MOVE_SPEED = 300 JUMP_SPEED = 500 GRAVITY = -1200 def start (self): self.target.velocity = (0, 0) def step (self, dt): global keyboard, scroller ak dt> 0,1: # nerobte nič počas prestojov na veľký návrat vx, vy = self.target.velocity vx = (keyboard [key.RIGHT] - keyboard [key.LEFT]) * self.MOVE_SPEED vy += self.GRAVITY * dt if self.on_ground a keyboard [key.SPACE]: vy = self.JUMP_SPEED dx = vx * dt dy = vy * dt last = self.target.get_rect () new = last.copy () new.x += dx new.y += dy self.target.velocity = self.target.collision_handler (last, new, vx, vy) self.on_ground = (new.y == last.y) self.target.position = new.center scrMang.set_focus (*new.center)
- 14Otestujte si kód. Ak ste nasledovali príklad, tučniaka by ste teraz mali presúvať pomocou klávesov so šípkami a skákať stlačením medzerníka. Tučniak by teraz mal padnúť nadol namiesto toho, aby sa vznášal nad zemou.
- 15Nech sa hra skončí. Dokonca aj hry, ktoré môžu pokračovať donekonečna, majú možnosť ich ukončiť prehrou. A pretože úroveň, ktorú ste v príklade urobili s funkciou, má koniec, malo by byť možné tiež vyhrať tým, že prídete na tento koniec: V opačnom prípade by hráč iba skákal po ľadových blokoch, ktoré by po určitom čase nudili..
- V ovládači plošinovky po zaostrení nastavte polohu x a y figúrky. Ak je pozícia y menšia ako 0, zavolajte funkciu finishGame()(ako neskoršie ju napíšete) "Game Over" ako argument. Ak je pozícia x väčšia ako veľkosť obrazovky vynásobenej číslom 3 (predtým ste ju nastavili ako veľkosť úrovne).
posX, posY = self.target.position if posY <0: finishGame ("Game Over") návrat ak posX> 800*3: # úroveň veľkosť finishGame ("úroveň dokončená") návrat
- Definujte triedu finishMenu. Mala by byť ako trieda hlavnej ponuky, ktorú ste definovali predtým, ale namiesto prázdneho reťazca ako názvu by mala používať premennútext ktoré _init_funkcia berie ako argument. Položky ponuky by mali mať označenie „Skúste to znova“ a „Ukončiť“, ale funkcie, ktoré volajú, zostanú rovnaké.
class FinishMenu (Menu): def _init_ (self, text): super (FinishMenu, self)._ init_ (text) self.menu_valign = CENTER self.menu_halign = CENTER menuItems = [(MenuItem („Try again“, startGame))), (Položka ponuky („Ukončiť“, pyglet.app.exit))] self.create_menu (položky ponuky)
- Definujte funkciu finishGame (). Malo by to trvaťtextako argument. Malo by to urobiť scénu z pozadia hlavnej ponuky, aFinishMenu s textargument sa prenáša do tohto menu. Potom by mala spustiť túto scénu.
def finishGame (text): menuSc = Scene (MainMenuBgr ()) menuSc.add (FinishMenu (text)) director.run (menuSc)
- V ovládači plošinovky po zaostrení nastavte polohu x a y figúrky. Ak je pozícia y menšia ako 0, zavolajte funkciu finishGame()(ako neskoršie ju napíšete) "Game Over" ako argument. Ak je pozícia x väčšia ako veľkosť obrazovky vynásobenej číslom 3 (predtým ste ju nastavili ako veľkosť úrovne).
- 16Pridajte kredity. To je zvyčajne nevyhnutné, ak ste použili médiá, ktoré ste neurobili, aby ste uviedli autora. Tiež budete pravdepodobne chcieť, aby hráči vedeli, že ste hru napísali. Kredity by mali byť zahrnuté v hre, aby ich mohol vidieť ktokoľvek, kto si nainštaluje vašu hru, bez toho, aby ste sa museli hlboko pozerať do súborov hry.
- Vytvorte súbor CREDITS a zadajte tam všetky svoje kredity takto:
Tučniak: Kelvin Shadewing, pod CC0 Ice block: Michał Banas digit1024 na opengameart.org pod CC-BY-SA 3.0
- Vráťte sa k svojmu kódu Python a importujte Label z cocos.text.
- Definujte podtriedu Kredity z Vrstva. V jeho_init_ funkciu, prečítajte si ÚVERY vytvorte súbor a vytvorte textový štítok na správnom mieste z každého riadka v ňom.
trieda Kredity (Layer): def _init_ (self): super (Credits, self)._ init_ () credFile = open ("CREDITS", "r") creds = credFile.read () creds = creds.split ("\ n ") pre i v rozsahu (0, len (creds)): credLabel = Label (creds [i], font_size = 32, anchor_x =" left ", anchor_y =" top ") credLabel.position = 25,500- (i+1)*40 self.add (credLabel)
- Prejdite do triedy hlavnej ponuky a pridajte položku ponuky s názvom „Kredity“, ktorá volá túto funkciushowCredits po kliknutí.
- Definujte podtriedu Tlačidlo BackToMainMenu z Ponuka. Vytvoriť z tejto ponuky jednu položku s názvom „Späť“, ktorá voláshowMainMenufunkciu. Toto „menu“, ktoré je skôr ako tlačidlo, by malo byť zvisle zarovnané dole a vodorovne hore.
trieda BackToMainMenuButton (Menu): def _init_ (self): super (BackToMainMenuButton, self)._ init_ ("") self.menu_valign = BOTTOM self.menu_halign = LEFT menuItems = [(MenuItem ("Back", showMainMenu))] self. create_menu (položky ponuky)
- Definujte funkciu showCredits. Malo by to urobiť scénu z aHlavné menuBgr vrstva a a Kredity vrstvu a spustite tú scénu.
def showCredits (): credSc = Scene (MainMenuBgr ()) credSc.add (Credits ()) credSc.add (BackToMainMenuButton ()) director.run (credSc)
- Vytvorte súbor CREDITS a zadajte tam všetky svoje kredity takto:
- 17Skontrolujte svoj kód. Keď si myslíte, že ste kód dokončili, mali by ste si ho znova pozrieť. Pomôže vám to zistiť, či je možné niečo optimalizovať alebo či ste zabudli odstrániť nepotrebné riadky. Ak ste nasledovali príklad, celý váš kód by teraz mal vyzerať nasledovne:
z cocos.director import * from cocos.menu import * from cocos.scene import * from cocos.layer import * from cocos.sprite import * from cocos.tile import * from cocos.mapcolliders import * from cocos.actions import * from cocos.text import Štítok import pyglet.app z pyglet.window import kľúč z matematiky import strop z náhodného importu randint # "deklarovanie" globálnych premenných klávesnica = 0 scrMang = 0 trieda MainMenuBgr (ColorLayer): def _init_ (self): super (MainMenuBgr, self)._ init_ (0,200,255,255) trieda MainMenu (Menu): def _init_ (self): super (MainMenu, self)._ init_ ("") self.menu_valign = CENTER self.menu_halign = CENTER menuItems = [(MenuItem ("Start Game ", startGame)), (MenuItem (" Credits ", showCredits)), (MenuItem (" Quit ", pyglet.app.exit))]] self.create_menu (menuItems) trieda Kredity (vrstva):def _init_ (self): super (Credits, self)._ init_ () credFile = open ("CREDITS", "r") creds = credFile.read () creds = creds.split ("\ n") pre i v rozsahu (0, len (creds)): credLabel = Label (creds [i], font_size = 32, anchor_x = "left", anchor_y = "top") credLabel.position = 25,500- (i+1)*40 self.add Trieda (credLabel) BackToMainMenuButton (Menu): def _init_ (self): super (BackToMainMenuButton, self)._ init_ ("") self.menu_valign = BOTTOM self.menu_halign = LEFT menuItems = [(MenuItem ("Back", showMainMenu)] self.create_menu (menuItems) trieda FinishMenu (Menu): def _init_ (self, text): super (FinishMenu, self)._ init_ (text) self.menu_valign = CENTER self.menu_halign = CENTER menuItems = [(MenuItem ("Skúste opäť ", startGame)), (MenuItem (" Quit ", pyglet.app.exit))] self.create_menu (menuItems) class PlatformerController (Action): global keyboard, scrMang on_ground = True MOVE_SPEED = 300 JUMP_SPEED = 500 GRAVITY = -1200 def start (self): self.target.velocity = (0, 0) def step (self, dt): globálna klávesnica, posúvač, ak dt> 0,1: # nerobte nič, kým sú prestoje príliš veľké, návrat vx, vy = self.target.velocity vx = (klávesnica [key.RIGHT] - klávesnica [key.LEFT]) * self.MOVE_SPEED vy += self.GRAVITY * dt if self.on_ground a keyboard [key.SPACE]: vy = self.JUMP_SPEED dx = vx * dt dy = vy * dt last = self.target.get_rect () new = last.copy () new.x += dx new.y += dy self.target.velocity = self.target.collision_handler (last, new, vx, vy) self.on_ground = (new.y == last.y) self.target.position = new.center scrMang.set_focus (*new.center) posX, posY = self.target.position if posY <0: finishGame ("Game Over") return if posX> 800*3: # level size finishGame ("Level Completed") return def finishGame (text): menuSc = Scene (MainMenuBgr ()) menuSc.add (FinishMenu (text)) director.run (menuSc) def showCredits (): credSc = scéna (MainMenuBgr ()) credSc.add (Credits ()) credSc.add (BackToMainMenuButton ()) director.run (credSc) def generateTilemap (): colAmount = ceil (800 /16)*3 # (šírka obrazovky / veľkosť dlaždice) * 3 riadkyMnožstvo = strop (600/16) # výška obrazovky / veľkosť dlaždice tileFile = otvorený ("levelMap.xml", "w") tileFile.write ('<zdroj> \ n <vyžaduje súbor = "icyTiles.xml" /> \ n <rectmap id = "solid" origin = "00,0" tile_size = "16x16"> \ n ') iceHeight = randint (1,10) pre i v rozsahu (0, colAmount): tileFile.write ('<column>') makeHole = False if randint (0,50) == 10 and i! = 0: # don 't povoliť otvory v mieste spawn makeHole = True pre j v rozsahu (0, rowAmount): if makeHole: tileFile.write ('<cell /> \ n') else: if j <= iceHeight: tileFile.write ('<bunka tile = "ice" /> \ n ') else: tileFile.write (' <bunka /> \ n ') iceHeight = randint (iceHeight-5, iceHeight+5) if iceHeight <0: # obmedzuje chod dlaždíc príliš nízko iceHeight = randint (1,5) if iceHeight> rowAmount: # limit tiles from being too high iceHeight = randint (int (rowAmount/2) -5, int (rowAmount/2) +5) tileFile.write ('</column > \ n ') tileFile.write (' </rectmap> \ n <rectmap id = "not_solid" origin = "00,0" tile_size = "16x16"> \ n ') pre i v rozsahu (0, colAmount): tileFile.write ('<column>') pre j v rozsahu (0, rowAmount): tileFile.write ('<cell tile = "sky" />\ n ') tileFile.write (' </column> \ n ') tileFile.write (' </rectmap> \ n </resource> \ n ') tileFile.close () def startGame (): globálna klávesnica, scrMang generateTilemap () # fig = Sprite ('pingu.png') fig.position = (8, 250) figLayer = ScrollableLayer () figLayer.add (obr) # tileLayer = zaťaženie ('levelMap.xml') solidTiles = tileLayer [' solid '] nsoliTiles = tileLayer [' not_solid '] # keyboard = key.KeyStateHandler () director.window.push_handlers (keyboard) # fig.do (PlatformerController ()) mapcollider = RectMapCollider (velocity_on_bump =' slide ') fig.collision_handler = make_collision_handler (mapcollider, solidTiles) # scrMang = ScrollingManager () scrMang.add (nsoliTiles, z = -1) scrMang.add (solidTiles, z = 0) scrMang.add (figLayer, z = 1) # gameSc = scéna (scrMang) director.run (gameSc) def showMainMenu ():menuSc = scéna (MainMenuBgr ()) menuSc.add (MainMenu ()) director.run (menuSc) okno = director.init (caption = "IcyPlat - a simple platformer", resizable = True) showMainMenu ()
- To je spolu 168 riadkov a 152 riadkov, ak počítate iba kód. Zdá sa to veľa, ale pre takú komplexnú hru je to skutočne malé množstvo.
- 18Hotovo. Teraz vyskúšajte hru. Keď niečo programujete, musíte skontrolovať, či to funguje, vždy, keď ste implementovali niečo nové. Tiež by ste si mohli nejaký čas zahrať hru, ktorú ste napísali.
Časť 3 zo 4: Vytvorenie hry s 3D grafikou
- 1Vyberte si nástroje. 3D grafika je ešte komplikovanejšia ako 2D grafika a vyžaduje si vlastné knižnice. Opäť môžete nájsť engine užitočný na veci, ako je detekcia kolízií v hre.
- Pre väčšinu hier budete potrebovať alebo upraviť 3D modely. Mali by ste teda mať aspoň základné znalosti o programe na úpravu 3D, ako je Blender.
Tento článok ukáže, ako vytvoriť hru Pong v 3D pomocou Panda3d.
- 2Nainštalujte nástroje. Panda3D je možné nainštalovať s. Program Blender je možné nainštalovať buď zo správcu balíkov vášho systému, alebo z jeho webových stránok. python3 -m pip install - extra-index-url https://archive.panda3d.org/ panda3d
- 3Vytvorte nový adresár. V tomto priečinku by ste mali ponechať všetky súbory pre svoju hru. Vďaka tomu budete mať v počítači poriadok a rýchlo uvidíte, aké súbory pre program máte.
- 4Vytvorte prázdne okno.
- Importovať knižnicu, ktorá je nevyhnutná pre vytvorenie okna: from direct.showbase.ShowBase import ShowBase. Tiež importujte všetko z panda3d.core knižnice (s from panda3d.core import *).
- Definujte podtriedu MyApp z ShowBase.
- Vo svojej inicializačnej funkcii napíšte
loadPrcFileData ('', '3D nadpis okna')
- Vytvorte predmet aplikácia triedy MyApp. Spustením zobrazte okno.
from direct.showbase.ShowBase import ShowBase from panda3d.core import * class MyApp (ShowBase): def _init_ (self): loadPrcFileData ('', 'window-title 3D Pong') ShowBase._init_ (self) app = MyApp () app.run ()
- 5Vytvorte 3D model. Veci, ktoré chcete v 3D hre predvádzať, musíte najskôr vytvoriť v programe na úpravu 3D, napríklad v programe Blender. Mali by ste začať s jedným 3D modelom, pridať ho a až potom pokračovať k ďalším. Vyhnete sa tak nutnosti opakovať veľa práce, ak spočiatku robíte niečo zle. Uistite sa, že vaše 3D modely nie sú zbytočne zložité, pretože to môže spomaliť hru.
- Otvorte mixér. Odstráňte predvolenú kocku a namiesto toho pridajte „Ico Sphere“. V samotnom Blenderi sa to nezdá byť veľmi sférické, ale v skutočnej hre to vyzerá dosť blízko k sfére. Mohli ste použiť UV sféru, ale je oveľa komplikovanejšia a vykreslenie trvá viac času.
Varovanie: Zaistite, aby bol každý objekt v programe Blender vycentrovaný na bod (0, 0, 0) a aby mal pôvod v strede svojej hmotnosti (použite Objekt → Transformovať → Počiatok na ťažisko). V opačnom prípade budú neskôr problémy s detekciou kolízií.
- 6Exportujte do formátu, ktorý môže používať vaša 3D knižnica. Rovnako ako pre 2D obrázky existujú pre 3D modely rôzne formáty. Mali by ste použiť takú, ktorej vaša 3D knižnica dokáže porozumieť a ukázať ju. Ak si nie ste istí, ktoré formáty podporuje, prečítajte si jeho dokumentáciu.
- Napríklad musíte exportovať model lopty do formátu Panda3D. Najprv uložte svoj model ako normálny.miešaťsúbor. To vám umožní vykonať zmeny, ak potrebujete, aby lopta vyzerala inak. Použite nejaký rozumný názov súboru, ktorý si môžete zapamätať ball.blend.
- V programe Blender povoľte export do formátu DirectX. V takom prípade prejdite na položku Súbor → Používateľské predvoľby... alebo stlačte Ctrl+ Alt+ U. V okne, ktoré sa otvorí, vyberte kategóriu Import-Export. NájsťFormát DirectX Xa začiarknite políčko vpravo od neho. Kliknite na položku Uložiť používateľské nastavenia a zatvorte okno.
- Exportujte model do formátu DirectX X tak, že prejdete na položku Súbor → Exportovať → DirectX (.x), zadáte názov súboru (znova vyberte niečo ako ball.x a kliknite na položku Exportovať DirectX.
- Previesť DirectX .X na Panda3D .vaj. Panda3D už na to poskytuje nástroj. Hovorí sa tomux2egg a syntax je nasledujúca: vstup x2egg.x výstup.egg. Takže previesť súbor, typ: x2egg ball.x ball.egg.
- 7Vložte model do svojho programu. Práve to vám v skutočnosti umožní vidieť to v programe a niečo s tým urobiť.
- Nastavte farbu pozadia na čiernu. Vďaka tomu budete môcť lepšie vidieť načítané modely. To sa robí ako nastavenie titulku, ale s ďalšou možnosťou:
loadPrcFileData ('', 'farba pozadia 0 0 0 0')
- Prejdite na koniec _init_funkciu. Naložte model s
seba. lopta = nakladač. loadModel ("ball.egg")
- Vykreslite načítaný model. To sa vykonáva pomocou ball.reparentTo(self.render).
- Nastavte správnu polohu lopty. Na začiatku by malo byť 0, 0, 0. Prvá súradnica je vľavo/vpravo, druhá je vpred/vzad, tretia je dole/hore. Príkaz na to je self.ball.setPos(0, 0, 0).
- Ak ešte nič nevidíte, je to normálne. Skúste myšou pohnúť nahor a súčasne držať stlačené pravé tlačidlo. Potom by ste to mali vidieť. Dôvodom je, že kamera je tiež na 0, 0, 0 - vo vnútri gule - takže ju nevidíte. Pravé tlačidlo myši posúva fotoaparát dopredu a dozadu.
- Nastavte farbu pozadia na čiernu. Vďaka tomu budete môcť lepšie vidieť načítané modely. To sa robí ako nastavenie titulku, ale s ďalšou možnosťou:
- 8Nastavte polohu kamery. Fotoaparát by mal byť v polohe, v ktorej je všetko dobre viditeľné. Pretože to nie je nevyhnutne prípad, a pretože predvolené nastavenia sa môžu líšiť od platformy k platforme v rovnakom softvéri, polohu kamery by ste mali nastaviť explicitne.
- Najprv musíte vypnúť ovládanie myšou, inak Panda3D odmieta nastaviť kameru na iné miesto v programe. Potom môžete skutočne nastaviť polohu kamery. Váš kód by teraz mal vyzerať nasledovne:
from direct.showbase.ShowBase import ShowBase from panda3d.core import * class MyApp (ShowBase): def _init_ (self): # Initialize the window loadPrcFileData ('', 'window-title 3D Pong') loadPrcFileData ('', 'background -color 0 0 0 0') ShowBase._init_ (self) # Load model loptičky self.ball = loader.loadModel ("ball.egg") self.ball.reparentTo (self.render) self.ball.setPos (0, 0, 0) # Nastavte správnu polohu kamery self.disableMouse () camera.setPos (0, -30,0) app = MyApp () app.run ()
- 9Nastavte zvyšok scény. Pri vytváraní a načítaní jedného modelu môžete pokračovať vo vytváraní a pridávaní ďalších, ktoré potrebujete pre svoju scénu.
- Pridajte steny a netopiere. Postupujte podľa krokov popísaných pre loptu, okrem toho, že nemusíte znova povoliť exportér DirectX. Napriek tomu, že sú tam štyri steny a dva netopiere, stačí vám jeden model oboch. Zo steny urobte tenký obdĺžnik, ktorý pokrýva celú „podlahu“ mixéra, a z netopiera tenký štvorec, ktorý je vysoký približne 2 jednotky mixéra. V kóde budete musieť manuálne nastaviť polohy, otočenia a mierky tak, aby sa konce stien navzájom dotýkali a vytvorili uzavretý tvar. Môžete sa pokúsiť nájsť správne čísla sami, alebo sa pozrieť do kódu nižšie, ktorý patrí do súboru_init_funkcia, kde je načítaný model lopty. Fotoaparát musíte tiež nastaviť bližšie k používateľovi na -60 namiesto -30.
# Načítať steny modely wallLeft = loader.loadModel ("wall.egg"); wallLeft.reparentTo (self.render) wallLeft.setPosHprScale (-15,0,0, 0,0,90, 2,2,1) wallRight = loader.loadModel ("wall.egg"); wallRight.reparentTo (self.render) wallRight.setPosHprScale (15,0,0, 0,0,90, 2,2,1) wallBottom = loader.loadModel ("wall.egg"); wallBottom.reparentTo (self.render) wallBottom.setPosHprScale (0,0,15, 0,0,0, 2,2,1) wallTop = loader.loadModel ("wall.egg"); wallTop.reparentTo (self.render) wallTop.setPosHprScale (0,0, -15, 0,0,0, 2,2,1) # Načítajte netopierie modely self.batPlay = loader.loadModel ("bat.egg"); batPlay.reparentTo (self.render) self.batPlay.setPos (-5, -15, -5) self.batPlay.setScale (3,1,3) self.batOpp = loader.loadModel ("bat.egg"); batOpp.reparentTo (self.render) self.batOpp.setPos (5,15, -5) self.batOpp.setScale (3,1,3)
- 10Pridajte osvetlenie. Teraz sú prítomné všetky objekty, ale nevyzerá to celkom prirodzene a je ťažké vidieť hĺbku. Dá sa to napraviť osvetlením. Všimnite si toho, že samotné svetlá nebudú viditeľné a že existujú rôzne druhy svetiel. Pre ukážkovú hru potrebujete tieto:
- Bodové svetlá. Vyžarujú svetlo všetkými smermi, ako nekonečne malá žiarovka. Pretože osvetľujú rôzne objekty rozdielne kvôli smeru a vzdialenosti, vytvoria tiene, vďaka ktorým bude scéna vyzerať prirodzenejšie.
- Okolité svetlá. V skutočnosti nemajú smer ani polohu, iba osvetľujú celú scénu rovnakým spôsobom. To nemôže pomôcť hĺbkovému vnímaniu, ale zaisťuje, že je všetko dobre viditeľné.
- Pridajte svetlá s nasledujúcim kódom:
# Lighting alight = AmbientLight ('alight') alight.setColor (VBase4 (0,1, 0,1, 0,1, 1)) alnp = render.attachNewNode (alight) render.setLight (alnp) plight = PointLight (' plight ') plight.setColor (VBase4 (0,9, 0,9, 0,9, 1)) plnp = render.attachNewNode (plight) plnp.setPos (0, -16,0) render.setLight (plnp)
- 11Pridajte ovládacie prvky. Rovnako ako v iných typoch hier, hráč by mal byť schopný nejakým spôsobom interagovať s herným svetom. Rovnako ako v 2D hrách je v 3D hrách bežný spôsob, ako prinútiť figúrku, aby urobila niečo po stlačení správnych kláves.
- V prípade tohto programu by ste mali pálkou pohnúť po stlačení klávesu. Po stlačení klávesu sa udalosť nazýva rovnako ako kláves. Podržaním klávesu sa spustí séria udalostí nazývaných ako klávesy s-opakovať nakoniec.
- Aktivujte program tak, aby vyvolal funkciu po stlačení klávesu. To sa robí pomocouseba.prijatiefunkciu. Napríklad volanie funkciepohyb vľavo keď kľúč aje stlačené by bolo vykonané s self.accept("a", moveLeft). Do svojho súboru zadajte nasledujúci kód_init_ funkcia:
# Pohyb po stlačení klávesu self.accept ("a", self.moveLeft) self.accept ("a-repeat", self.moveLeft) self.accept ("d", self.moveRight) self.accept ("d- repeat ", self.moveRight) self.accept (" w ", self.moveUp) self.accept (" w-repeat ", self.moveUp) self.accept (" s ", self.moveDown) self.accept (" s-repeat ", self.moveDown)
- Definujte funkcie, ktoré sú vyvolané udalosťami. Vhodne posunú hráčovu palicu. Uistite sa, že funkcie sú stále v triedeMyApp.
def moveLeft (self): self.batPlay.setX (self.batPlay.getX ()-1) def moveRight (self): self.batPlay.setX (self.batPlay.getX ()+1) def moveUp (self): self.batPlay.setZ (self.batPlay.getZ ()+1) def moveDown (self): self.batPlay.setZ (self.batPlay.getZ ()-1)
- 12Pridajte detekciu kolízií. Detekcia kolízií vám umožňuje všimnúť si, či sú dva objekty vo vnútri seba, a urobiť správne opatrenia. Môžete ho použiť napríklad na zabránenie prechodu hráča cez stenu alebo na to, aby sa niečo, čo je odhodené, odrazilo, keď dopadne na podlahu.
- Najprv by ste mali vykonať detekciu kolízií pre netopiere, pretože to môžete teraz vyskúšať. Detekciu kolízií pre loptu pridáte neskôr, pretože vyžaduje rôzne akcie.
- Pridajte kolízny traverz. Toto je predpokladom akejkoľvek detekcie kolízií v Panda3D a vykonáva sa s
základňa. cTrav = CollisionTraverser ()
základňa. cTrav. showCollisions (render)
- Vytvorte si oznamovateľa. Ako naznačuje jeho názov, tento objekt upozorní program na to, že došlo k stretu niektorých objektov alebo stále dochádza k ich stretu. Môžete tiež upozorniť, že niektoré objekty sa už nezrážajú, ale v tejto hre to nepotrebujete.
self.notifier = CollisionHandlerEvent () self.notifier.addInPattern ("%fn-in-%in") self.notifier.addAgainPattern ("%fn-again-%in")
- Nechajte program volať funkciu, keď sa zrazia dva objekty. To sa robí rovnakým spôsobom ako pri stlačení klávesov. Ak sa napríklad pálka hráča zrazí s ľavou stenou, udalosť sa nazýva„batPlay-in-wallLeft“. Takže volanie funkcieblockCollisionby byť vykonané self.accept("batPlay-in-wallLeft", self.blockCollision).
- Nastavte kolízne boxy pre všetky objekty, u ktorých chcete zistiť kolízie. Zatiaľ to znamená všetky múry a dva netopiere. Všimnite si toho, že musíte pridať čiaru base.cTrav.addCollider(batPlayColl, self.notifier) ku každému objektu, ktorý sa môže s niečím zraziť (v tomto prípade netopiere), pričom do každého objektu s tvarom kolízie je možné automaticky naraziť. Kolízia okno trvá štyri argumenty, ktoré majú byť vytvorené: poloha vzhľadom na stred objektu sa vzťahuje na, a mierka v X, Y a Z sa vzhľadom k danému objektu. Napríklad:
batPlayColl = self.batPlay.attachNewNode (CollisionNode ("batPlay")) batPlayColl.node (). addSolid (CollisionBox (LPoint3 (0,0,0), 1, 1, 1)) batPlayColl.show ()
- Definujte funkciu pre kolízne udalosti. Pretože správanie je v zásade rovnaké vo všetkých prípadoch, mali by ste definovať iba jednu funkciu, ktorá zvládne všetky tieto kolízie medzi netopierom a stenou. Malo by vrátiť netopiera späť do polohy, kde sa nezrazí so stenou. V ideálnom prípade by sa to dalo vyriešiť nastavením polohyentry.getFromNodePath (), ale to nefunguje, takže musíte operácie oboch netopierov považovať za samostatné prípady.
Tip: Vďaka kolíznym boxom vyzerá hra trochu zvláštne. Aj keď nie všetky kolízie sú implementované a fungujú bezchybne, je najlepšie nechať ich tam. Potom ich môžete urobiť neviditeľnými odstránením riadku
- Celý váš kód by teraz mal vyzerať takto:
z direct.showbase. Import ShowBase ShowBasefrom panda3d.core import * class MyApp (ShowBase): def _init_ (self): # Initialize the window loadPrcFileData ('', 'window-title 3D Pong') loadPrcFileData ('', 'background-color 0 0 0 0') ShowBase._init_ (self) # Inicializácia detekcie kolízií base.cTrav = CollisionTraverser () base.cTrav.showCollisions (render) self.notifier = CollisionHandlerEvent () self.notifier.addInPattern ("%fn-in-%in") self. notifier.addAgainPattern ("%fn-again-%in") self.accept ("batPlay-in-wallLeft", self.blockCollision) self.accept ("batPlay-again-wallLeft", self.blockCollision) self.accept ("batPlay-in-wallRight", self.blockCollision) self.accept ("batPlay-again-wallRight", self.blockCollision) self.accept ("batPlay-in-wallBottom", self.blockCollision) self.accept ("batPlay-again-wallBottom ", self.blockCollision) self.accept (" batPlay-in-wallTop ", self.blockCollision) self.accept (" batPlay-again-wallTop ", self.blockCollision) self.accept (" batOpp- in-wallLeft ", self.blockCollision) self.accept (" batOpp-again-wallLeft ", self.blockCollision) self.accept (" batOpp-in-wallRight ", self.blockCollision) self.accept (" batOpp-again- wallRight ", self.blockCollision) self.accept (" batOpp-in-wallBottom ", self.blockCollision) self.accept (" batOpp-again-wallBottom ", self.blockCollision) self.accept (" batOpp-in-wallTop ", self.blockCollision) self.accept ("batOpp-again-wallTop", self.blockCollision) # Načítať model lopty self.ball = loader.loadModel ("ball.egg") self.ball.reparentTo (self.render) self.ball.setPos (0, 0,0) # Načítajte modely stien a definujte ich kolízne boxy wallLeft = loader.loadModel ("wall.egg"); wallLeft.reparentTo (self.render) wallLeft.setPosHprScale (-15,0,0, 0,0,90, 2,2,1) wallLeftColl = wallLeft.attachNewNode (CollisionNode ("wallLeft")) wallLeftColl.node (). addSolid (CollisionBox (LPoint3 (0,0,0), 10, 10, 0,25)) wallLeftColl.show () wallRight = loader.loadModel ("wall.egg"); wallRight.reparentTo (self.render) wallRight.setPosHprScale (15,0,0, 0,0,90, 2,2,1) wallRightColl = wallRight.attachNewNode (CollisionNode ("wallRight")) wallRightColl.node (). addSolid (CollisionBox (LPoint3 (0,0,0), 10, 10, 0,25)) wallRightColl.show () wallBottom = loader.loadModel ("wall.egg"); wallBottom.reparentTo (self.render) wallBottom.setPosHprScale (0,0,15, 0,0,0, 2,2,1) wallBottomColl = wallBottom.attachNewNode (CollisionNode ("wallBottom")) wallBottomColl.node (). addSolid (CollisionBox (LPoint3 (0,0,0), 10, 10, 0,25)) wallBottomColl.show () wallTop = loader.loadModel ("stena.egg "); wallTop.reparentTo (self.render) wallTop.setPosHprScale (0,0, -15, 0,0,0, 2,2,1) wallTopColl = wallTop.attachNewNode (CollisionNode ("wallTop")) wallTopColl.node (). addSolid (CollisionBox (LPoint3 (0,0,0), 10, 10, 0,25)) wallTopColl.show () # Načítajte modely bat self.batPlay = loader.loadModel ("bat.egg"); self.batPlay.reparentTo (self.render) self.batPlay.setScale (3,1,3) self.batPlay.setPos (-5, -15, -5) batPlayColl = self.batPlay.attachNewNode (CollisionNode ("batPlay"))) batPlayColl.node (). addSolid (CollisionBox (LPoint3 (0,0,0), 1, 1, 1)) batPlayColl.show () base.cTrav.addCollider (batPlayColl, self.notifier) self.batOpp = nakladač.loadModel ("bat.egg"); self.batOpp.reparentTo (self.render) self.batOpp.setPos (5,15, -5) self.batOpp.setScale (3,1,3) batOppColl = self.batOpp.attachNewNode (CollisionNode ("batOpp")) batOppColl.node (). addSolid (CollisionBox (LPoint3 (0,0,0), 1, 1, 1)) batOppColl.show () base.cTrav.addCollider (batOppColl, self.notifier) # Nastavte správnu polohu kamery # vlastné.disableMouse () camera.setPos (0, -60,0) # Lighting alight = AmbientLight ('alight') alight.setColor (VBase4 (0,1, 0,1, 0,1, 1)) alnp = render. attachNewNode (alight) render.setLight (alnp) plight = PointLight ('plight') plight.setColor (VBase4 (0,9, 0,9, 0,9, 1)) plnp = render.attachNewNode (plight) plnp.setPos (0, -16,0) render.setLight (plnp) # Pohyb po stlačení klávesu self.accept ("a", self.moveLeft) self.accept ("a-repeat", self.moveLeft) self.accept (" d ",self.moveRight) self.accept ("d-opakovanie", self.moveRight) self.accept ("w", self.moveUp) self.accept ("w-opakovanie", self.moveUp) self.accept ("s ", self.moveDown) self.accept (" s-repeat ", self.moveDown) def moveLeft (self): self.batPlay.setX (self.batPlay.getX ()-1) def moveRight (self): self. batPlay.setX (self.batPlay.getX ()+1) def moveUp (self): self.batPlay.setZ (self.batPlay.getZ ()+1) def moveDown (self): self.batPlay.setZ (self. batPlay.getZ ()-1) def blockCollision (self, entry): if str (entry.getFromNodePath ()) == "render/bat.egg/batPlay": if str (entry.getIntoNodePath ()) == "render /wall.egg/wallLeft ": self.batPlay.setX (-15+entry.getIntoNodePath (). getSx ()+self.batPlay.getSx ()) if str (entry.getIntoNodePath ()) ==" render/wall.egg/wallRight ": self.batPlay.setX (15-entry.getIntoNodePath ().getSx ()-self.batPlay.getSx ()) if str (entry.getIntoNodePath ()) == "render/wall.egg/wallBottom": self.batPlay.setZ (15-entry.getIntoNodePath (). getSz () -self.batPlay.getSz ()) if str (entry.getIntoNodePath ()) == "render/wall.egg/wallTop": self.batPlay.setZ (-15+entry.getIntoNodePath (). getSz ()+self.batPlay.getSz ()) if str (entry.getFromNodePath ()) == "render/bat.egg/batOpp": if str (entry.getIntoNodePath ()) == "render/wall.egg/wallLeft": self.batOpp.setX (-15+entry.getIntoNodePath (). getSx ()+self.batOpp.getSx ()) if str (entry.getIntoNodePath ()) == "render/wall.egg/wallRight": self.batOpp.setX (15-entry.getIntoNodePath (). getSx ()-self.batPlay.getSx ()) if str (entry.getIntoNodePath ()) == "render/wall.egg/wallBottom": self.batPlay.setZ (15-entry.getIntoNodePath (). GetSz ()-self.batPlay.getSz ()) if str (vstup.getIntoNodePath ()) == "render/wall.egg/wallTop": self.batPlay.setZ (-15+entry.getIntoNodePath (). getSz ()+self.batPlay.getSz ()) if str (entry.getFromNodePath ()) == "render/bat.egg/batOpp": if str (entry.getIntoNodePath ()) == "render/wall.egg/wallLeft": self.batOpp.setX (-15+entry.getIntoNodePath (). getSx ()+self.batOpp.getSx ()) if str (entry.getIntoNodePath ()) == "render/wall.egg/wallRight": self.batOpp.setX (15-entry.getIntoNodePath (). getSx () -self.batPlay.getSx ()) if str (entry.getIntoNodePath ()) == "render/wall.egg/wallBottom": self.batPlay.setZ (10-entry.getIntoNodePath (). getSz ()-self. batPlay.getSz ()) if str (entry.getIntoNodePath ()) == "render/wall.egg/wallTop": self.batPlay.setZ (-20+entry.getIntoNodePath (). getSz ()+self.batPlay. getSz ()) app = MyApp () app.run ()egg/wallTop ": self.batPlay.setZ (-15+entry.getIntoNodePath (). getSz ()+self.batPlay.getSz ()) if str (entry.getFromNodePath ()) ==" render/bat.egg/ batOpp ": if str (entry.getIntoNodePath ()) ==" render/wall.egg/wallLeft ": self.batOpp.setX (-15+entry.getIntoNodePath (). getSx ()+self.batOpp.getSx ()) if str (entry.getIntoNodePath ()) == "render/wall.egg/wallRight": self.batOpp.setX (15-entry.getIntoNodePath (). getSx ()-self.batPlay.getSx ()) if str (entry.getIntoNodePath ()) == "render/wall.egg/wallBottom": self.batPlay.setZ (10-entry.getIntoNodePath (). getSz ()-self.batPlay.getSz ()) if str (vstup. getIntoNodePath ()) == "render/wall.egg/wallTop": self.batPlay.setZ (-20+entry.getIntoNodePath (). getSz ()+self.batPlay.getSz ()) app = aplikácia MyApp (). spustiť ()egg/wallTop ": self.batPlay.setZ (-15+entry.getIntoNodePath (). getSz ()+self.batPlay.getSz ()) if str (entry.getFromNodePath ()) ==" render/bat.egg/ batOpp ": if str (entry.getIntoNodePath ()) ==" render/wall.egg/wallLeft ": self.batOpp.setX (-15+entry.getIntoNodePath (). getSx ()+self.batOpp.getSx ()) if str (entry.getIntoNodePath ()) == "render/wall.egg/wallRight": self.batOpp.setX (15-entry.getIntoNodePath (). getSx ()-self.batPlay.getSx ()) if str (entry.getIntoNodePath ()) == "render/wall.egg/wallBottom": self.batPlay.setZ (10-entry.getIntoNodePath (). getSz ()-self.batPlay.getSz ()) if str (vstup. getIntoNodePath ()) == "render/wall.egg/wallTop": self.batPlay.setZ (-20+entry.getIntoNodePath (). getSz ()+self.batPlay.getSz ()) app = aplikácia MyApp (). spustiť ()batPlay.getSz ()) if str (entry.getFromNodePath ()) == "render/bat.egg/batOpp": if str (entry.getIntoNodePath ()) == "render/wall.egg/wallLeft": self. batOpp.setX (-15+entry.getIntoNodePath (). getSx ()+self.batOpp.getSx ()) if str (entry.getIntoNodePath ()) == "render/wall.egg/wallRight": self.batOpp. setX (15-entry.getIntoNodePath (). getSx ()-self.batPlay.getSx ()) if str (entry.getIntoNodePath ()) == "render/wall.egg/wallBottom": self.batPlay.setZ (10 -entry.getIntoNodePath (). getSz ()-self.batPlay.getSz ()) if str (entry.getIntoNodePath ()) == "render/wall.egg/wallTop": self.batPlay.setZ (-20+vstup.getIntoNodePath (). getSz ()+self.batPlay.getSz ()) app = MyApp () app.run ()batPlay.getSz ()) if str (entry.getFromNodePath ()) == "render/bat.egg/batOpp": if str (entry.getIntoNodePath ()) == "render/wall.egg/wallLeft": self. batOpp.setX (-15+entry.getIntoNodePath (). getSx ()+self.batOpp.getSx ()) if str (entry.getIntoNodePath ()) == "render/wall.egg/wallRight": self.batOpp. setX (15-entry.getIntoNodePath (). getSx ()-self.batPlay.getSx ()) if str (entry.getIntoNodePath ()) == "render/wall.egg/wallBottom": self.batPlay.setZ (10 -entry.getIntoNodePath (). getSz ()-self.batPlay.getSz ()) if str (entry.getIntoNodePath ()) == "render/wall.egg/wallTop": self.batPlay.setZ (-20+vstup.getIntoNodePath (). getSz ()+self.batPlay.getSz ()) app = MyApp () app.run ()egg/wallLeft ": self.batOpp.setX (-15+entry.getIntoNodePath (). getSx ()+self.batOpp.getSx ()) if str (entry.getIntoNodePath ()) ==" render/wall.egg/ wallRight ": self.batOpp.setX (15-entry.getIntoNodePath (). getSx ()-self.batPlay.getSx ()) if str (entry.getIntoNodePath ()) ==" render/wall.egg/wallBottom ": self.batPlay.setZ (10-entry.getIntoNodePath (). getSz ()-self.batPlay.getSz ()) if str (entry.getIntoNodePath ()) == "render/wall.egg/wallTop": self.batPlay.setZ (-20+entry.getIntoNodePath (). getSz ()+self.batPlay.getSz ()) app = MyApp () app.run ()egg/wallLeft ": self.batOpp.setX (-15+entry.getIntoNodePath (). getSx ()+self.batOpp.getSx ()) if str (entry.getIntoNodePath ()) ==" render/wall.egg/ wallRight ": self.batOpp.setX (15-entry.getIntoNodePath (). getSx ()-self.batPlay.getSx ()) if str (entry.getIntoNodePath ()) ==" render/wall.egg/wallBottom ": self.batPlay.setZ (10-entry.getIntoNodePath (). getSz ()-self.batPlay.getSz ()) if str (entry.getIntoNodePath ()) == "render/wall.egg/wallTop": self.batPlay.setZ (-20+entry.getIntoNodePath (). getSz ()+self.batPlay.getSz ()) app = MyApp () app.run ()egg/wallBottom ": self.batPlay.setZ (10-entry.getIntoNodePath (). getSz ()-self.batPlay.getSz ()) if str (entry.getIntoNodePath ()) ==" render/wall.egg/wallTop ": self.batPlay.setZ (-20+entry.getIntoNodePath (). getSz ()+self.batPlay.getSz ()) app = MyApp () app.run ()egg/wallBottom ": self.batPlay.setZ (10-entry.getIntoNodePath (). getSz ()-self.batPlay.getSz ()) if str (entry.getIntoNodePath ()) ==" render/wall.egg/wallTop ": self.batPlay.setZ (-20+entry.getIntoNodePath (). getSz ()+self.batPlay.getSz ()) app = MyApp () app.run ()
- 13Pridajte pohyb. Nielenže by mal hráč po stlačení klávesu vidieť určitú odozvu, niektoré objekty by sa mali pohybovať aj samy: dá sa to použiť na vyžiadanie reakcie hráča alebo rovnako pekné detaily pozadia.
- Nechajte loptu v pohybe. Zatiaľ to bude lietať cez steny, ale to napravíte v nasledujúcom kroku.
- Importujte funkcie randint a randrange z náhodnýknižnica. Tiež importovaťÚloha od direct.task.
- Vypočítajte rýchlosť, ktorú by mala mať loptička na začiatku. Prejdite na koniec_init_funkciu pre toto. Vytvorte vektor z 3 náhodných celých čísel. Rýchlosť y je vždy rovnaká, buď negatívna alebo pozitívna. Normalizujte tento vektor, tj. Zmeňte jeho súčasti tak, aby bol zachovaný ich vzťah, ale celková dĺžka vektora je 1. Rozdelte tento normalizovaný vektor na 5, aby lopta nelietala príliš rýchlo.
# Nechajte loptu v pohybe self.ballSpeed = VBase3 (randint (-10,10), randrange (-1,1,2), randint (-10,10)) self.ballSpeed.normalize () self.ballSpeed /= 5
- Vytvorte úlohu. V Panda3D znamená úloha volanie funkcie v každom rámci. Do výpočtov rýchlosti napíšte nasledujúci kód:
seba. taskMgr. pridať (self. updateBallPos, „UpdateBallPos“)
- Definujte funkciu úlohy. Funkcia by mala jednoducho pridať rýchlosť k pozícii lopty. Potom by sa to malo vrátiťÚloha.kont, čo spôsobí, že sa funkcia opäť vyvolá v nasledujúcom rámci.
def updateBallPos (self, task): self.ball.setPos (self.ball.getPos ()+self.ballSpeed) návrat Task.cont
- 14Pridajte detekciu kolízií aj pre pohybujúce sa objekty. Dávajte pozor na rýchlo sa pohybujúce objekty: môžu vyžadovať špeciálny druh detekcie kolízií, ktorý sa zameriava aj na predchádzajúce snímky a určuje, či sa objekty kedykoľvek zrazili, aj keď to bolo príliš rýchle na to, aby sa to stalo v ľubovoľnom rámci.
- Loptu by ste mali nechať odraziť, kedykoľvek sa s niečím zrazí. Zabráni sa tým preletom cez steny alebo netopiere.
- Povoliť detekciu kolízií kvapalín. V prípade rýchlo sa pohybujúcich predmetov, ako je lopta v tejto hre, je problém s normálnou detekciou kolízie: Ak je predmet v jednom rámci pred objektom, do ktorého bude narážať, a v nasledujúcom rámci už za ním bude, k zrážke nedôjde. t zistené. Ale detekuje také kolízie s určitými úpravami: choďte tam, kde ste inicializovali traverz zrážok a pridajte riadok
základňa. cTrav. setRespectPrevTransform (True)
- Prijmite udalosti pri kolízii s loptou. Váš program by si mal všimnúť kolízie medzi loptou a stenami alebo pálkou. Nepridávajteznova Udalosti tentoraz, pretože by ste sa mali uistiť, že lopta zmení smer iba raz - ak dvakrát zmení smer, pokračuje v lietaní cez stenu alebo pálku.
- Definujte odskočiťVypfunkcia, ktorá sa volá zakaždým, keď sa lopta zrazí. Ak chcete zmeniť smer, nastavte ho na záporný. Použite ľubovoľný smer, v ktorom mala lopta uniknúť: napríklad ak narazí do ľavej alebo pravej steny, otočte smer x.
def bounceOff (self, entry): if str (entry.getIntoNodePath ()) == "render/wall.egg/wallLeft" alebo str (entry.getIntoNodePath ()) == "render/wall.egg/wallRight": self.ballSpeed [0] = -self.ballSpeed [0] if str (entry.getIntoNodePath ()) == "render/bat.egg/batPlay" alebo str (entry.getIntoNodePath ()) == "render/bat.egg /batOpp ": self.ballSpeed [1] = -self.ballSpeed [1] if str (entry.getIntoNodePath ()) ==" render/wall.egg/wallBottom "alebo str (entry.getIntoNodePath ()) ==" render/wall.egg/wallTop ": self.ballSpeed [2] = -self.ballSpeed [2]
- Upravte nevhodné hodnoty. Teraz si môžete vyskúšať, aké to je hrať hru, hoci súperovi bude lopta chýbať s veľmi vysokou pravdepodobnosťou. Môžete si ale vyskúšať, či na loptu dobre vidíte a sami ju trafiť. Fotoaparát môžete presunúť späť na -75 a netopiere na ± 25, aby ste uľahčili hranie. Loptu môžete tiež zväčšiť, aby bolo jednoduchšie vidieť, v akom smere sa pohybuje a ako blízko je. Steny môžete trochu predĺžiť (mierka 3 namiesto 2 v smere Y), aby loptička nemohla lietať mimo zorného poľa, kým sa dostane za pálku.
- 15Definujte správanie súpera. Ak má vaša hra akéhokoľvek druhu súpera, budete musieť naprogramovať jeho správanie, pretože je veľmi nepravdepodobné, že by hráč mal skutočného súpera. Určite existujú sieťové hry pre viacerých hráčov, kde musí hráč hrať proti inému hráčovi na inom počítači, ale veľmi ťažko sa programujú a mnohé z nich majú aj možnosť pre jedného hráča.
- Pridajte ďalšiu úlohu. Urobte z tohto jedného hovoru funkciu s názvomdirectOpponent.
- Definujte funkciu directOpponent. Usmerniť pálku tak, aby nasledovala loptu v smere X/Z, je jednoduché. Problém je, že aj súper musí robiť chyby, aby mal hráč šancu vyhrať. To sa dá dosiahnuť správnym množstvom náhodnosti.
- V nižšie uvedenej funkcii sa súperova pálka pohybuje buď správnym smerom, alebo opačným smerom. Vďaka tomu je niekedy možné loptu minúť.
- Make kladné číslo vyššie, ak chcete, aby súper zasiahnuť loptu častejšie a záporné číslo nižšie, ak chcete, aby loptu chýbať častejšie. Ak urobíte oboje, efekty sa navzájom zrušia.
def directOpponent (self, task): dirX = randint (-2,4)*(self.ball.getX ()-self.batOpp.getX ()) dirZ = randint (-2,4)*(self.ball. getZ () - self.batOpp.getZ ()) self.batOpp.setX (self.batOpp.getX () + copysign (1/7, dirX)) self.batOpp.setZ (self.batOpp.getZ () + copysign (1/7, dirZ)) vrátiť Task.cont
- Hrať hru. Kým lopta stále chýba, keď hráč alebo súper chýbajú, je už možné otestovať hrateľnosť a v prípade potreby niečo upraviť.
- Teraz urobte kolízne boxy neviditeľnými. V tejto hre dochádza k mnohým kolíziám a neustále blikanie škatúľ môže rozptyľovať a otravovať. Odstráňte teda riadokbase.cTrav.showCollisions (render) a všetky riadky sú názvom zrážkového tvaru s .šou() na konci, ako napr wallLeftColl.show ().
- 16Stanovte limity. Ak, okrem iných predmetov, s ktorými sa má stretnúť, objekty nemajú žiadne obmedzenia v tom, kam sa môžu pohybovať, môže to spôsobiť problémy. Ak napríklad hráč hodí loptičkou a tá sa už nevráti, budú z toho poriadne naštvaní.
- V tomto prípade by program mal zistiť, kedy je lopta mimo poľa. Ak sa to stane, program by ho mal vrátiť späť na (00,0) a dať bod hráčovi, ktorý nezmeškal.
- Importovať OnscreenText z direct.gui.OnscreenText.
- Definujte skóre ako zoznam. Malo by mať dve položky, ktoré sú na začiatku nastavené na 0.
- Zobraziť text ako OnscreenText. Poloha je tu odlišná: prvé číslo je vľavo/vpravo a druhé je dole/hore. Oba majú polovicu obrazovky ako 1 jednotku.fg nastavuje farbu textu.
# Spočítajte skóre self.scores = [0,0] self.scoreCount = OnscreenText (text = (str (self.scores [0]) + "" + str (self.scores [1])), pos = (0 0,75), stupnica = 0,1, fg = (0, 255, 0, 0,5))
- Pridajte dve príkazy if do súboru updateBallPosfunkciu. Mali by skontrolovať, či je lopta mimo 26 alebo -26, a ak je to tak, vráťte loptu na (00,0) a zvýšte príslušné skóre (buď hráčove alebo súperove).
defin updateBallPos (self, task): self.ball.setFluidPos (self.ball.getPos () +self.ballSpeed) ak self.ball.getY ()> 26: self.scores [0] += 1 self.ball. setPos (0,0,0) self.scoreCount.destroy () # zničiť posledný text pred pridaním nového self.scoreCount = OnscreenText (text = (str (self.scores [0]) + "" + str (self.scores [1])), pos = (0, 0,75), mierka = 0,1, fg = (0, 255, 0, 0,5)) ak self.ball.getY () <-26: self.scores [1] + = 1 self.ball.setPos (0,0,0) self.scoreCount.destroy () self.scoreCount = OnscreenText (text = (str (self.scores [0]) + "" + str (self.score [1])), pos = (0, 0,75), scale = 0,1, fg = (0, 255, 0, 0,5)) návrat Task.cont
- 17Skontrolujte svoj kód. Ak ste v príklade napísali hru, celý váš kód by teraz mal vyzerať takto:
z direct.showbase.ShowBase import ShowBase z direct.task import Úloha z panda3d.core import * z direct.gui.OnscreenText import OnscreenText z náhodného importu randint, randrange z matematického importu copysign class MyApp (ShowBase): def _init_ (self): # Inicializujte okno loadPrcFileData ('', '3D titulok okna') loadPrcFileData ('', 'farba pozadia 0 0 0 0') ShowBase._init_ (self) # Inicializujte detekciu kolíziíbase.cTrav = CollisionTraverser () base.cTrav.setRespectPrevTransform (True) self.notifier = CollisionHandlerEvent () self.notifier.addInPattern ("%fn-in-%in") self.notifier.addAgainPattern ("%fn-again-%in ") self.accept (" batPlay-in-wallLeft ", self.blockCollision) self.accept (" batPlay-again-wallLeft ", self.blockCollision) self.accept (" batPlay-in-wallRight ", self. blockCollision) self.accept ("batPlay-again-wallRight", self.blockCollision) self.accept ("batPlay-in-wallBottom", self.blockCollision) self.accept ("batPlay-again-wallBottom", self.blockCollision) self.accept ("batPlay-in-wallTop", self.blockCollision) self.accept ("batPlay-again-wallTop", self.blockCollision) self.accept ("batOpp-in-wallLeft", self.blockCollision) self. súhlasiť("batOpp-again-wallLeft ", self.blockCollision) self.accept (" batOpp-in-wallRight ", self.blockCollision) self.accept (" batOpp-again-wallRight ", self.blockCollision) self.accept (" batOpp- in-wallBottom ", self.blockCollision) self.accept (" batOpp-again-wallBottom ", self.blockCollision) self.accept (" batOpp-in-wallTop ", self.blockCollision) self.accept (" batOpp-again- wallTop ", self.blockCollision) self.accept (" ball-in-wallLeft ", self.bounceOff) self.accept (" ball-in-wallRight ", self.bounceOff) self.accept (" ball-in-wallBottom ", self.bounceOff) self.accept ("ball-in-wallTop", self.bounceOff) self.accept ("ball-in-batPlay", self.bounceOff) self.accept ("ball-in-batOpp", self.bounceOff) # Vložte model loptičky self.ball = loader.loadModel („lopta.vajíčko ") self.ball.reparentTo (self.render) self.ball.setPos (0, 0, 0) ballColl = self.ball.attachNewNode (CollisionNode (" ball ")) ballColl.node (). addSolid (CollisionSphere (0, 0, 0, 0,25)) ballColl.show () base.cTrav.addCollider (ballColl, self.notifier) # Načítajte modely stien a definujte ich kolízne boxy wallLeft = loader.loadModel ("wall.egg"); wallLeft.reparentTo (self.render) wallLeft.setPosHprScale (-15,0,0, 0,0,90, 2,3,1) wallLeftColl = wallLeft.attachNewNode (CollisionNode ("wallLeft")) wallLeftColl.node (). addSolid (CollisionBox (LPoint3 (0,0,0), 10, 10, 0,25)) wallRight = loader.loadModel ("wall.egg"); wallRight.reparentTo (self.render) wallRight.setPosHprScale (15,0, 0, 0,0,90, 2,3,1) wallRightColl = wallRight.attachNewNode (CollisionNode ("wallRight")) wallRightColl.node (). AddSolid (CollisionBox (LPoint3 (0,0,0), 10, 10, 0,25)) wallBottom = loader.loadModel ("wall.egg"); wallBottom.reparentTo (self.render) wallBottom.setPosHprScale (0,0,15, 0,0,0, 2,3,1) wallBottomColl = wallBottom.attachNewNode (CollisionNode ("wallBottom")) wallBottomColl.node (). addSolid (CollisionBox (LPoint3 (0,0,0), 10, 10, 0,25)) wallTop = loader.loadModel ("wall.egg"); wallTop.reparentTo (self.render) wallTop.setPosHprScale (0,0, -15, 0,0,0, 2,3,1) wallTopColl = wallTop.attachNewNode (CollisionNode ("wallTop")) wallTopColl.node (). addSolid (CollisionBox (LPoint3 (0,0,0), 10, 10, 0,25)) # Načítajte modely bat self.batPlay = loader.loadModel ("bat.egg"); self.batPlay.reparentTo (self.render) self.batPlay.setScale (3,1,3) self.batPlay.setPos (-5, -25, -5) batPlayColl = self.batPlay.attachNewNode (CollisionNode ("batPlay"))) batPlayColl.node ().addSolid (CollisionBox (LPoint3 (0,0,0), 1, 1, 1)) base.cTrav.addCollider (batPlayColl, self.notifier) self.batOpp = loader.loadModel ("bat.egg"); self.batOpp.reparentTo (self.render) self.batOpp.setPos (5,25, -5) self.batOpp.setScale (3,1,3) batOppColl = self.batOpp.attachNewNode (CollisionNode ("batOpp")) batOppColl.node (). addSolid (CollisionBox (LPoint3 (0,0,0), 1, 1, 1)) base.cTrav.addCollider (batOppColl, self.notifier) # Nastavte správnu polohu kamery self.disableMouse () kamera. setPos (0, -75,0) # Lighting alight = AmbientLight ('alight') alight.setColor (VBase4 (0,1, 0,1, 0,1, 1)) alnp = render.attachNewNode (alight) render. setLight (alnp) plight = PointLight ('plight') plight.setColor (VBase4 (0,9, 0,9, 0,9, 1)) plnp = render.attachNewNode (plight) plnp.setPos (0, -16, 0) render.setLight (plnp) # Pohyb po stlačení klávesu self.accept ("a ", self.moveLeft) self.accept (" a-repeat ", self.moveLeft) self.accept (" d ", self.moveRight) self.accept (" d-opakovanie ", self.moveRight) self.accept ("w", self.moveUp) self.accept ("w-opakovanie", self.moveUp) self.accept ("s", self.moveDown) self.accept ("s-opakovanie", self.moveDown) # Nechajte loptu v pohybe self.ballSpeed = VBase3 (randint (-10,10), randrange (-1,2,2)*8, randint (-10,10)) self.ballSpeed.normalize () self.ballSpeed /= 7 self.taskMgr.add (self.updateBallPos, "UpdateBallPos") self.taskMgr.add (self.directOpponent, "DirectOpponent") # Spočítajte skóre self.scores = [0,0] self.scoreCount = OnscreenText (text = (str (self.scores [0]) + "" + str (self.scores [1])), pos = (0, 0,75), scale = 0,1, fg = (0, 255, 0, 0,5)) def move Vľavo (self): self.batPlay.setX (self.batPlay.getX ()-1) def moveRight (self): self.batPlay.setX (self.batPlay.getX ()+1) def moveUp (self): self.batPlay.setZ (self.batPlay.getZ ()+ 1) def moveDown (self): self.batPlay.setZ (self.batPlay.getZ ()-1) def blockCollision (self, entry): if str (entry.getFromNodePath ()) == "render/bat.egg/ batPlay ": if str (entry.getIntoNodePath ()) ==" render/wall.egg/wallLeft ": self.batPlay.setX (-15+entry.getIntoNodePath (). getSx ()+self.batPlay.getSx ()) if str (entry.getIntoNodePath ()) == "render/wall.egg/wallRight": self.batPlay.setX (15-entry.getIntoNodePath (). getSx ()-self.batPlay.getSx ()) if str (entry.getIntoNodePath ()) == "render/wall.egg/wallBottom": self.batPlay.setZ (15-entry.getIntoNodePath (). getSz ()-self.batPlay.getSz ()) if str (vstup. getIntoNodePath ()) == "render/wall.egg/wallTop": self.batPlay.setZ (-15+vstup.getIntoNodePath (). getSz ()+self.batPlay.getSz ()) if str (entry.getFromNodePath ()) == "render/bat.egg/batOpp": if str (entry.getIntoNodePath ()) == "render /wall.egg/wallLeft ": self.batOpp.setX (-15+entry.getIntoNodePath (). getSx ()+self.batOpp.getSx ()) if str (entry.getIntoNodePath ()) ==" render/wall.egg/wallRight ": self.batOpp.setX (15-entry.getIntoNodePath (). getSx ()-self.batOpp.getSx ()) if str (entry.getIntoNodePath ()) ==" render/wall.egg/ wallBottom ": self.batOpp.setZ (15-entry.getIntoNodePath (). getSz ()-self.batOpp.getSz ()) if str (entry.getIntoNodePath ()) ==" render/wall.egg/wallTop ": self.batOpp.setZ (-15+entry.getIntoNodePath (). getSz ()+self.batOpp.getSz ()) def bounceOff (self, entry): if str (entry.getIntoNodePath ()) == "render/wall.egg/wallLeft "alebo str (entry.getIntoNodePath ()) ==" render/wall.egg/wallRight ": self.ballSpeed [0] = -self.ballSpeed [0] if str (entry.getIntoNodePath ()) ==" render/bat.egg/batPlay "alebo str (entry.getIntoNodePath ()) == "render/bat.egg/batOpp": self.ballSpeed [1] = -self.ballSpeed [1] if str (entry.getIntoNodePath ()) == "render/wall.egg/wallBottom" alebo str (entry.getIntoNodePath ()) == "render/wall.egg/wallTop": self.ballSpeed [2] = -self.ballSpeed [2] def updateBallPos (self, task): self.ball.setFluidPos (self.ball.getPos () +self.ballSpeed) ak self.ball.getY ()> 26: self.scores [0] += 1 self.ball.setPos (0,0,0) self.scoreCount.destroy () # zničiť posledný text pred pridaním new self.scoreCount = OnscreenText (text = (str (self.scores [0]) + "" + str (self.scores [1])), pos = (0, 0,75), scale = 0,1, fg = (0, 255, 0, 0,5)) ak self.ball.getY () <-26: self.scores [1] += 1 self.ball.setPos (0,0,0) self.scoreCount.destroy () self.scoreCount = OnscreenText (text = (str (self.scores [0]) + "" + str (self.scores [1])), pos = (0, 0,75), scale = 0,1, fg = (0, 255, 0, 0,5)) return Task.cont def directOpponent (self, task): dirX = randint (-2,4)*(self.ball.getX () - self.batOpp.getX ()) dirZ = randint (-2,4)*(self.ball.getZ () - self.batOpp.getZ ()) self.batOpp. setX (self.batOpp.getX () + copysign (1/7, dirX)) self.batOpp.setZ (self.batOpp.getZ () + copysign (1/7, dirZ)) vrátiť aplikáciu Task.cont = MyApp () app.run ()ball.getZ () - self.batOpp.getZ ()) self.batOpp.setX (self.batOpp.getX () + copysign (1/7, dirX)) self.batOpp.setZ (self.batOpp.getZ () + copysign (1/7, dirZ)) návrat Task.cont app = MyApp () app.run ()ball.getZ () - self.batOpp.getZ ()) self.batOpp.setX (self.batOpp.getX () + copysign (1/7, dirX)) self.batOpp.setZ (self.batOpp.getZ () + copysign (1/7, dirZ)) návrat Task.cont app = MyApp () app.run ()
- To je celkom 166 riadkov a 152 riadkov čistého kódu. 3D hry sú veľmi komplexné, takže ide o bežné množstvo riadkov pre takúto hru.
- 18Hotovo. Táto hra zatiaľ nemôže v určitom bode vyhrať ani prehrať a nie je možné ju ani reštartovať bez reštartu programu. Takéto funkcie by váš program ešte skomplikovali, takže ak chcete viac praxe, skúste ich implementovať. Každopádne by ste mali hru nejaký čas hrať, aby ste zistili, či všetko funguje, ako má, a možno sa aj pobavili na hre, ktorú ste napísali.
Časť 4 zo 4: zverejnenie hry
- 1Napíšte závislosti. Každý, kto používa iný počítač, nebude mať nainštalovaný rovnaký softvér a knižnice ako vy. Musíte sa teda uistiť, že každý používateľ, ktorý si nainštaluje váš program, si nainštaluje aj všetko, čo program potrebuje na svoju prácu. Nemusíte si zapisovať všetky závislosti všetkých závislostí od všetkých závislostí a podobne, pretože zoznam by sa takto mohol veľmi predĺžiť, ale mali by ste napísať aspoň závislosti vášho balíka a ich závislosti.
- 2Skontrolujte licencie. Platí to pre médiá, ako sú obrázky, 3D modely alebo hudba, knižnice a rámce, ktoré ste použili pre svoj program, a čokoľvek, čo ste vo svojom programe použili a ktoré ste sami nenapísali.
- Často existujú určité podmienky, ako napríklad pripísanie autorovi alebo zdieľanie úprav média pod rovnakou licenciou. Niekedy je tiež zakázané používať ho na komerčné účely, ako je hra, ktorú budete predávať za peniaze. Ak musíte autorovi poďakovať, urobte to na dobre viditeľnom mieste, napríklad na karte „Kredity“ vo vašej hre.
- Existujú aj médiá s nárokovanými autorskými právami a bez uvedenia licencie, niekedy s textom ako „Všetky práva vyhradené“. Ak je to tak, pred zaradením do hry musíte získať výslovné povolenie od autora.
- Knižnice sú spravidla vydávané pod licenciou, ktorá umožňuje ich použitie ako knižníc. Významnou výnimkou je GPL bez výnimky z prepojenia: takáto licencia ju umožňuje používať iba v programe s určitými licenciami. A vždy by ste si mali prečítať aspoň základné body licencie, aby ste sa presvedčili, že čokoľvek, čo robíte s médiom alebo knižnicou, je povolené.
Varovanie: Používanie médií alebo knižníc spôsobom, ktorý licencia nepovoľuje v hre, ktorú publikujete, vás môže dostať do vážnych právnych problémov. Ak si teda nie ste istí, či je vaše použitie povolené, opýtajte sa autora alebo sa úplne vyhnite médiu.
- 3Rozhodnite sa, za akých podmienok chcete hru publikovať. Aj keď si musíte dávať pozor na obmedzenia, ktoré stanovujú vaše externé médiá, o licencii svojho kódu sa spravidla môžete rozhodnúť sami. Môžete použiť veľmi tolerantnú licenciu, napríklad CC0. Môžete použiť licenciu, ktorá za určitých podmienok umožňuje distribúciu a úpravy, napríklad licenciu BSD alebo GPL. Alebo môžete svoj softvér nechať vlastniť, čo znamená, že nikto ho nesmie distribuovať alebo upravovať bez vášho súhlasu.
- Rozhodnite sa, či chcete svoj softvér predať. Aj keď je možné predajom softvéru zarobiť peniaze, je veľmi nepravdepodobné, že by si ľudia kúpili váš prvý softvér, ktorý má spravidla málo funkcií a nič zvláštne. Tiež, ak bezplatný program nefunguje, ľudia, ktorí si ho stiahli, budú jednoducho sklamaní; ak za to zaplatia, budú požadovať svoje peniaze späť, čo spôsobí ďalšie problémy vám aj používateľom. Zvážte preto sprístupnenie prvých niekoľkých programov zadarmo.
- 4Rozhodnite sa, ako chcete svoju hru zverejniť. Každá metóda má svoje výhody a nevýhody, takže sa musíte rozhodnúť sami.
- Publikovanie na webovej stránke: Ak máte webovú stránku, môžete na ňu nahrať svoju hru. Nezabudnite návštevníkom poskytnúť pokyny, ako nainštalovať nielen softvér, ale aj závislosti. Nevýhodou tejto metódy je, že používateľ si závislosti nainštaloval manuálne, čo môže byť pre niektorých ľudí, ktorí si chcú hru len zahrať, príliš náročné a je to celkom nudná úloha.
- Vytvorenie balíka pre správcu balíkov: Existujú rôzni správcovia balíkov, napríklad apt, yum alebo homebrew. Všetky majú rôzne špecifické formáty balíkov. Príslušný formát nájdete v referenciách. Dobrá vec na balíkoch správcu balíkov je, že automaticky nainštalujú všetky závislosti, ak ich nakonfigurujete správne. Užívateľ si teda musí nainštalovať iba váš balík a potom môže hrať hru. Problém je v tom, že na rôznych platformách existuje mnoho rôznych správcov balíkov, takže si budete musieť dať prácu s poskytovaním balíkov pre všetky najbežnejšie.
- 5Venujte pozornosť svojmu programu. Zvážte nahranie programu do hlavného úložiska balíkov, ako sú tie, ktoré udržujú Ubuntu a Debian. Používateľom to umožní veľmi jednoduchú inštaláciu. Tiež uverejňujte príspevky na príslušných fórach, napríklad v sekcii projektov v GameDev alebo v časti tigSource. Ale nebuďte sklamaní, ak sa vaše prvé hry nestanú slávnymi. Pokračujte, ak máte predstavu, že sa to mnohým ľuďom páči a kódujú to, vaša hra sa môže stať známou.
- Uistite sa, že ste trpezliví a ochotní sa učiť - programovanie môže byť niekedy frustrujúce!
- Ak vás zaujíma, ako sa niečo robí v inej hre, a táto hra je open-source, môžete sa pozrieť na jej zdrojový kód.
- Pri hľadaní médií hľadajte výslovne voľne dostupné. Možnosť tak urobiť zahŕňa zadanie akejkoľvek z možností Creative Commons alebo Public Domain pri vyhľadávaní obrázkov vo vašom vyhľadávacom nástroji. Ďalším spôsobom je použiť webovú stránku, ktorá poskytuje iba voľne licencované médiá, napríklad https://opengameart.org alebo https://publicdomainpictures.net.
- Nenechajte kopírovať veľké kusy kódu bez kontroly Kódexu preukaz. Je to často zakázané, a ak nie, zvyčajne to vyžaduje uvedenie zdroja.
- Pri propagácii svojej hry nevytvárajte spam ani nezverejňujte príspevky na nevhodných miestach. Pravdepodobne vás to zablokuje na dotknutej stránke, bude to jednoducho nepríjemné a poškodí to vašu povesť.