Avatar
Honza
Člen
Avatar
Honza:

Dobrý den,
pracuji na ročníkové práci v C#. Je to zjednodušená verze Pacmana. Bludiště mám vytořené pomocí picture boxů (pacman a duch jsou také v picture boxech) a kolize s pacmanem řeším pomocí boolean metody, podle které se určí, zda se pacman může, či nemůže pohnout. Ale narazil jsem na problém s duchy. Chtěl jsem vytvořit pouze náhodný pohyb v bludišti, ale ne a ne se mi to daří. Chtěl bych tedy prosím zažádat o pomoc. V přiloženém kódu je kolize pro pohyb nahoru pro představu, jakým způsobem to mám vyřešené.
Děkuji za všechny odpovědi a návrhy.

PictureBox[] WorldObjects = new PictureBox[34];
private void PacMan_Load(object sender, EventArgs e)
{
    WorldObjects[0] = pictureBox1;
    WorldObjects[1] = pictureBox2;
    WorldObjects[2] = pictureBox4;
    WorldObjects[3] = pictureBox5;
    WorldObjects[4] = pictureBox6;
    WorldObjects[5] = pictureBox7;
    WorldObjects[6] = pictureBox8;
    WorldObjects[7] = pictureBox9;
    WorldObjects[8] = pictureBox10;
    WorldObjects[9] = pictureBox11;
    WorldObjects[10] = pictureBox12;
    WorldObjects[11] = pictureBox13;
    WorldObjects[12] = pictureBox14;
    WorldObjects[13] = pictureBox15;
    WorldObjects[14] = pictureBox16;
    WorldObjects[15] = pictureBox17;
    WorldObjects[16] = pictureBox18;
    WorldObjects[17] = pictureBox19;
    WorldObjects[18] = pictureBox20;
    WorldObjects[19] = pictureBox21;
    WorldObjects[20] = pictureBox22;
    WorldObjects[21] = pictureBox23;
    WorldObjects[22] = pictureBox24;
    WorldObjects[23] = pictureBox25;
    WorldObjects[24] = pictureBox26;
    WorldObjects[25] = pictureBox27;
    WorldObjects[26] = pictureBox28;
    WorldObjects[27] = pictureBox29;
    WorldObjects[28] = pictureBox30;
    WorldObjects[29] = pictureBox31;
    WorldObjects[30] = pictureBox32;
    WorldObjects[31] = pictureBox33;
    WorldObjects[32] = pictureBox34;
    WorldObjects[33] = pictureBox35;


    KolizeUP();
    KolizeDOWN();
    KolizeLEFT();
    KolizeRIGHT();

}
private Boolean KolizeUP()
{
    foreach (PictureBox objekt in WorldObjects)
    {
        if (objekt != null)
        {
            PictureBox temp1 = new PictureBox();
            temp1.Bounds = objekt.Bounds;
            temp1.SetBounds(temp1.Location.X, temp1.Location.Y + 2, temp1.Width, temp1.Height);
            if (pbPacman.Bounds.IntersectsWith(temp1.Bounds))
            {
                return true;
            }
        }

    }
    return false;
}
private void timer1_Tick_1(object sender, EventArgs e)
{
    if (up)
    {
        if (KolizeUP() == false)
            pbPacman.Top -= 2;
    }
 }
Editováno 21.5.2015 17:28
 
Odpovědět 21.5.2015 17:26
Avatar
Honza
Člen
Avatar
Honza:

Ahoj, té implementaci ve tvém kódu moc nerozumím, ale zkusím ti popsat jak jsem obdobně jednoduchou 2D hru řešil já, když jsem si hrál.

V první řadě bych oddělil logiku hry od vykreslování. Pokud tvůj kód chápu dobře tak řešíš kolize tak, že kontroluješ zda se nesrazily dva pictureboxy. Takhle bych to určitě nedělal, protože pokud změníš obrázek, budeš mít .png s průhledným pozadím okolo obrázku apod. tak to nebude moc dobře fungovat.
Hrací plochu bych reprezentoval dvourozměrným polem integeru o velikosti hrací plochy. Předem bych si určil ID typů objektů co které číslo bude znamenat (resp. pro přehlednost bych použil enum). Např. 0 == volné pole, 1 == zeď, 2 == pac man, 3 == duch atd. V tomto poli bude tedy uložen stav celé hry s vyjímkou směru jakým se pohybují objekty které se pohybovat mají.

Pro každý nestatický objekt bych tedy vytvořil instanci jednoduché třídy, která v sobě obsahuje ID typu objektu (odpovídající tomu co doplňuješ do pole), pozici v poli a směr kterým se aktuálně pohybuje. Při každém tiku se všechny objekty mají posunout ve směru který mají nastavený a předpokládám, že na jednom poli může být v jednu chvíli pouze jeden objekt. Předtím si ale musíš zkontrolovat co na daném poli je a podle toho zareagovat(např. pokud pacman narazí do zdi tak se zastaví, pokud duch narazí do zdi tak vygeneruje náhodný směr kam pokračovat, pokud pacman narazí do ducha tak ztratí život atd.) Výhoda tohodle řešení je že není nezbytně nutné procházet celé pole, projdeš jen nestatické objekty a z pole zjistíš co se nachází v jejich bezprostředním okolí.

Ve chvíli kdy je herní logika spočítaná a uložená do pole tak bych zavolal funkci, která podle informací v poli vykreslí scénu. Tím je herní logika nezávislá na grafice. Pokud by jsi to chtěl řešit nějak komplexnějí, popř. tam byly složitější věci, bylo by lepší to všechno řešit objektově, ale na pacmana bohatě stačí pole.

Snad ti tenhle obecný popis trochu pomůže.

Editováno 22.5.2015 11:08
Nahoru Odpovědět  +2 22.5.2015 11:05
Snadnou cestou se daleko nedostanete, je tam velká tlačenice...
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 2 zpráv z 2.