PacMan

Tomáš Herceg       12. 5. 2008       VB.NET, Grafika       7443 zobrazení

Hru PacMan nám zaslal čtenář Jan Dědek.

Dobrý den,

zasílám Vám námět do rubriky „Od našich čtenářů“.

Začínám se učit ve VB.net programovat grafiku a jako ukázka na které můžu dělat pokusy mi krásně posloužila vaše hra Hungry Snake.

Chvíli jsem dělal se zdrojákem pokusy a různé úpravy, až jsem se rozhodl, že zkusím co jsem se všechno naučil a jestli jsem základy této problematiky pochopil a rozhodl jsem se naprogramovat hru úplně od začátku. Vybral jsem si další velmi známou hru PAC MAN. Jak už jsem řekl z Vašeho článku o hře had jsem se poprvé setkal s programováním grafiky, takže v mé hře bude několik bloku kódu velmi podobných (protože zatím nevím jaké jiné možnosti řešení jsou).

Hra je velmi jednoduchá. V 1 levelu jsou 3 protihráč, v každém dalším kole je jeden protihráč navíc. Po sebrání všech mincí hráč postupuje do dalšího kola kterých je celkem 5. Pokud hráč narazí do protihráče hra končí.

Konstrukce hry je podobná jako u hada s tím rozdílem, že jsem přidal ještě jeden timer který se stará o pohyb protihráčů které řídí počítač. To že počítačem řízené postavy mají vlastní timer má tu výhodu, že si uživatel může nastavit obtížnost hry (zmenší se interval na timeru a tím se NPC pohybují rychleji).

Kvůli protihráčům jsem si musel také vytvořit více typů polí. Tam jsem narazil na úskalí jak zjistit po přejezdu NPC jestli pole bylo prázdné a nebo na něm byl bod který ještě hráč nesebral. Proto jsem si u protihráče vytvořil 2 typy pole (obsazeni.volno a obsazeni.bod). Podle toho poznám co na poli bylo před změnou souřadnic a po další změně tam vrátím původní hodnotu.

Vnitřní stěna se generuje náhodně a tam jsem narazil na jedno úskalí které se mi prozatím nepodařilo vyřešit a to jak zajistit, aby mi nezůstalo nějaké (buď osamocené nebo skupina několika polí s mincema) které jsou zazděné a nejde se k nim dostat.

Rozmístění protihráčů je také generováno automaticky s tím, že je pole pro jejich rozmisťování úmyslně zmenšeno, aby se hned na začátku nevygeneroval protihráč hned vedle hráče a nedošlo ke sražení a tím ukončení hry.

Nejtěžší bylo vymyslet umělou inteligenci NPC. Nakonec jsem to vyřešil tak, že NPC jdou jedním směrem dokud do něčeho nenarazí (do stěny nebo do jiného NPC). Po nárazu je volána procedura která vygeneruje náhodné číslo od 1 do 4. (každému číslu je přiřazen jeden směr) a ten se pak u příslušného NPC nastaví, takže pohyb je opravdu náhodný. Pro každý směr (u hráče i NPC) je samostatný obrázek, aby to vypadalo že se smajlík vždycky kouká směrem kterým jde.

Pokud se Vám zdá tento námět zajímavý, určitě budu rád pokud se objeví na stránkách VBnet. Třeba někdo přijde s nějakým zajímavým zlepšením (ať už zmíněnou nevyřešenou kontrolou dostupností všech políček s mincemi nebo čímkoliv jiným) a hlavně s kritikou, abych se dozvěděl co udělat jinak,lépe, protože chybami se člověk učíJ

S pozdravem

Jan Dědek

 

 

hodnocení článku

1 bodů / 1 hlasů       Hodnotit mohou jen registrované uživatelé.

Mohlo by vás také zajímat

 

Nový příspěvek

 

Diskuse: PacMan

Pěkné!

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: PacMan

Veľmi pekná hra. Len by som mal jednu pripomienku a to :

Stalo sa mi, že pri náhodnom umiestňovaní stien sa steny usporiadali tak, že obkolesili guličku a ja som sa k nej PacManom nemohol dostať. Možno by to chcelo doplniť ešte nejakú podmienku, ktorá by to riešila.

Vašo

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ano o tom vím, píšu to i v příspěvku. Prozatím se mi tento problém nepodařilo vyřešit. Až budu mít chvilku čas zkusím na to ještě sednout;)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Navrhoval bych řešení typu projít všechny kuličky a zjišťovat, co má za sousedy, pokud by ani jeden z nich nebyl kulička, jednoduše by se kulička nahradila zdí.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

To jsem zkoušel ale jde o to že takto nemusí být zablokovaná jenom jedna kulička,může jich být klidně 5 nebo když to přeženu tak se zeď může rozestavět po celá šířce hracího pole čímž hráč bude úplně odříznutý od vrchní půlky hrací plochy.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

hmm a čo skúsiť pridať test taký, ktorý by hovoril, že každé políčko steny vnútry hracej plochy musí mať aspoň jedného suseda guličku. A ak nemá, tak náhodne vytvorí jednu guličku v okolí.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Prepáčte, že som poukázal na to, čo ste už spomenuli v článku ako nedostatok. Bola už pokročilá večerná hodina....

Vašo

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Ono to není ani moc složité, jenom to chce trochu potrápit hlavičku:

Nám jde o to, aby se ke každému penízku Vaše potvora mohla prokousat. Což tedy ty penízky umisťovat stejně?

Udělám si hrací pole (obvodové a vnitřní zdi) tak, jak jste zvyklý umístím hráče a sám se postavím na stejné pole, jako je on. (modré potvory ještě nechám v klidu).

No a teď se podívám na políčko, které mám po levé ruce, a pokud je toto políčko volné, umístím na něj puntík, postavím na něj brášku a řeknu mu, ať dělá úplně totéž, co já.

Dále se o brášku nestarám a kouknu se na políčko přede mnou a opět - je-li tam pusto a prázdno, dám další puntík a pošlu na něj dalšího brášku se stejnými instrukcemi. Sám se stejným způsobem ještě zajímám o políčko vpravo ode mne a nakonec to za zády. Tím mám padla.

No a každý z mých brášků dělá na "svém" políčku totéž, co jsem před chvílí dělal já, a umístí další bodíky a další brášky....

A až všichni bráškové zkontrolují všechna 4 svá sousední políčka, je pohádky konec a máme vystaráno, protože na všech políčkách, na která je možno jakkoliv dojít z výchozí pozice máme ťumplíky, no a pokud se vám při stavění zdi stane ten malér, že nějakou část pole uzavřete, vůbec to nevadí - vnitřní políčka budou bez penízků (pouze nezapomeňte počítat s tím, že nyní nemáte plný počet bodíků v každém kole při vyhodnocování skóre).

No a v řeči VB tato "složitost" vypadá nesmírně jednoduše:

Sub vykreslitBody()
        ' vykreslíme body všude tam, kde není zeď a přitom je pole přístupné

        ' výchozí poloha bude na souřadnicích, na kterých je umístěn hráč [hrac.X,hrac.Y]
        prozkoumejOkoli(hrac.X, hrac.Y)

        ' po provedeném průzkumu body vykreslím

        For x As Integer = 1 To 15
            For y As Integer = 1 To 15
                If pole(x, y) = obsazeni.bod Then
                    g.DrawImage(ImageList1.Images(9), x * 35, y * 35)
                End If
            Next
        Next

    End Sub

    Private Sub prozkoumejOkoli(ByVal X As Integer, ByVal Y As Integer)
        ' rekurzivní funkce, která jako vstup obdrží bod hracího pole, jehož okolí má prozkoumat

        ' prozkoumáme nejprve políčko vlevo od stávající pozice
        ' pokud je pole vlevo od aktuální pozice prázdné,
        ' pak na ně umístím bod a zkusím opětovným voláním stejné funkce
        ' prozkoumat jeho okolí
        If pole(X - 1, Y) = obsazeni.volno Then pole(X - 1, Y) = obsazeni.bod : prozkoumejOkoli(X - 1, Y)
        ' totéž udělám pro políčko nad aktuální pozicí...
        If pole(X, Y - 1) = obsazeni.volno Then pole(X, Y - 1) = obsazeni.bod : prozkoumejOkoli(X, Y - 1)
        ' ...a vpravo od ní...
        If pole(X + 1, Y) = obsazeni.volno Then pole(X + 1, Y) = obsazeni.bod : prozkoumejOkoli(X + 1, Y)
        ' ... a ještě dole
        If pole(X, Y + 1) = obsazeni.volno Then pole(X, Y + 1) = obsazeni.bod : prozkoumejOkoli(X, Y + 1)


    End Sub

No a pokud se Vám, tak jako mně, po několika pokusech o "rozdání" puntíků na hrací pole stane, že Vám hra "zamrzne", je to tím, že nemáte ošetřenu ještě jednu drobnost a totiž stav, kdy si kolem hráče nastavíte natěsno zdi ze všech 4 stran, takže se chudák hned od začátku nemůže ani hnout.:o(

nahlásit spamnahlásit spam 3 / 3 odpovědětodpovědět

Smekám klobouk, jak názorně se vám povedlo popsat a vysvětlit rekurzi, ten nápad s tím bráškou je naprosto skvělý.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Diskuse: PacMan

Zdravím,

Objevil jsem ve Vaší hře (btw je dobrá :)) malou chybku. Pokud se střetnete s protivníkem a tudíž nastane konec hry, je možno našeho hrdinu "resuscitovat" malým trikem, a sice stiskem volby Pauza v nabídce Hra. Ovšem efekt je pouze dočasný. Nevím čím to je (přiznám se, že zdroáky jsem moc nezkoumal, protože mi teď přerůstají přes hlavy ty moje).

Hodně zdaru při vývoji dalšího projektu

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Děkuji za pochvalu a upozornění na bug, opravím ho:)

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback