Konzolový Had 5 – Herná scéna

V tomto diely sa pozrieme na samotnú hernú scénu, v ktorej sa všetko bude odohrávať.

Upozornenie : Z Dôvodu dĺžky dielu do neho pridané menu.

Úvod

Scény v našej hre budú slúžiť na prepínanie medzi rôznymi časťami hry, napríklad hlavné menu, alebo obrazovka načítania. Herná scéna bude (ako už názov napovedá) obsahovať hada, všetky objekty alebo vykresľovanie aktuálneho počtu životov, bodov a ďalšie. Tiež bude spravovať zvuky hry a životy.

Návrat do menu

Trieda Level

Na začiatok si ešte vytvoríme jednú triedu, ktorá bude uchovávať informácie o leveli, a bude slúžiť na ich ukladanie a čítanie zo súboru. Bude teda serializovateľná.

Jej premenné budú obsahovať štartovacie pozície, smer, veľkosť, rýchlosť, potrebnú veľkosť na postup do ďalšieho kola a maximálny počet životov, bodov a jedov naraz na obrazovke. Tiež bude obsahovať Modifikátor rýchlosti a všetky prekážky v kole.

[Serializable]
public class Level
{
    public Vector2 Player1_StartPosition;
    public Vector2 Player2_StartPosition;
    public Snake.Side Start_Direction;

    public int StartingSize;
    public int NeededSize;

    public int MaxPoints;
    public int MaxLives;
    public int MaxPoisons;

    public int SpeedModifier;

    public List<Rectangle> Obstacles;
}
Návrat do menu

Premenné

Teraz už sa pozrieme na triedu GameScene. Ako vždy vo väčšej triede sa bude nachádzať množstvo premenných. V tejto ich bude viac ako obyčajne, a to preto, lebo obstaráva samotnú hru.

Ako prvú samozrejme definujeme premennú uchovávajúcu odkaz rodiča typu Game.

private Game Parent;

Po tomto si definujeme hadov pre oboch hráčov a objekty uchovávajúce informácie o vzhľade aktuálneho kola.

private Snake snake1;
private Snake snake2;
private List<Vector2> points = new List<Vector2>();
private List<Vector2> lives = new List<Vector2>();
private List<Vector2> poisons = new List<Vector2>();
private List<Rectangle> obstacles = new List<Rectangle>();

Teraz si deklarujeme premenné, ktoré budú mať informácie o nastavení aktuálneho levelu.

private int maxPoints = 3;
private int maxLives = 1;
private int maxPoisons = 1;

Ďalej deklarujeme niekoľko premenných, ktoré si budú pamätať počiatočné hodnoty aktuálneho kola.

private Vector2 startingPos1;
private Vector2 startingPos2;
private int startingSize;
private int speed;
private int needSize;
private Snake.Side startingDir;

Teraz deklarujeme pár premenných na správu bodov a životov.

private bool IsThereLive = false;
private bool IsTherePoison = false;

Na záver príjdu objekty obsahujúce niektoré interné informácie tejto triedy, ako napríklad zapnutie multiplayerugenerátor náhodných číselovládanie alebo slot uloženia.

public int SaveFile = 0;
public bool MultiPlayer = false;
private Random r = new Random();
private Dictionary<Snake.Side, ConsoleKey> controls1 = new Dictionary<Snake.Side, ConsoleKey>();
private Dictionary<Snake.Side, ConsoleKey> controls2 = new Dictionary<Snake.Side, ConsoleKey>();
Návrat do menu

Pomocné metódy

Aby sme si ďalšiu prácu uľahčili, použijeme viaceré pomocné metódy.

Generácia bodu

Začneme generovaním bodov, ktoré bude had zbierať.

Vector2 point = new Vector2(0,0);
point.X = r.Next(0, Renderer.WindowSize.X);
point.Y = r.Next(2, Renderer.WindowSize.Y);
bool collision = snake1.CheckCollisionFull(point);
if (MultiPlayer)
    collision |= snake2.CheckCollisionFull(point);

Najprv si deklarujeme pár premenných a nastavíme ich. Ako prvé vygenerujeme náhodný bod (pomocou nášho generátora náhodných čísel r). Pozícia X bude vybratá ako náhodný bod medzi pozíciou 0 (úplne vľavo) a veľkosťou obrazovky (úplne vpravo). Pozícia Y sa nachádza až od bodu 2 – preskočíme teda dva riadky, ktoré budú ukazovať naše skóre.

Po tomto si vytvoríme boolovu premennú, ktorá skontroluje kolíziu z hadom (v prípade že hráme multiplayer, skontroluje aj druhého hráča). Táto kontrola je tu z dôvodu, aby sa bod nevygeneroval vnútri hráča.

foreach (Vector2 pnt in lives)
{
    collision |= (pnt == point);
}

foreach (Vector2 pnt in points)
{
    collision |= (pnt == point);
}

foreach (Vector2 pnt in poisons)
{
    collision |= (pnt == point);
}

foreach (Rectangle pnt in obstacles)
{
    collision |= pnt.Intersects(pnt);
}

Teraz si skontrolujeme kolízie aj zo všetkými ostatnými bodmi a prekážkami.

Po tomto prichádza na radu slučka while, ktorá bude prebiehať, dokým sa bod nevygeneruje na správnom mieste.

while (collision)
{
    point.X = r.Next(0, Renderer.WindowSize.X);
    point.Y = r.Next(2, Renderer.WindowSize.Y);

    collision = snake1.CheckCollisionFull(point);
    if (MultiPlayer)
        collision |= snake2.CheckCollisionFull(point);

    foreach (Vector2 pnt in lives)
    {
        collision |= (pnt == point);
    }

    foreach (Vector2 pnt in points)
    {
        collision |= (pnt == point);
    }

    foreach (Vector2 pnt in poisons)
    {
        collision |= (pnt == point);
    }

    foreach (Rectangle pnt in obstacles)
    {
        collision |= pnt.Intersects(pnt);
    }
}

Na záver už len vrátime jeho pozíciu.

return point;

Zobraziť celú metódu

public Vector2 GeneratePoint()
{
    Vector2 point = new Vector2(0,0);
    point.X = r.Next(0, Renderer.WindowSize.X);
    point.Y = r.Next(2, Renderer.WindowSize.Y);
    bool collision = (snake1.CheckCollisionFull(point)) || (snake1.CheckCollisionFull(point));
    if (MultiPlayer)
        collision |= (snake2.CheckCollisionFull(point)) || (snake2.CheckCollisionFull(point));
    foreach (Vector2 pnt in lives)
    {
        collision |= (pnt == point);
    }

    foreach (Vector2 pnt in points)
    {
        collision |= (pnt == point);
    }

    foreach (Vector2 pnt in poisons)
    {
        collision |= (pnt == point);
    }

    foreach (Rectangle pnt in obstacles)
    {
        collision |= pnt.Intersects(pnt);
    }
    while (collision)
    {
        point.X = r.Next(0, Renderer.WindowSize.X);
        point.Y = r.Next(2, Renderer.WindowSize.Y);

        collision = snake1.CheckCollisionFull(point);
        if (MultiPlayer)
            collision |= snake2.CheckCollisionFull(point);

        foreach (Vector2 pnt in lives)
        {
            collision |= (pnt == point);
        }

        foreach (Vector2 pnt in points)
        {
            collision |= (pnt == point);
        }

        foreach (Vector2 pnt in poisons)
        {
            collision |= (pnt == point);
        }

        foreach (Rectangle pnt in obstacles)
        {
            collision |= pnt.Intersects(pnt);
        }
    }
    return point;
}

Návrat do menu

Načítanie levelu zo súboru

Načítavanie levelu zo súboru hry bude jeden zo spôsobov ako nový level vytvoriť. Vytvoríme si na to metódu void LoadFile(string file).

Tu použijeme našu triedu z minulého dielu na načítanie súboru. Následne už len priradíme premenné z načítaného súboru, nastavíme rýchlosť a vytvoríme hadov – v prípade hry dvoch hráčov otočíme smer druhého hada.

public void LoadFile(string file)
{
    Level l = FileController.Load<Level>(file);

    maxPoints = l.MaxPoints;
    maxLives = l.MaxLives;
    maxPoisons = l.MaxPoisons;
            
    speed = 10 - (Parent.Level / l.SpeedModifier);
    if (speed <= 0) speed = 1;
    needSize = l.NeededSize;
    startingSize = l.StartingSize;
    startingDir = l.Start_Direction;

    startingPos1 = l.Player1_StartPosition;
    startingPos2 = l.Player2_StartPosition;

    obstacles.Clear();

    snake1 = new Snake(this, true, startingPos1, needSize, speed, startingSize, startingDir, controls1);
    Snake.Side dir2;
    if (startingDir == Snake.Side.Down) dir2 = Snake.Side.Up;
    else if (startingDir == Snake.Side.Up) dir2 = Snake.Side.Down;
    else if (startingDir == Snake.Side.Left) dir2 = Snake.Side.Right;
    else dir2 = Snake.Side.Left;
    if (MultiPlayer) snake2 = new Snake(this, false, startingPos2, needSize, speed, startingSize, dir2, controls2);

    foreach (Rectangle rec in l.Obstacles)
    {
        obstacles.Add(rec);
    }
}
Návrat do menu

Generovanie náhodného levelu

Pokiaľ level, ktorý hráč začal nemá súbor, bude vygenenerovaný náhodne. Na to slúži metóda void MakeRandom().

Tá na začiatku vygeneruje náhodné údaje pre pozícia hráča, počet bodov, veľkosti a smery a priradí ich podobne ako pri načítavaní kola.

maxPoints = r.Next(1,7);
maxLives = r.Next(1,3);
maxPoisons = r.Next(1,3);

int spdr = r.Next(1, 3);
speed = 10 - (Parent.Level/spdr);
if (speed <= 0) speed = 1;
needSize = r.Next(10, 100);
startingSize = r.Next(0, 9);
startingDir = (Snake.Side)(r.Next(0, 4));

startingPos1 = new Vector2(r.Next(10,Renderer.WindowSize.X-10), r.Next(10, Renderer.WindowSize.Y - 12));
startingPos2 = new Vector2(Renderer.WindowSize.X-startingPos1.X, Renderer.WindowSize.Y-startingPos1.Y);

obstacles.Clear();

snake1 = new Snake(this, true, startingPos1, needSize, speed, startingSize, startingDir, controls1);
Snake.Side dir2;
if (startingDir == Snake.Side.Down) dir2 = Snake.Side.Up;
else if (startingDir == Snake.Side.Up) dir2 = Snake.Side.Down;
else if (startingDir == Snake.Side.Left) dir2 = Snake.Side.Right;
else dir2 = Snake.Side.Left;
if (MultiPlayer) snake2 = new Snake(this, false, startingPos2, needSize, speed, startingSize, dir2, controls2);

Následne vygeneruje bežné okrajové prekážky. Tých budú tri typy : A) žiadne prekážky, B) celý okraj, C) okraj z medzerami. Na to vygenerujeme náhodné číslo od 0 do 10. V prípade ak bude vygenerované číslo medzi 3-6, vytvoríme celý okraj, ak bude viac ako 6, vytvoríme okraj z medzerami, inak nevytvoríme žiadny.

int sides = r.Next(0, 10);
if ((sides > 3) && (sides < 6))
{
    obstacles.Add(new Rectangle(1, 2, Renderer.WindowSize.X - 2, 1));
    obstacles.Add(new Rectangle(1, Renderer.WindowSize.Y - 1, Renderer.WindowSize.X - 2, 1));
    obstacles.Add(new Rectangle(0, 3, 1, Renderer.WindowSize.Y - 4));
    obstacles.Add(new Rectangle(Renderer.WindowSize.X - 1, 3, 1, Renderer.WindowSize.Y - 4));
}
else if ((sides >= 6))
{
    obstacles.Add(new Rectangle(1, 2, (Renderer.WindowSize.X - 2)/2-10, 1));
    obstacles.Add(new Rectangle((Renderer.WindowSize.X - 2) / 2+11, 2, (Renderer.WindowSize.X - 2) / 2 - 10, 1));
    obstacles.Add(new Rectangle(1, Renderer.WindowSize.Y-1, (Renderer.WindowSize.X - 2) / 2 - 10, 1));
    obstacles.Add(new Rectangle((Renderer.WindowSize.X - 2) / 2 + 11, Renderer.WindowSize.Y-1,(Renderer.WindowSize.X - 2) /2 - 10, 1));
    obstacles.Add(new Rectangle(0, 3, 1, (Renderer.WindowSize.Y - 4)/2-5));
    obstacles.Add(new Rectangle(0, (Renderer.WindowSize.Y - 4) / 2 + 8, 1, (Renderer.WindowSize.Y - 4)/2-5));
    obstacles.Add(new Rectangle(Renderer.WindowSize.X-1, 3, 1, (Renderer.WindowSize.Y - 4) / 2 - 5));
    obstacles.Add(new Rectangle(Renderer.WindowSize.X - 1, (Renderer.WindowSize.Y - 4) / 2 + 8, 1, (Renderer.WindowSize.Y - 4) / 2 - 5));
}

Na záver ešte vygenerujeme pár náhodných prekážok, ktoré overíme aby nemali kolíziu z hráčom.

for (int i = 0; i < r.Next(0, 5); i++)
{
    Rectangle rec = new Rectangle(r.Next(10, Renderer.WindowSize.X - 10), r.Next(10, Renderer.WindowSize.Y - 10), r.Next(1, 20), r.Next(1, 10));

    if (!MultiPlayer)
        while (snake1.CheckCollisionFull(rec))
        {
            rec = new Rectangle(r.Next(10, Renderer.WindowSize.X - 10), r.Next(10, Renderer.WindowSize.Y - 10), r.Next(1, 20), r.Next(1, 10));
        }
    else
        while ((snake1.CheckCollisionFull(rec)) || (snake2.CheckCollisionFull(rec)))
        {
            rec = new Rectangle(r.Next(10, Renderer.WindowSize.X - 10), r.Next(10, Renderer.WindowSize.Y - 10), r.Next(1, 20), r.Next(1, 10));
        }
    obstacles.Add(rec);
}

Zobraziť celú metódu

public void MakeRandom()
{
    maxPoints = r.Next(1,7);
    maxLives = r.Next(1,3);
    maxPoisons = r.Next(1,3);

    int spdr = r.Next(1, 3);
    speed = 10 - (Parent.Level/spdr);
    if (speed <= 0) speed = 1;
    needSize = r.Next(10, 100);
    startingSize = r.Next(0, 9);
    startingDir = (Snake.Side)(r.Next(0, 4));

    startingPos1 = new Vector2(r.Next(10,Renderer.WindowSize.X-10), r.Next(10, Renderer.WindowSize.Y - 12));
    startingPos2 = new Vector2(Renderer.WindowSize.X-startingPos1.X, Renderer.WindowSize.Y-startingPos1.Y);

    obstacles.Clear();

    snake1 = new Snake(this, true, startingPos1, needSize, speed, startingSize, startingDir, controls1);
    Snake.Side dir2;
    if (startingDir == Snake.Side.Down) dir2 = Snake.Side.Up;
    else if (startingDir == Snake.Side.Up) dir2 = Snake.Side.Down;
    else if (startingDir == Snake.Side.Left) dir2 = Snake.Side.Right;
    else dir2 = Snake.Side.Left;
    if (MultiPlayer) snake2 = new Snake(this, false, startingPos2, needSize, speed, startingSize, dir2, controls2);

    int sides = r.Next(0, 10);
    if ((sides > 3) && (sides < 6))
    {
        obstacles.Add(new Rectangle(1, 2, Renderer.WindowSize.X - 2, 1));
        obstacles.Add(new Rectangle(1, Renderer.WindowSize.Y - 1, Renderer.WindowSize.X - 2, 1));
        obstacles.Add(new Rectangle(0, 3, 1, Renderer.WindowSize.Y - 4));
        obstacles.Add(new Rectangle(Renderer.WindowSize.X - 1, 3, 1, Renderer.WindowSize.Y - 4));
    }
    else if ((sides >= 6))
    {
        obstacles.Add(new Rectangle(1, 2, (Renderer.WindowSize.X - 2)/2-10, 1));
        obstacles.Add(new Rectangle((Renderer.WindowSize.X - 2) / 2+11, 2, (Renderer.WindowSize.X - 2) / 2 - 10, 1));
        obstacles.Add(new Rectangle(1, Renderer.WindowSize.Y-1, (Renderer.WindowSize.X - 2) / 2 - 10, 1));
        obstacles.Add(new Rectangle((Renderer.WindowSize.X - 2) / 2 + 11, Renderer.WindowSize.Y-1,(Renderer.WindowSize.X - 2) /2 - 10, 1));
        obstacles.Add(new Rectangle(0, 3, 1, (Renderer.WindowSize.Y - 4)/2-5));
        obstacles.Add(new Rectangle(0, (Renderer.WindowSize.Y - 4) / 2 + 8, 1, (Renderer.WindowSize.Y - 4)/2-5));
        obstacles.Add(new Rectangle(Renderer.WindowSize.X-1, 3, 1, (Renderer.WindowSize.Y - 4) / 2 - 5));
        obstacles.Add(new Rectangle(Renderer.WindowSize.X - 1, (Renderer.WindowSize.Y - 4) / 2 + 8, 1, (Renderer.WindowSize.Y - 4) / 2 - 5));
    }

    for (int i = 0; i < r.Next(0, 5); i++)
    {
        Rectangle rec = new Rectangle(r.Next(10, Renderer.WindowSize.X - 10), r.Next(10, Renderer.WindowSize.Y - 10), r.Next(1, 20), r.Next(1, 10));

        if (!MultiPlayer)
            while (snake1.CheckCollisionFull(rec))
            {
                rec = new Rectangle(r.Next(10, Renderer.WindowSize.X - 10), r.Next(10, Renderer.WindowSize.Y - 10), r.Next(1, 20), r.Next(1, 10));
            }
        else
            while ((snake1.CheckCollisionFull(rec)) || (snake2.CheckCollisionFull(rec)))
            {
                rec = new Rectangle(r.Next(10, Renderer.WindowSize.X - 10), r.Next(10, Renderer.WindowSize.Y - 10), r.Next(1, 20), r.Next(1, 10));
            }
        obstacles.Add(rec);
    }
}

Návrat do menu

Načítanie kola

Nasleduje metóda, ktorá vyberie, ktorá z predošlých dvoch metód sa má vykonať a následne vygenerované kolo pripraví – jedná sa o metódu public void LoadLevel().

Najprv skontrolujeme, či pre kolo, ktoré nasleduje existuje súbor. Pre to sa pozrieme do zložky Levels a zistíme či tam existuje súbor Level číslokola .lvl (napr. Level3.lvl). Ak existuje, tak ho načíta metódou LoadFile. Inak použije metódu MakeRandom.

if ((Directory.Exists("Levels")) && (File.Exists("Levels\\Level" + Parent.Level + ".lvl"))) LoadFile("Levels\\Level" + Parent.Level + ".lvl");
else MakeRandom();

Ďalej obom hadom priradí metódy k eventom (metódy si ukážeme neskôr).

snake1.GotScore += GotScore;
snake1.GotLive += GotLive;
snake1.Died += Died;
snake1.Complete += Completed;

snake1.AtePoint += AtePoint;
snake1.AteLive += AteLive;
snake1.AtePoision += AtePoison;

if (MultiPlayer)
{
    snake2.GotScore += GotScore;
    snake2.GotLive += GotLive;
    snake2.Died += Died;
    snake2.Complete += Completed;

    snake2.AtePoint += AtePoint;
    snake2.AteLive += AteLive;
    snake2.AtePoision += AtePoison;
}

Na záver ešte vygenerujeme všetky body.

for (int i = 0; i < maxPoints; i++)
{
    points.Add(GeneratePoint());
}
for (int i = 0; i < maxPoisons; i++)
{
    poisons.Add(GeneratePoint());
}
for (int i = 0; i < maxLives; i++)
{
    lives.Add(GeneratePoint());
}

Zobraz celú metódu

public void LoadLevel()
{
    if ((Directory.Exists("Levels")) && (File.Exists("Levels\\Level" + Parent.Level + ".lvl"))) LoadFile("Levels\\Level" + Parent.Level + ".lvl");
    else MakeRandom();

    snake1.GotScore += GotScore;
    snake1.GotLive += GotLive;
    snake1.Died += Died;
    snake1.Complete += Completed;

    snake1.AtePoint += AtePoint;
    snake1.AteLive += AteLive;
    snake1.AtePoision += AtePoison;

    if (MultiPlayer)
    {
        snake2.GotScore += GotScore;
        snake2.GotLive += GotLive;
        snake2.Died += Died;
        snake2.Complete += Completed;

        snake2.AtePoint += AtePoint;
        snake2.AteLive += AteLive;
        snake2.AtePoision += AtePoison;
    }

    for (int i = 0; i < maxPoints; i++)
    {
        points.Add(GeneratePoint());
    }
    for (int i = 0; i < maxPoisons; i++)
    {
        poisons.Add(GeneratePoint());
    }
    for (int i = 0; i < maxLives; i++)
    {
        lives.Add(GeneratePoint());
    }
}

Návrat do menu

Resetovanie kola

Na resetovanie kola sa používa prakticky totožná metóda z pár malými zmenami. Jediný rozdiel je, že pôvodného hada vygenerujeme nanovo.

Zobraz metódu

public void ResetLevel()
{
    snake1 = new Snake(this, true, startingPos1, needSize, speed, startingSize, startingDir, controls1);
    snake1.GotScore += GotScore;
    snake1.GotLive += GotLive;
    snake1.Died += Died;
    snake1.Complete += Completed;

    snake1.AtePoint += AtePoint;
    snake1.AteLive += AteLive;
    snake1.AtePoision += AtePoison;

    if (MultiPlayer)
    {

        Snake.Side dir2;
        if (startingDir == Snake.Side.Down) dir2 = Snake.Side.Up;
        else if (startingDir == Snake.Side.Up) dir2 = Snake.Side.Down;
        else if (startingDir == Snake.Side.Left) dir2 = Snake.Side.Right;
        else dir2 = Snake.Side.Left;

        snake2 = new Snake(this, false, startingPos2, needSize, speed, startingSize, dir2, controls2);
        snake2.GotScore += GotScore;
        snake2.GotLive += GotLive;
        snake2.Died += Died;
        snake2.Complete += Completed;

        snake2.AtePoint += AtePoint;
        snake2.AteLive += AteLive;
        snake2.AtePoision += AtePoison;

    }

    points.Clear();
    poisons.Clear();
    lives.Clear();
    for (int i = 0; i < maxPoints; i++)
    {
        points.Add(GeneratePoint());
    }
    for (int i = 0; i < maxPoisons; i++)
    {
        poisons.Add(GeneratePoint());
    }
    for (int i = 0; i < maxLives; i++)
    {
        lives.Add(GeneratePoint());
    }
}

Návrat do menu

Resetovanie scény

Metóda na resetovanie scény – public void ResetScene() je pomerne jednoduchá a len nanovo načíta pár premenných a kolo.

Ako prvé vyčistíme ovládanie a nanovo ho priradíme, potom vyčistíme zoznamy bodov a nakoniec zavoláme metódu LoadLevel().

public void ResetScene()
{
    controls1.Clear();
    controls2.Clear();
    controls1.Add(Snake.Side.Up, ConsoleKey.W);
    controls1.Add(Snake.Side.Down, ConsoleKey.S);
    controls1.Add(Snake.Side.Left, ConsoleKey.A);
    controls1.Add(Snake.Side.Right, ConsoleKey.D);
    controls2.Add(Snake.Side.Up, ConsoleKey.UpArrow);
    controls2.Add(Snake.Side.Down, ConsoleKey.DownArrow);
    controls2.Add(Snake.Side.Left, ConsoleKey.LeftArrow);
    controls2.Add(Snake.Side.Right, ConsoleKey.RightArrow);

    points = new List<Vector2>();
    lives = new List<Vector2>();
    poisons = new List<Vector2>();

    LoadLevel();
}
Návrat do menu

Vyresľovanie informácií

Na záver prichádza pomocná trieda na vykreslenie informačného panelu – private void DrawInfo().

Najprv si vykreslíme (pomocou triedy Renderer) modrý obdĺžnik, ktorý bude mať šírku obrazovky a výšku dva riadky.

Renderer.DrawRectangle(new Rectangle(0, 0, Renderer.WindowSize.X, 2), ConsoleColor.Blue);

Po tomto si vytvoríme pár stringov, ktoré budú obsahovať text informujúci o životoch, skóre a čísle levela a vykreslíme ich do prvého riadku.

string livString = "Lives : " + Parent.Lives;<br>string levString = "Level : " + Parent.Level;<br>string scoString = "Score : " + Parent.Score;
Renderer.DrawString(livString, new Vector2(1, 0), ConsoleColor.White);
Renderer.DrawString(levString, new Vector2((Renderer.WindowSize.X - levString.Length) / 2, 0), ConsoleColor.White); //Výpočet stredovej pozície
Renderer.DrawString(scoString, new Vector2(Renderer.WindowSize.X - 1 - scoString.Length, 0), ConsoleColor.White); //Výpočet pozície sprava

Poznámka: Na tomto mieste bude Visual Studio vypisovať chyby, pretože vaša trieda Game ešte neobsahuje všetky premenné.

Do druhého riadku podobným spôsobom vypíšeme informácie o aktuálnej a potrebnej veľkosti podľa počtu hráčov.

if (!MultiPlayer)
{
    string sizString = "Current Size : " + snake1.Size;
    string neeString = "Needed Size : " + snake1.NeedToComplete;
    Renderer.DrawString(sizString, new Vector2(1, 1), ConsoleColor.White);
    Renderer.DrawString(neeString, new Vector2(Renderer.WindowSize.X - 1 - neeString.Length, 1), ConsoleColor.White);
}
else
{
    string siz1String = "Player 1 Size : " + snake1.Size;
    string siz2String = "Player 2 Size : " + snake2.Size;
    string neeString = "Needed Size : " + (snake1.NeedToComplete*2);
    Renderer.DrawString(siz1String, new Vector2(1, 1), ConsoleColor.White);
    Renderer.DrawString(siz2String, new Vector2(Renderer.WindowSize.X - 1 - siz2String.Length, 1), ConsoleColor.White);
    Renderer.DrawString(neeString, new Vector2((Renderer.WindowSize.X - neeString.Length)/2, 1), ConsoleColor.White);
}

V prípade jedného hráča vypíšeme aktuálnu veľkosť vľavo a potrebnú v pravo, v prípade dvoch hráčov vypíšeme veľkosť hráča 1 vľavo, veľkosť hráča 2 vpravo a potrebnú veľkosť do stredu. Potrená veľkosť je pri hre dvoch hráčov násobená dvoma.

Zobraziť celú funkciu

private void DrawInfo()
{
    Renderer.DrawRectangle(new Rectangle(0, 0, Renderer.WindowSize.X, 2), ConsoleColor.Blue);
    string livString = "Lives : " + Parent.Lives;
    string levString = "Level : " + Parent.Level;
    string scoString = "Score : " + Parent.Score;
    Renderer.DrawString(livString, new Vector2(1, 0), ConsoleColor.White);
    Renderer.DrawString(levString, new Vector2((Renderer.WindowSize.X - levString.Length) / 2, 0), ConsoleColor.White);
    Renderer.DrawString(scoString, new Vector2(Renderer.WindowSize.X - 1 - scoString.Length, 0), ConsoleColor.White);
    if (!MultiPlayer)
    {
        string sizString = "Current Size : " + snake1.Size;
        string neeString = "Needed Size : " + snake1.NeedToComplete;
        Renderer.DrawString(sizString, new Vector2(1, 1), ConsoleColor.White);
        Renderer.DrawString(neeString, new Vector2(Renderer.WindowSize.X - 1 - neeString.Length, 1), ConsoleColor.White);
    }
    else
    {
        string siz1String = "Player 1 Size : " + snake1.Size;
        string siz2String = "Player 2 Size : " + snake2.Size;
        string neeString = "Needed Size : " + (snake1.NeedToComplete*2);
        Renderer.DrawString(siz1String, new Vector2(1, 1), ConsoleColor.White);
        Renderer.DrawString(siz2String, new Vector2(Renderer.WindowSize.X - 1 - siz2String.Length, 1), ConsoleColor.White);
        Renderer.DrawString(neeString, new Vector2((Renderer.WindowSize.X - neeString.Length)/2, 1), ConsoleColor.White);
    }
}

Návrat do menu

Update a Draw

Teraz prichádzajú na rad dve najzákladnejšie metódy, a to Update a Draw – tie budú obstarávať všetko vykresľovanie a aktualizácie logiky.

Update

Začnime ovládaním hry. To bude prebiehať cez konzolový vstup. Najprv si musíme overiť, či je stlačené tlačidlo. Ak áno, tak si ho zaznamenáme a odošleme hadom. Ak je stlačený escape, otvoríme pauzu.

if (Console.KeyAvailable)
{
    ConsoleKeyInfo pressed = Console.ReadKey(true);
    if (pressed.Key == ConsoleKey.Escape) { Parent.currentScene = Game.Scenes.Pause; }
    snake1.Control(pressed);
    if (MultiPlayer) snake2.Control(pressed);
}

Poznámka : v triede Game ešte Scénu Pause nemáte, takže vám tam bude ukazovať chybu.

Ďalej nastavíme podľa náhody zobrazenie životov alebo jedov.

if (!IsThereLive)
    IsThereLive = r.Next(0, 1000) == 1;
if (!IsTherePoison)
    IsTherePoison = r.Next(0, 100) == 1;

A na záver zavoláme metódy Update u hadov. Ak sú premenné IsThereLives a IsTherePoison false, odošleme im ako zoznam bodov, životov a jedov len prázdny List.

snake1.Update((IsThereLive) ? lives : new List<Vector2>(), points, (IsTherePoison) ? poisons : new List<Vector2>(), obstacles, snake2);
if (MultiPlayer) snake2.Update((IsThereLive) ? lives : new List<Vector2>(), points, (IsTherePoison) ? poisons : new List<Vector2>(), obstacles, snake1);

Zobraz celú metódu

public void Update()
{
    if (Console.KeyAvailable)
    {
        ConsoleKeyInfo pressed = Console.ReadKey(true);
        if (pressed.Key == ConsoleKey.Escape) { Parent.currentScene = Game.Scenes.Pause; }
        snake1.Control(pressed);
        if (MultiPlayer) snake2.Control(pressed);
    }
    if (!IsThereLive)
        IsThereLive = r.Next(0, 1000) == 1;
    if (!IsTherePoison)
        IsTherePoison = r.Next(0, 100) == 1;
    snake1.Update((IsThereLive) ? lives : new List<Vector2>(), points, (IsTherePoison) ? poisons : new List<Vector2>(), obstacles, snake2);
    if (MultiPlayer) snake2.Update((IsThereLive) ? lives : new List<Vector2>(), points, (IsTherePoison) ? poisons : new List<Vector2>(), obstacles, snake1);
}

Návrat do menu

Draw

Metóda Draw bude slúžiť na vykresľovanie všetkého na obrazovku. Najprv musíme vykresliť body – životy a jedy budeme vykreslovať len ak sú premenné IsThereLifeIsTherePoison true. Po tomto vykreslíme prekážky, ktoré, pokiaľ sú väčšie ako 3×3 budú mať bledšiu výplň. Na záver už len vykreslíme hadov pomocou ich metódy Draw a použijeme pomocnú metódu DrawInfo.

public void Draw()
{
    foreach (Vector2 point in points)
    {
        Renderer.DrawPoint(point, ConsoleColor.Blue);
    }
    if (IsTherePoison)
        foreach (Vector2 poison in poisons)
        {
            Renderer.DrawPoint(poison, ConsoleColor.Red);
        }
    if (IsThereLive)
        foreach (Vector2 live in lives)
        {
            Renderer.DrawPoint(live, ConsoleColor.Green);
        }

    foreach(Rectangle r in obstacles)
    {
        Renderer.DrawRectangle(r, ConsoleColor.DarkGray);
        if ((r.Width > 3) && (r.Height > 3))
        {
            Renderer.DrawRectangle(new Rectangle(r.X+1, r.Y+1,r.Width-2, r.Height-2), ConsoleColor.Gray);
            //Tento kód nakreslí druhý obdĺžnik vo vnútri prvého, ktorý je o 1 pixel posunutý doprava dole, a je o dva pixeli menší z každej strany.
        }
    }

    snake1.Draw();
    if (MultiPlayer) snake2.Draw();

    DrawInfo();
}
Návrat do menu

Eventy

Nakoniec prichádzajú eventy, ktoré vyvolá had.

GotScore

Metóda eventu GotScore – public void GotScore(object sender, int e) slúži na zvýšenie skóre (ktorý sa ukladá v triede Game). Jednoducho k nemu pripočíta hodnotu, ktorú dostane ako argument e.

public void GotScore(object sender, int e)
{
    Parent.Score += e;
}
Návrat do menu

GotLive

Metóda pre event GotLive – public void GotLive(object sender, EventArgs e) pripočíta život po jeho získaní.

public void GotLive(object sender, EventArgs e)
{
    Parent.Lives++;
}
Návrat do menu

Died

Táto metóda sa aktivuje po smrti hráča. Public void Died(object sender, Snake.DeathCause e) zníži počet životov o jeden.

Ak je počet životov menší ako nula, nastaví sa pre scénu HighscoreScn (ktorú ešte nemáme hotovú) premenná MP, aby bola rovnaká ako naša premenná multiplayer, povie sa tejto scéne, nech načíta tabuľku najvyšších skóre a nastaví sa jej aktuálne skóre.

Ak počet životov nieje menší ako nula, bude zahraná jednoduchá melódia a následne sa v prípade multiplayerovej hry zmenší had na začiatočnú veľkosť, inak sa reštartuje level. Level sa reštartuje pri multiplayeri, aj keď narazíme do protihráča.

public void Died(object sender, Snake.DeathCause e)
{
    Parent.Lives--;
    if (Parent.Lives < 0)
    {
        Parent.HighscoreScn.MP = MultiPlayer;
        Parent.HighscoreScn.LoadScores();
        Parent.currentScene = Game.Scenes.HighScore;
    }
    else
    {
        Console.Beep(1000, 500);
        Console.Beep(500, 500);
        Console.Beep(250, 500);
        if ((!MultiPlayer) || (e == Snake.DeathCause.CollisionOppenent))
        {
            ResetLevel();
        }
        else
        {
            ((Snake)sender).Size = startingSize;
        }
    }
}
Návrat do menu

Completed

Event public void Completed(object sender, EventArgs e) je zavolaný, keď sa dokončí kolo. Po jeho zavolaní sa zahrá jednoduchá melódia, uloží hra, zvýši číslo kola a resetuje scéna.

public void Completed(object sender, EventArgs e)
{
    Console.Beep(250, 500);
    Console.Beep(500, 1000);
    Console.Beep(1000, 500);
    Console.Beep(1000, 500);
    Parent.Level++;
    SaveState state = new SaveState();
    state.Level = Parent.Level;
    state.Lives = Parent.Lives;
    state.Score = Parent.Score;
    FileController.Save<SaveState>(state, "Saves\\Save_" + ((!MultiPlayer)?"SP_":"MP_") + SaveFile + ".xml");
    ResetScene();
}

Meno súboru je vygenerované podľa toho či hráme multiplayer a podľa úložného slotu. (napr Save_SP_1.xml pre prvý save singleplayeru).

Návrat do menu

AtePoint

Event public void AtePoint(object sender, Vector2 e) sa zavolá po zjedení bodu. Po jeho zavolaní vygeneruje zjedený pod na novom mieste a zahrá krátky tón.

public void AtePoint(object sender, Vector2 e)
{
    foreach (Vector2 point in points)
    {
        if (point == e)
        {
            Vector2 p = GeneratePoint();
            point.X = p.X;
            point.Y = p.Y;
        }
    }
    Console.Beep(1000,10);
}
Návrat do menu

AteLive

Event public void AteLive(object sender, Vector2 e) sa zavolá po zjedení života. Je podobný predošlému, no okrem zahrania melódie aj nastaví premennú IsThereLife na hodnotu false.

public void AteLive(object sender, Vector2 e)
{
    foreach (Vector2 point in lives)
    {
        if (point == e)
        {
            Vector2 p = GeneratePoint();
            point.X = p.X;
            point.Y = p.Y;
        }
    }
    Console.Beep(500, 50);
    Console.Beep(1000, 50);
    Console.Beep(1500, 50);
    IsThereLive = false;
}
Návrat do menu

AtePoison

Na záver tu máme event public void AtePoison(object sender, Vector2 e), ktorý je zhodný s predošlym, len nastavuje premennú IsTherePoison.

public void AtePoison(object sender, Vector2 e)
{
    foreach (Vector2 point in poisons)
    {
        if (point == e)
        {
            Vector2 p = GeneratePoint();
            point.X = p.X;
            point.Y = p.Y;
        }
        Console.Beep(1000, 50);
        Console.Beep(500, 50);
        Console.Beep(250, 50);
        IsTherePoison = false;
    }
}
Návrat do menu

A toto je celá trieda GameScene. Teraz už máme väčšinu hry dokončenú, a nabudúce sa pozrieme na scénu zobrazujúce najvyššie skóre. Ešte vám sem vložím celý kód triedy GameScene.

Zobraziť celú triedu

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Snake
{
public class GameScene
{
private Game Parent;
private Snake snake1;
private Snake snake2;
private List<Vector2> points = new List<Vector2>();
private List<Vector2> lives = new List<Vector2>();
private List<Vector2> poisons = new List<Vector2>();
private List<Rectangle> obstacles = new List<Rectangle>();
private int maxPoints = 3;
private int maxLives = 1;
private int maxPoisons = 1;
private Vector2 startingPos1;
private Vector2 startingPos2;
private int startingSize;
private int speed;
private int needSize;
private Snake.Side startingDir;
private bool IsThereLive = false;
private bool IsTherePoison = false;
public int SaveFile = 0;
public bool MultiPlayer = false;
private Random r = new Random();
private Dictionary<Snake.Side, ConsoleKey> controls1 = new Dictionary<Snake.Side, ConsoleKey>();
private Dictionary<Snake.Side, ConsoleKey> controls2 = new Dictionary<Snake.Side, ConsoleKey>();
public Vector2 GeneratePoint()
{
Vector2 point = new Vector2(0,0);
point.X = r.Next(0, Renderer.WindowSize.X);
point.Y = r.Next(2, Renderer.WindowSize.Y);
bool collision = (snake1.CheckCollisionFull(point)) || (snake1.CheckCollisionFull(point));
if (MultiPlayer)
collision |= (snake2.CheckCollisionFull(point)) || (snake2.CheckCollisionFull(point));
foreach (Vector2 pnt in lives)
{
collision |= (pnt == point);
}
foreach (Vector2 pnt in points)
{
collision |= (pnt == point);
}
foreach (Vector2 pnt in poisons)
{
collision |= (pnt == point);
}
foreach (Rectangle pnt in obstacles)
{
collision |= pnt.Intersects(pnt);
}
while (collision)
{
point.X = r.Next(0, Renderer.WindowSize.X);
point.Y = r.Next(2, Renderer.WindowSize.Y);
collision = snake1.CheckCollisionFull(point);
if (MultiPlayer)
collision |= snake2.CheckCollisionFull(point);
foreach (Vector2 pnt in lives)
{
collision |= (pnt == point);
}
foreach (Vector2 pnt in points)
{
collision |= (pnt == point);
}
foreach (Vector2 pnt in poisons)
{
collision |= (pnt == point);
}
foreach (Rectangle pnt in obstacles)
{
collision |= pnt.Intersects(pnt);
}
}
return point;
}
public GameScene(Game parent)
{
Parent = parent;
ResetScene();
}
public void MakeRandom()
{
maxPoints = r.Next(1,7);
maxLives = r.Next(1,3);
maxPoisons = r.Next(1,3);
int spdr = r.Next(1, 3);
speed = 10 - (Parent.Level/spdr);
if (speed <= 0) speed = 1;
needSize = r.Next(10, 100);
startingSize = r.Next(0, 9);
startingDir = (Snake.Side)(r.Next(0, 4));
startingPos1 = new Vector2(r.Next(10,Renderer.WindowSize.X-10), r.Next(10, Renderer.WindowSize.Y - 12));
startingPos2 = new Vector2(Renderer.WindowSize.X-startingPos1.X, Renderer.WindowSize.Y-startingPos1.Y);
obstacles.Clear();
snake1 = new Snake(this, true, startingPos1, needSize, speed, startingSize, startingDir, controls1);
Snake.Side dir2;
if (startingDir == Snake.Side.Down) dir2 = Snake.Side.Up;
else if (startingDir == Snake.Side.Up) dir2 = Snake.Side.Down;
else if (startingDir == Snake.Side.Left) dir2 = Snake.Side.Right;
else dir2 = Snake.Side.Left;
if (MultiPlayer) snake2 = new Snake(this, false, startingPos2, needSize, speed, startingSize, dir2, controls2);
int sides = r.Next(0, 10);
if ((sides > 3) && (sides < 6))
{
obstacles.Add(new Rectangle(1, 2, Renderer.WindowSize.X - 2, 1));
obstacles.Add(new Rectangle(1, Renderer.WindowSize.Y - 1, Renderer.WindowSize.X - 2, 1));
obstacles.Add(new Rectangle(0, 3, 1, Renderer.WindowSize.Y - 4));
obstacles.Add(new Rectangle(Renderer.WindowSize.X - 1, 3, 1, Renderer.WindowSize.Y - 4));
}
else if ((sides >= 6))
{
obstacles.Add(new Rectangle(1, 2, (Renderer.WindowSize.X - 2)/2-10, 1));
obstacles.Add(new Rectangle((Renderer.WindowSize.X - 2) / 2+11, 2, (Renderer.WindowSize.X - 2) / 2 - 10, 1));
obstacles.Add(new Rectangle(1, Renderer.WindowSize.Y-1, (Renderer.WindowSize.X - 2) / 2 - 10, 1));
obstacles.Add(new Rectangle((Renderer.WindowSize.X - 2) / 2 + 11, Renderer.WindowSize.Y-1,(Renderer.WindowSize.X - 2) /2 - 10, 1));
obstacles.Add(new Rectangle(0, 3, 1, (Renderer.WindowSize.Y - 4)/2-5));
obstacles.Add(new Rectangle(0, (Renderer.WindowSize.Y - 4) / 2 + 8, 1, (Renderer.WindowSize.Y - 4)/2-5));
obstacles.Add(new Rectangle(Renderer.WindowSize.X-1, 3, 1, (Renderer.WindowSize.Y - 4) / 2 - 5));
obstacles.Add(new Rectangle(Renderer.WindowSize.X - 1, (Renderer.WindowSize.Y - 4) / 2 + 8, 1, (Renderer.WindowSize.Y - 4) / 2 - 5));
}
for (int i = 0; i < r.Next(0, 5); i++)
{
Rectangle rec = new Rectangle(r.Next(10, Renderer.WindowSize.X - 10), r.Next(10, Renderer.WindowSize.Y - 10), r.Next(1, 20), r.Next(1, 10));
if (!MultiPlayer)
while (snake1.CheckCollisionFull(rec))
{
rec = new Rectangle(r.Next(10, Renderer.WindowSize.X - 10), r.Next(10, Renderer.WindowSize.Y - 10), r.Next(1, 20), r.Next(1, 10));
}
else
while ((snake1.CheckCollisionFull(rec)) || (snake2.CheckCollisionFull(rec)))
{
rec = new Rectangle(r.Next(10, Renderer.WindowSize.X - 10), r.Next(10, Renderer.WindowSize.Y - 10), r.Next(1, 20), r.Next(1, 10));
}
obstacles.Add(rec);
}
}
public void LoadFile(string file)
{
Level l = FileController.Load<Level>(file);
maxPoints = l.MaxPoints;
maxLives = l.MaxLives;
maxPoisons = l.MaxPoisons;
speed = 10 - (Parent.Level / l.SpeedModifier);
if (speed <= 0) speed = 1;
needSize = l.NeededSize;
startingSize = l.StartingSize;
startingDir = l.Start_Direction;
startingPos1 = l.Player1_StartPosition;
startingPos2 = l.Player2_StartPosition;
obstacles.Clear();
snake1 = new Snake(this, true, startingPos1, needSize, speed, startingSize, startingDir, controls1);
Snake.Side dir2;
if (startingDir == Snake.Side.Down) dir2 = Snake.Side.Up;
else if (startingDir == Snake.Side.Up) dir2 = Snake.Side.Down;
else if (startingDir == Snake.Side.Left) dir2 = Snake.Side.Right;
else dir2 = Snake.Side.Left;
if (MultiPlayer) snake2 = new Snake(this, false, startingPos2, needSize, speed, startingSize, dir2, controls2);
foreach (Rectangle rec in l.Obstacles)
{
obstacles.Add(rec);
}
}
public void LoadLevel()
{
if ((Directory.Exists("Levels")) && (File.Exists("Levels\\Level" + Parent.Level + ".lvl"))) LoadFile("Levels\\Level" + Parent.Level + ".lvl");
else MakeRandom();
snake1.GotScore += GotScore;
snake1.GotLive += GotLive;
snake1.Died += Died;
snake1.Complete += Completed;
snake1.AtePoint += AtePoint;
snake1.AteLive += AteLive;
snake1.AtePoision += AtePoison;
if (MultiPlayer)
{
snake2.GotScore += GotScore;
snake2.GotLive += GotLive;
snake2.Died += Died;
snake2.Complete += Completed;
snake2.AtePoint += AtePoint;
snake2.AteLive += AteLive;
snake2.AtePoision += AtePoison;
}
for (int i = 0; i < maxPoints; i++)
{
points.Add(GeneratePoint());
}
for (int i = 0; i < maxPoisons; i++)
{
poisons.Add(GeneratePoint());
}
for (int i = 0; i < maxLives; i++)
{
lives.Add(GeneratePoint());
}
}
public void ResetScene()
{
controls1.Clear();
controls2.Clear();
controls1.Add(Snake.Side.Up, ConsoleKey.W);
controls1.Add(Snake.Side.Down, ConsoleKey.S);
controls1.Add(Snake.Side.Left, ConsoleKey.A);
controls1.Add(Snake.Side.Right, ConsoleKey.D);
controls2.Add(Snake.Side.Up, ConsoleKey.UpArrow);
controls2.Add(Snake.Side.Down, ConsoleKey.DownArrow);
controls2.Add(Snake.Side.Left, ConsoleKey.LeftArrow);
controls2.Add(Snake.Side.Right, ConsoleKey.RightArrow);
points = new List<Vector2>();
lives = new List<Vector2>();
poisons = new List<Vector2>();
LoadLevel();
}
public void ResetLevel()
{
snake1 = new Snake(this, true, startingPos1, needSize, speed, startingSize, startingDir, controls1);
snake1.GotScore += GotScore;
snake1.GotLive += GotLive;
snake1.Died += Died;
snake1.Complete += Completed;
snake1.AtePoint += AtePoint;
snake1.AteLive += AteLive;
snake1.AtePoision += AtePoison;
if (MultiPlayer)
{
Snake.Side dir2;
if (startingDir == Snake.Side.Down) dir2 = Snake.Side.Up;
else if (startingDir == Snake.Side.Up) dir2 = Snake.Side.Down;
else if (startingDir == Snake.Side.Left) dir2 = Snake.Side.Right;
else dir2 = Snake.Side.Left;
snake2 = new Snake(this, false, startingPos2, needSize, speed, startingSize, dir2, controls2);
snake2.GotScore += GotScore;
snake2.GotLive += GotLive;
snake2.Died += Died;
snake2.Complete += Completed;
snake2.AtePoint += AtePoint;
snake2.AteLive += AteLive;
snake2.AtePoision += AtePoison;
}
points.Clear();
poisons.Clear();
lives.Clear();
for (int i = 0; i < maxPoints; i++)
{
points.Add(GeneratePoint());
}
for (int i = 0; i < maxPoisons; i++)
{
poisons.Add(GeneratePoint());
}
for (int i = 0; i < maxLives; i++)
{
lives.Add(GeneratePoint());
}
}
public void Update()
{
if (Console.KeyAvailable)
{
ConsoleKeyInfo pressed = Console.ReadKey(true);
if (pressed.Key == ConsoleKey.Escape) { Parent.currentScene = Game.Scenes.Pause; }
snake1.Control(pressed);
if (MultiPlayer) snake2.Control(pressed);
}
if (!IsThereLive)
IsThereLive = r.Next(0, 1000) == 1;
if (!IsTherePoison)
IsTherePoison = r.Next(0, 100) == 1;
snake1.Update((IsThereLive) ? lives : new List<Vector2>(), points, (IsTherePoison) ? poisons : new List<Vector2>(), obstacles, snake2);
if (MultiPlayer) snake2.Update((IsThereLive) ? lives : new List<Vector2>(), points, (IsTherePoison) ? poisons : new List<Vector2>(), obstacles, snake1);
}
public void Draw()
{
foreach (Vector2 point in points)
{
Renderer.DrawPoint(point, ConsoleColor.Blue);
}
if (IsTherePoison)
foreach (Vector2 poison in poisons)
{
Renderer.DrawPoint(poison, ConsoleColor.Red);
}
if (IsThereLive)
foreach (Vector2 live in lives)
{
Renderer.DrawPoint(live, ConsoleColor.Green);
}
foreach(Rectangle r in obstacles)
{
Renderer.DrawRectangle(r, ConsoleColor.DarkGray);
if ((r.Width > 3) && (r.Height > 3))
{
Renderer.DrawRectangle(new Rectangle(r.X+1, r.Y+1,r.Width-2, r.Height-2), ConsoleColor.Gray);
}
}
snake1.Draw();
if (MultiPlayer) snake2.Draw();
DrawInfo();
}
private void DrawInfo()
{
Renderer.DrawRectangle(new Rectangle(0, 0, Renderer.WindowSize.X, 2), ConsoleColor.Blue);
string livString = "Lives : " + Parent.Lives;
string levString = "Level : " + Parent.Level;
string scoString = "Score : " + Parent.Score;
Renderer.DrawString(livString, new Vector2(1, 0), ConsoleColor.White);
Renderer.DrawString(levString, new Vector2((Renderer.WindowSize.X - levString.Length) / 2, 0), ConsoleColor.White);
Renderer.DrawString(scoString, new Vector2(Renderer.WindowSize.X - 1 - scoString.Length, 0), ConsoleColor.White);
if (!MultiPlayer)
{
string sizString = "Current Size : " + snake1.Size;
string neeString = "Needed Size : " + snake1.NeedToComplete;
Renderer.DrawString(sizString, new Vector2(1, 1), ConsoleColor.White);
Renderer.DrawString(neeString, new Vector2(Renderer.WindowSize.X - 1 - neeString.Length, 1), ConsoleColor.White);
}
else
{
string siz1String = "Player 1 Size : " + snake1.Size;
string siz2String = "Player 2 Size : " + snake2.Size;
string neeString = "Needed Size : " + (snake1.NeedToComplete*2);
Renderer.DrawString(siz1String, new Vector2(1, 1), ConsoleColor.White);
Renderer.DrawString(siz2String, new Vector2(Renderer.WindowSize.X - 1 - siz2String.Length, 1), ConsoleColor.White);
Renderer.DrawString(neeString, new Vector2((Renderer.WindowSize.X - neeString.Length)/2, 1), ConsoleColor.White);
}
}
public void GotScore(object sender, int e)
{
Parent.Score += e;
}
public void GotLive(object sender, EventArgs e)
{
Parent.Lives++;
}
public void Died(object sender, Snake.DeathCause e)
{
Parent.Lives--;
if (Parent.Lives < 0)
{
Parent.HighscoreScn.MP = MultiPlayer;
Parent.HighscoreScn.LoadScores();
Parent.currentScene = Game.Scenes.HighScore;
}
else
{
Console.Beep(1000, 500);
Console.Beep(500, 500);
Console.Beep(250, 500);
if ((!MultiPlayer) || (e == Snake.DeathCause.CollisionOppenent))
{
ResetLevel();
}
else
{
((Snake)sender).Size = startingSize;
}
}
}
public void Completed(object sender, EventArgs e)
{
Console.Beep(250, 500);
Console.Beep(500, 1000);
Console.Beep(1000, 500);
Console.Beep(1000, 500);
Parent.Level++;
SaveState state = new SaveState();
state.Level = Parent.Level;
state.Lives = Parent.Lives;
state.Score = Parent.Score;
FileController.Save<SaveState>(state, "Saves\\Save_" + ((!MultiPlayer)?"SP_":"MP_") + SaveFile + ".xml");
ResetScene();
}
public void AtePoint(object sender, Vector2 e)
{
foreach (Vector2 point in points)
{
if (point == e)
{
Vector2 p = GeneratePoint();
point.X = p.X;
point.Y = p.Y;
}
}
Console.Beep(1000,10);
}
public void AteLive(object sender, Vector2 e)
{
foreach (Vector2 point in lives)
{
if (point == e)
{
Vector2 p = GeneratePoint();
point.X = p.X;
point.Y = p.Y;
}
}
Console.Beep(500, 50);
Console.Beep(1000, 50);
Console.Beep(1500, 50);
IsThereLive = false;
}
public void AtePoison(object sender, Vector2 e)
{
foreach (Vector2 point in poisons)
{
if (point == e)
{
Vector2 p = GeneratePoint();
point.X = p.X;
point.Y = p.Y;
}
Console.Beep(1000, 50);
Console.Beep(500, 50);
Console.Beep(250, 50);
IsTherePoison = false;
}
}
}
}

Návrat do menu

Pridajte Komentár

Vaša e-mailová adresa nebude zverejnená.

Scroll to Top