LifeLike – Tworzenie Postaci i Okno Szczegółów

Już słyszę ten chór ludzi, którzy wołają “Buuuu! Gdzie ta cholerna walka i te cholerne tury!”.
I wiecie co? Macie rację … ale pomęczę was dłużej. W dzisiejszym odcinku naszej telenoweli pod tytułem “LifeLike – żmudny proces tworzenia prostej gry”, kontynuuje temat UI.

Dług technologiczny

Na swoim blogu i prezentacjach Arek (http://www.benedykt.net/) wielokrotnie wspominał na temat długu technologicznego i zasadach Solid. Ten pierwszy jest kluczowy i rozwija trochę temat długiego tworzenia projektu i każdego modułu. Jak wiadomo, gdy pójdziemy na skróty w tworzeniu i wykonamy dużo rzeczy na odpieprz, zemści się to na nas w procesie refaktoryzacji czy optymalizacji lub w późniejszym rozwoju. Czyli wszelako źle zaprojektowany projekt, kod będzie szybkim rozwiązaniem, ale za przeproszeniem ch.. rozwiązaniem. Wiem, że nie jest to idealnie SOLIDowy projekt, gdyż nie ma depedency injector. Pewnie wiele modułów i rozwiązań można by było lepiej oprogramować , a sposób otwarcia paneli też mógłby być lepszy, ale staram się wciąż rozwijać w technologii tworzenia gier.

Tworzenie Postaci – Ciąg dalszy

Wiecie, czego najbardziej brakuje mi w tworzeniu UI do Unity? MVVM (Model View ViewModel), gdzie w warstwie ViewModel mamy tylko Properties i logikę biznesową. Naszym modelem byłby np. CharacterStatisticDataModel, a w warstwie View bindowalibyśmy elementy z Widoku. Wiecie ile zaoszczędziło by to kodu i pracy w implementacji okien, które mają dość dużo pól? … Sporo. Marudzę na to, ponieważ w oknie tworzenia postaci dodałem nowe pola i kontrolki – do ustawiania statystyk. Na tę chwilę wszystkie nasze statystyki zaczynają się od 1. Limit punktów dla postaci wynosi 10. Poniżej 0 nie stworzymy postaci. Wyżej niż 10 .. no way!
Jak zauważyliście w poprzedniej części, dla kontrolek tworzy się listenery z delegatami zamiast akcji z delegatami. Dla Sliderów, których używamy do rozdysponowania punktów dla każdej wartości używamy onValueChanged.

StrengthSlider.onValueChanged.AddListener(StrengthChanged);

Brakuje trochę wpf parametru, do jakiej kontrolki się odwołujemy. Uprościłoby to trochę kod.Tworzenie Postaci

Następnym kluczowym dla projektu elementem jest okno postaci. W obecnej wersji tylko ze statystykami i imieniem. W przyszłości -> z ekwipunkiem i dodatkowym atrybutami.
Pod klawiszem i otwieramy nasze okienko z postacią. Kiedy je otwieramy, wyłączamy obsługę klawiszy i wyłączamy UI gry.

 if (!OpenedWindow)
        {
            if (Input.GetKeyDown(LightKey)) IsDay = !IsDay;
            if (Input.GetKeyDown(FightNormalKey)) FightSystem.AttackEnemy();
            if (Input.GetKeyDown(SelectEnemyKey)) SelectEnemy();
            if (Input.GetKeyDown(ExitKey)) EndGame();
            if (Input.GetKeyDown(OpenDetailKey)) OpenDetail();
            _gameUI.enabled = true;
        }
        else
        {
            _gameUI.enabled = false;
        }

Dotyczy to również okna kreatora postaci (w końcu, kto chce manipulować światłem w trakcie wpisywania swojego imienia).
Na obecną chwilę, zamknięcie Okna ze szczegółami postaci lub kreatora polega na … zabiciu go i Zmianie *OpenedWindow* na false.
Szczerze, w tym oknie tak samo brakowało mi MVVM, ale w mniejszym stopniu, pewnie odczuję brak na późniejszym etapie – w przypadku nowych poziomów i opcji dodania skill point.Tworzenie Postaci

Podsumowanie

To tyle na dzisiaj w tematyce UI. Pod adresem: Dostępna jest również zaaktualizowana wersja gry, m.in wzbogacona o nowe okno postaci. Następny wpis już w weekend 🙂
Cheers

Filmik z gry w mov (quick time) inaczej nie zapisuje

LifeLike – Interfejs Użytkownika

Witam w następnej części dotyczącej LifeLike. Poprzednio pisałem o zaznaczaniu postaci i dodawaniu przeciwników oraz przełączaniu się między nimi. Dzisiaj, przejdę do UI!

Manager UI w LifeLike

Jak można było zobaczyć, z UI można było spotkać się w menu głównym i w mini grze The Ball, które znajdują się pod linkiem poniżej. Link
W UI Managerze zawarte są metody do kontrolowania komponentów UI, jak np. okno z logami oraz z szczegółami. UI Manager jest podpięty do GameManagera.

Ekran Logów

PIerwszym elementem dla rasowych Rogue Like i Oldschoolowych RPG jest ekran logów. Czyli pole tekstowe z logiem – ile zadaliśmy, co znaleźliśmy i ewentualnie, co, kto do nas powiedział.
Jednak ekran logów trzeba było ograniczyć do określonej liczby linijek – tzn. czyścić te pierwsze, aby cały czas nie było więcej niż wybrana liczba linijek – u mnie 10. Logi dodaje się przez metodę AddLog(treść), a edytor przyjmuje podstawowe tagi html jak „b”, „i” oraz \t i \n dla nowej linii.
Cały kod zobaczycie na GitHubie, a fragment o którym mówię, zobaczycie poniżej.

    public void AddLog(string log)
    {
        ClearFirstLine();

        _stringLog.AppendLine(log);
         GameLog.text = _stringLog.ToString();
    }

Zaznaczony Przeciwnik

W poprzedniej części nauczyliśmy się, jak zaznaczać przeciwnika i przełączać się pomiędzy nimi, dlatego też, aby to rozszerzyć, stworzyłem panel do wyświetlania danych wybranego wroga.
Obecnie wyświetlane jest jego imię, lvl oraz coś, co poruszę w następnym punkcie, do którego potrzebny jest…

private void SelectedEnemyPanel()
    {
        if (EnemyUtils.SelectedEnemy==null) return;
        if (SelectedEnemyStatistic != null)
        {
            SelectedEnemyStatistic.text = string.Format("<b>Name</b>: {0} \n<b>Class Name</b>: {1}",
                EnemyUtils.SelectedEnemy.EnemyCharacter.Name,
                EnemyUtils.SelectedEnemy.ClassName);
        }
        if (SelectedEnemyDetail != null)
        {
            SelectedEnemyDetail.text = string.Format("<b>Distance:</b>{0}",
                EnemyUtils.SelectedEnemy.Distance);
        }

    }

Dystans

Tak, dobrze wiedzieć, jak daleko jesteśmy od przeciwnika, nie tylko, aby był to nowy wodotrysk do wyświetlania, ale także jest to przydatne do systemu walki dystansowego oraz jako informacja, czy jesteśmy na tyle blisko, aby zaatakować bezpośrednio.
Tu by się przydała trochę wiedza z uczelni oraz wzór na odległość między 2 wektorami … ale Unity dostarcza nam Vector.Distance pomiędzy graczem a wrogiem.

Dystans dodałem do klasy Enemy. Pomaga to także posortować przeciwników ze względu na dystans od gracza.

 public  int Distance {
            get {
                if (GameManager.Instance.PlayerObject != null)
                    return (int) Vector2.Distance(GameManager.Instance.PlayerObject.transform.position,
                        transform.position);
                Debug.Log(GameManager.Instance.PlayerObject);
                return 0;
                //Matematyka jednak cos daje!
                //      return (int) Mathf.Sqrt(Mathf.Pow(Player.transform.position.x - SelectedEnemy.transform.position.x, 2) +
                //                  Mathf.Pow(Player.transform.position.y - SelectedEnemy.transform.position.y, 2));
            }
        }
LifeLIke
1 wersja UI

Podsumowanie

To tyle na temat UI. Temat będzie jeszcze poruszony przy okienku tworzenia postaci oraz dodawania szczegółów dotyczących gracza.
Kod jak zwykle można znaleźć na GitHub https://github.com/aluspl/RogueLikeDSP.
Chciałem dodać player, ale Unity upiera się, że klasy Enemy nie ma … mimo że jest .

Pozdrawiam!