Konzolový Had 6 – Tabuľka najvyššieho skóre

V dnešnom diely sa pozrieme na scénu zobrazujúcu tabuľku najvyššieho skóre a jej pridružené triedy.

Úvod

Keďže chceme, aby si hráči mohli svoj úspech, alebo neúspech zaznamenať, vytvoríme pre nich tabuľku najvyššieho skóre. Tá sa bude podobne ako hra zobrazovať na samostatnej scéne. Okrem toho vytvoríme triedu, ktorá bude všetky hodnoty uchovávať.

Triedy Highscores a Score

Keďže sa jedná o veľmi malé pomocné triedy, tak ich môžeme umiestniť do jedného súboru (napríklad Highscores.cs). Tieto triedy budú uchovávať posledné bodové stavy hráčov.

Score

Najprv vytvoríme triedu Score. Tá bude serializovatelná a bude obsahovať dve premenné – string Name (z predvolenou hodnotou prázdneho stringu) a int Points z predvolenou hodnotou 0.

[Serializable]
public class Score
{
    public string Name = "";
    public int Points = 0;
}

Highscores

Trieda Highscores bude obsahovať len jednu premennú, a to pole veľkosti desať typu pred chvíľou vytvorenej triedy Score. Pole bude mať preddefinovaných 10 prázdnych objektov Score.

[Serializable]
public class Highscores
{
    public Score[] scores = new Score[10] { new Score(), new Score(), new Score(), new Score(), new Score(), new Score(), new Score(), new Score(), new Score(), new Score()};
}

Trieda HighscoresScene – Premenné

Teraz, keď sa dostávame k samotnej scéne, si musíme určiť aké premenné a objekty bude obsahovať.

Najprv si určíme technickejšie premenné, jedná sa o rodiča typu Game a dve boolovské hodnoty určujúce, či už zaznela krátka melódia a či prebehlo prvé vykreslenie.

private Game Parent;
private bool FirstDraw = false;
private bool played = false;

Ďalej si určíme informácie, ktoré budú znázorňovať aktuálny stav, čiže integer označujúci vybranú položku, string obsahujúci meno hráča a tabuľku najvyšších score – typ triedy Highscores.

private int selectedItem = -1;
private string name = "";
private Highscores highscores;

Na záver už len pribudne malá informácia o tom, či sa jednalo, alebo nejednalo o hru viacerých hráčov.

public bool MP;

Pomocná metóda LoadScores a Konštruktor triedy

Naša trieda HighscoresScene bude mať len jednu pomocnú metódu, a tá bude mať za úlohu prečítať tabuľku vysokého skóre zo súboru. Konštruktor je tiež primitívny.

LoadScores

Samotné načítanie tabuľky prebehne pomocou našej triedy FileController. Pri výbere cesty k súboru sa podľa toho, či sa jedná o hru jedného, či dvoch hráčov rozhodneme pre Highscores_SP.xml alebo Highscores_MP.xml.

highscores = FileController.Load<Highscores>("Saves\\Highscores_" + ((MP) ? "MP" : "SP") + ".xml");

Po tomto prejdeme cyklom for všetky body a ak je hráčové skóre väčšie ako to, ktoré je v tabuľke, tak si zaznačíme jeho polohu do premennej selectedItem.

for (int i = 0; i < 10; i++)
    if (Parent.Score > highscores.scores[i].Points)
    {
        selectedItem = i;
        break;
    }

Aby sme nakoniec po tomto vyradili najhoršieho hráča (len v prípade ak sa hráč dostal do tabuľky), posunieme všetkých za ním o jedno pole dozadu.

if (selectedItem != -1)
    for (int i = 8; i >= selectedItem; i--)
    {
        highscores.scores[i + 1] = new Score() { Name = highscores.scores[i].Name, Points = highscores.scores[i].Points };
    }

Zobraziť celú metódu

public void LoadScores()
{
    highscores = FileController.Load<Highscores>("Saves\\Highscores_" + ((MP) ? "MP" : "SP") + ".xml");
    for (int i = 0; i < 10; i++)
        if (Parent.Score > highscores.scores[i].Points)
        {
            selectedItem = i;
            break;
        }
    if (selectedItem != -1)
        for (int i = 8; i >= selectedItem; i--)
        {
            highscores.scores[i + 1] = new Score() { Name = highscores.scores[i].Name, Points = highscores.scores[i].Points };
        }
}

Konštruktor

Konštruktor tejto triedy má za úlohu len priradiť argument typu Game k premennej Parent.

public HighscoresScene(Game parent)
{
    Parent = parent;
}

Metóda Update

Teraz sa dostávame do srdca triedy HighscoresScene. Metóda Update bude ovládať dve základné veci.

  1. Zadanie mena hráča (a jeho zápis do súboru) ak sa dostal do tabuľky najvyššieho skóre.
  2. Opustenie obrazovky a návrat do hlavného menu.

Celá metóda Update bude prebiehať v podmienke, ak je premenná FirstDraw nastavená na true.

Tu sa bude skrývať ďalšia podmienka, a to ak je premenná selectedItem väčšia ako -1. V tom prípade zahrá krátku melódiu (ak ju už nezahral).

if (!played)
{
    played = true;
    Console.Beep(200, 500);
    Console.Beep(300, 500);
    Console.Beep(400, 500);
    Console.Beep(500, 500);
    Console.Beep(600, 1500);
}

Ďalej zobrazí kurzor, nastaví farbu pozadia/poprieda, pozíciu kurzora a dovolí hráčovi napísať svoje meno, potom opäť skryje kurzor.

Console.CursorVisible = true;
Console.BackgroundColor = ConsoleColor.DarkYellow;
Console.ForegroundColor = ConsoleColor.Red;
Console.CursorLeft = (Renderer.WindowSize.X - 42) / 2 + 2;
Console.CursorTop = (Renderer.WindowSize.Y - 23) / 2 + (selectedItem + 1) * 2;
name = Console.ReadLine();
Console.CursorVisible = false;

Na záver uložíme tabuľku hráčov a nastavíme selectedItem na -1.

highscores.scores[selectedItem].Name = name;
highscores.scores[selectedItem].Points = Parent.Score;
FileController.Save<Highscores>(highscores, "Saves\\Highscores_" + ((MP) ? "MP" : "SP") + ".xml");
selectedItem = -1;

V prípade že selectedItem NIE JE VÄČŠÍ AKO -1 opäť zahrá melódiu (ak už raz nebola zahraná)

if (!played)
{
    played = true;
    Console.Beep(200, 500);
    Console.Beep(400, 500);
    Console.Beep(600, 1500);
}

Po tom len čaká na stlačenie tlačidla Enter. Po jeho stlačení sa vráti do hlavného menu nastavením aktuálnej scény v rodičovi na MainMenu. Zároveň obnoví základné údaje, ako počet životov, skóre a aktuálny level na pôvodné hodnoty.

ConsoleKey key = Console.ReadKey(true).Key;
if (key == ConsoleKey.Enter)
{
    Parent.currentScene = Game.Scenes.MainMenu;
    Parent.Score = 0;
    Parent.Lives = 5;
    Parent.Level = 1;
}

Zobraziť celú metódu

public void Update()
{
    if (FirstDraw)
    {
        if (selectedItem != -1)
        {
            if (!played)
            {
                played = true;
                Console.Beep(200, 500);
                Console.Beep(300, 500);
                Console.Beep(400, 500);
                Console.Beep(500, 500);
                Console.Beep(600, 1500);
            }
            Console.CursorVisible = true;
            Console.BackgroundColor = ConsoleColor.DarkYellow;
            Console.ForegroundColor = ConsoleColor.Red;
            Console.CursorLeft = (Renderer.WindowSize.X - 42) / 2 + 2;
            Console.CursorTop = (Renderer.WindowSize.Y - 23) / 2 + (selectedItem + 1) * 2;
            name = Console.ReadLine();
            Console.CursorVisible = false;
            highscores.scores[selectedItem].Name = name;
            highscores.scores[selectedItem].Points = Parent.Score;
            FileController.Save<Highscores>(highscores, "Saves\\Highscores_" + ((MP) ? "MP" : "SP") + ".xml");
            selectedItem = -1;
        }
        else
        {
            if (!played)
            {
                played = true;
                Console.Beep(200, 500);
                Console.Beep(400, 500);
                Console.Beep(600, 1500);
            }
            ConsoleKey key = Console.ReadKey(true).Key;
            if (key == ConsoleKey.Enter)
            {
                Parent.currentScene = Game.Scenes.MainMenu;
                Parent.Score = 0;
                Parent.Lives = 5;
                Parent.Level = 1;
            }
        }
    }
}

Metóda Draw

Metóda Draw má za úlohu vykresliť tabuľku skóre a je teda celkom jednoduchá.

Na začiatku zabezpečíme, aby sa premenná FirstDraw zmenila na true. To má za úlohu zabezpečiť, aby pred písaním mena bola tabuľka vykreslená.

if (!FirstDraw) FirstDraw = true;

Po tomto vykreslíme zelený obdĺžnik z tmavozeleným okrajom a do stredu horného okraja napíšeme „HIGH SCORES TABLE“.

Renderer.DrawRectangle(new Rectangle((Renderer.WindowSize.X - 42) / 2, (Renderer.WindowSize.Y - 23)/2, 42, 23), ConsoleColor.DarkGreen);
Renderer.DrawRectangle(new Rectangle((Renderer.WindowSize.X - 40) / 2, (Renderer.WindowSize.Y - 21) / 2, 40, 21), ConsoleColor.Green);
Renderer.DrawString("HIGH SCORES TABLE", new Vector2((Renderer.WindowSize.X - "HIGH SCORES TABLE".Length) / 2, (Renderer.WindowSize.Y - 21) / 2 - 1), ConsoleColor.White);

Ďalej v cykle o 10 krokoch vypíšeme všetky body tabuľky jeden pod druhý. Medzi každým vynecháme jeden riadok. Ak vypisujeme aktuálneho hráča, nastavíme tmavožlté pozadie, inak ho nastavíme modré.

for (int i = 0; i < 10; i++)
{
    if (selectedItem == i)
    {
        Renderer.DrawRectangle(new Rectangle((Renderer.WindowSize.X - 42) / 2 + 2, (Renderer.WindowSize.Y - 23) / 2 + (i + 1) * 2, 38, 1), ConsoleColor.DarkYellow);
        Renderer.DrawString(name.PadRight(38 - Parent.Score.ToString().Length, ' ') + Parent.Score.ToString(), new Vector2((Renderer.WindowSize.X - 42) / 2 + 2, (Renderer.WindowSize.Y - 23) / 2 + (i + 1) * 2), ConsoleColor.White);
    }
    else
    {
        Renderer.DrawRectangle(new Rectangle((Renderer.WindowSize.X - 42) / 2 + 2, (Renderer.WindowSize.Y - 23) / 2 + (i + 1) * 2, 38, 1), ConsoleColor.Blue);
        Renderer.DrawString(highscores.scores[i].Name.PadRight(38 - highscores.scores[i].Points.ToString().Length, ' ') + highscores.scores[i].Points.ToString(), new Vector2((Renderer.WindowSize.X - 42) / 2 + 2, (Renderer.WindowSize.Y - 23) / 2 + (i + 1) * 2), ConsoleColor.White);
    }
}

Zobraziť celú metódu

public void Draw()
{
    if (!FirstDraw) FirstDraw = true;
    Renderer.DrawRectangle(new Rectangle((Renderer.WindowSize.X - 42) / 2, (Renderer.WindowSize.Y - 23)/2, 42, 23), ConsoleColor.DarkGreen);
    Renderer.DrawRectangle(new Rectangle((Renderer.WindowSize.X - 40) / 2, (Renderer.WindowSize.Y - 21) / 2, 40, 21), ConsoleColor.Green);
    Renderer.DrawString("HIGH SCORES TABLE", new Vector2((Renderer.WindowSize.X - "HIGH SCORES TABLE".Length) / 2, (Renderer.WindowSize.Y - 21) / 2 - 1), ConsoleColor.White);
    for (int i = 0; i < 10; i++)
    {
        if (selectedItem == i)
        {
            Renderer.DrawRectangle(new Rectangle((Renderer.WindowSize.X - 42) / 2 + 2, (Renderer.WindowSize.Y - 23) / 2 + (i + 1) * 2, 38, 1), ConsoleColor.DarkYellow);
            Renderer.DrawString(name.PadRight(38 - Parent.Score.ToString().Length, ' ') + Parent.Score.ToString(), new Vector2((Renderer.WindowSize.X - 42) / 2 + 2, (Renderer.WindowSize.Y - 23) / 2 + (i + 1) * 2), ConsoleColor.White);
        }
        else
        {
            Renderer.DrawRectangle(new Rectangle((Renderer.WindowSize.X - 42) / 2 + 2, (Renderer.WindowSize.Y - 23) / 2 + (i + 1) * 2, 38, 1), ConsoleColor.Blue);
            Renderer.DrawString(highscores.scores[i].Name.PadRight(38 - highscores.scores[i].Points.ToString().Length, ' ') + highscores.scores[i].Points.ToString(), new Vector2((Renderer.WindowSize.X - 42) / 2 + 2, (Renderer.WindowSize.Y - 23) / 2 + (i + 1) * 2), ConsoleColor.White);
        }
    }
}

A takto bude vaša tabuľka vyzerať pokiaľ by ste si ju nechali zobraziť.

Highscores

Na záver sa s vami lúčim a uvidíme sa zas o týždeň pri ďalšom diely z tutoriálov na konzolovú hru had. Pravdepodobne si konečne preberieme hlavné menu. Zároveň vám sem vložím celý kód triedy HighscoresScene.

Zobraziť celú triedu

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Snake
{
public class HighscoresScene
{
private Game Parent;
private bool FirstDraw = false;
private bool played = false;
private int selectedItem = -1;
private string name = "";
private Highscores highscores;
public bool MP;
public HighscoresScene(Game parent)
{
Parent = parent;
}
public void LoadScores()
{
highscores = FileController.Load<Highscores>("Saves\\Highscores_" + ((MP) ? "MP" : "SP") + ".xml");
for (int i = 0; i < 10; i++)
if (Parent.Score > highscores.scores[i].Points)
{
selectedItem = i;
break;
}
if (selectedItem != -1)
for (int i = 8; i >= selectedItem; i--)
{
highscores.scores[i + 1] = new Score() { Name = highscores.scores[i].Name, Points = highscores.scores[i].Points };
}
}
public void Update()
{
if (FirstDraw)
{
if (selectedItem != -1)
{
if (!played)
{
played = true;
Console.Beep(200, 500);
Console.Beep(300, 500);
Console.Beep(400, 500);
Console.Beep(500, 500);
Console.Beep(600, 1500);
}
Console.CursorVisible = true;
Console.BackgroundColor = ConsoleColor.DarkYellow;
Console.ForegroundColor = ConsoleColor.Red;
Console.CursorLeft = (Renderer.WindowSize.X - 42) / 2 + 2;
Console.CursorTop = (Renderer.WindowSize.Y - 23) / 2 + (selectedItem + 1) * 2;
name = Console.ReadLine();
Console.CursorVisible = false;
highscores.scores[selectedItem].Name = name;
highscores.scores[selectedItem].Points = Parent.Score;
FileController.Save<Highscores>(highscores, "Saves\\Highscores_" + ((MP) ? "MP" : "SP") + ".xml");
selectedItem = -1;
}
else
{
if (!played)
{
played = true;
Console.Beep(200, 500);
Console.Beep(400, 500);
Console.Beep(600, 1500);
}
ConsoleKey key = Console.ReadKey(true).Key;
if (key == ConsoleKey.Enter)
{
Parent.currentScene = Game.Scenes.MainMenu;
Parent.Score = 0;
Parent.Lives = 5;
Parent.Level = 1;
}
}
}
}
public void Draw()
{
if (!FirstDraw) FirstDraw = true;
Renderer.DrawRectangle(new Rectangle((Renderer.WindowSize.X - 42) / 2, (Renderer.WindowSize.Y - 23)/2, 42, 23), ConsoleColor.DarkGreen);
Renderer.DrawRectangle(new Rectangle((Renderer.WindowSize.X - 40) / 2, (Renderer.WindowSize.Y - 21) / 2, 40, 21), ConsoleColor.Green);
Renderer.DrawString("HIGH SCORES TABLE", new Vector2((Renderer.WindowSize.X - "HIGH SCORES TABLE".Length) / 2, (Renderer.WindowSize.Y - 21) / 2 - 1), ConsoleColor.White);
for (int i = 0; i < 10; i++)
{
if (selectedItem == i)
{
Renderer.DrawRectangle(new Rectangle((Renderer.WindowSize.X - 42) / 2 + 2, (Renderer.WindowSize.Y - 23) / 2 + (i + 1) * 2, 38, 1), ConsoleColor.DarkYellow);
Renderer.DrawString(name.PadRight(38 - Parent.Score.ToString().Length, ' ') + Parent.Score.ToString(), new Vector2((Renderer.WindowSize.X - 42) / 2 + 2, (Renderer.WindowSize.Y - 23) / 2 + (i + 1) * 2), ConsoleColor.White);
}
else
{
Renderer.DrawRectangle(new Rectangle((Renderer.WindowSize.X - 42) / 2 + 2, (Renderer.WindowSize.Y - 23) / 2 + (i + 1) * 2, 38, 1), ConsoleColor.Blue);
Renderer.DrawString(highscores.scores[i].Name.PadRight(38 - highscores.scores[i].Points.ToString().Length, ' ') + highscores.scores[i].Points.ToString(), new Vector2((Renderer.WindowSize.X - 42) / 2 + 2, (Renderer.WindowSize.Y - 23) / 2 + (i + 1) * 2), ConsoleColor.White);
}
}
}
}
}

Pridajte Komentár

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

Scroll to Top