06 stycznia 2025

Walka z plecakiem Sladuma

Okazało się, że pisanie kodu generującego gui jest dla mnie sporym wyzwaniem. Im dalej w las tym trudniej mi ogarnąć sposób i oczekiwane działanie elementów widocznych na ekranie. Często samo rozwiązanie problemu okazuje się banalnie proste jednakże sposób myślenia o gui od strony kodu jest dla mnie tak odmienny od tego co robię na codzień, że mam problemy ze stworzeniem czegoś działającego bez siedzenia jednym okiem na tutorialu, a drugim na stackoverflow. Niby miałem jakieś doświadczenia z pisaniem w JavaFX (zresztą nawet na blogu o tym pisałem) ale nigdy nie musiałem się jakoś mocno zagłębić w temat. 

Postęp jednak jest. 

Przerobiłem tutorial na Zenwie (ponownie) ale okazał się on niewystarczający, stąd poszukałem na youtube i  w końcu (pod dwóch niezbyt dobrych, albo ich po prostu nie zrozumiałem) trafiłem tu: How to Make an Inventory System in Godot . I to był strzał w dziesiątkę. W końcu pchnąłem pracę sensownie do przodu. Chylę czoła przed twórcą bo powoli zacząłem rozumieć co ja właściwie koduję. 

Plecak wersja 2.0


Po przerobieniu dwóch filmików wszystko działa mi jak w trzeba. Przedmioty można przerzucać między slotami (oj miałem tu ogromny problem z przekazaniem z jakiego slotu do jakiego trzeba wrzucić przedmioty) grupować i podmieniać w slotach (tu też miałem problem bo w godot kod wygląda inaczej niż w C#).

Czeka mnie jeszcze 6 kolejnych filmików w tej serii, ale już teraz widzę światełko w tunelu, ponieważ jak plecak zacznie mi działać (przynajmniej jako-tako) będę mógł skupić się na implementacji rozgrywki i samych map. 

Grupowanie przedmiotów w slotach

Przeniesienie przedmiotu między slotami


Przedmioty po sortowaniu


    

03 stycznia 2025

Generator postaci do... Kryształów Czasu

 Nie żeby mi się nudziło, ale generator postaci oparty o zasady Kryształów Czasu był jednym z założeń zabawy w pisanie mini gry rpg i wykorzystania przygody Sladuma jako bazy do nauczenia się Godota i C# przy okazji. 

Stąd po bardzo krótkim czasie (zaledwie dwa-trzy dłuższe posiedzenia w ciągu ostatnich dni) udało się osiągnąć wstępny projekt kolejnej mechaniki gry (i kolejnej na tę chwilę nie dokończonej lecz nie mogłem się powstrzymać) czyli wspomnianego generatora postaci.
I tak patrząc na to jak szybko udało mi się stworzyć wyjściową wersję w C# generującą cechy w porównaniu z tym jak męczyłem się przy JavieScript, aby osiągnąć podobny efekt... jestem miło zaskoczony. Niby kod, a w sumie struktury obiektów POJO mógłbym przenieść niemal 1:1 jednakże zauważyłem w starym kodzie mnóstwo elementów, które były po prostu źle przemyślane. 

Nie ma się co oszukiwać - doświadczenie w programowaniu procentuje.  

Aktualnie kod w C# jest wygodniejszy w użyciu oraz czytelniejszy. Skomplikowane elementy dotyczące struktur potrzebne do wygenerowania cech stały się bardziej generyczne. Mechanizm losuje cechy główne i odporności w identyczny sposób w oparciu o takie same obiekty przenoszone w kodzie. W poprzedniej wersji nie udało mi się osiągnąć takiej spójności danych. Zawsze też jest opcja wstępnego refaktoru napisanych klas ponieważ już teraz widzę kilka elementów, które z powodzeniem mogę skrócić.

Oczywiście nowy generator nie ma pełnej obsługi wszystkich kroków wymaganych do stworzenia pełnoprawnej postaci. Brakuje w nim losowania wagi, pochodzenia, uwzględnienia wszystkich profesji i ras czy zalet i wad postaci, zawodów...  ale już teraz widzę, że dodawanie tych elementów będzie o wiele prostsze niż w JavieScript. Dobrze też, że pliki które tworzyły bazę danych dla starego generatora, w miarę łatwo będę mógł przekształcić w pliki jsona i wczytać do kodu zamiast mozolnie wszystko przepisywać na nowo. 

Ale koniec lania wody, pora na prezentację. 

Można wylosować  człowieka (mężczyznę) w profesji wojownika na poziomie 0. Elementy wchodzące w definicji rasy oraz profesji są zgodne z tym co jest w KC-tach.

Mam trzy zakładki grupujące dane.
Ogólny wygląd jest paskudny, ale nie to było celem.

Wylosowane statystyki postaci wraz z wyświetlonymi
składowymi (po prawej stronie od cech) z których zostały obliczone


I to samo, ale dla odporności.

Stary generator postaci (dostępny tutaj Generator postaci Kryształy Czasu ) pod względem zawartości bije na głowę to co teraz napisałem jednakże siedziałem nad nim z miesiąc(jak nie dwa) a tu to dopiero początek. I w innym języku :) 

I trochę o kodzie

Jak wiecie pisze w dla Godot w C#.  Struktura klas nie jest nadmiernie skomplikowana.
Jest generator cech (zlany w jedną gównianą klasę z kontrolerem ekranu wyświetlającym cechy i to musze obowiązkowo poprawić) i generator dla odporności oraz klasy wspierające. 

I o ile część losująca nie jest zbyt interesująca najfajniejsze klasy to StatDefinition odpowiadająca za definicję cech postaci - tak głównych jak i odporności oraz klasa odpowiedzialna za kostki. Poniżej jak wygląda w kodzie (zwykłe POJO ale o szerokim zastosowaniu)

public class StatDefinition
{
    /* nazwa cechy*/
    public StatName Name;
    /* długa nazwa parametru*/
    public string LongName;
    /* wartośc bazowa */
    public int BaseValue;
    /* czy powinna być losowana w generatorze */
    public bool ShouldBeRolled = true;
    /* czy to zdolnosć profesji lub rasy i możliwa przerzucana dla lepszego wyniku */
    public bool ProffStat = false;
    /* definicja kostki jaka trzeba rzucać */
    public RollDefinition RollCode;
}

I sama definicja przykładowo Żywotność dla człowieka , której w KC nie przerzucamy przy generowaniu 
    internal StatDefinition HitPoints { get; } =
        new()
        {
            Name = StatDefinition.StatName.HP,
            LongName = "Hit points",
            BaseValue = 100,
            ShouldBeRolled = false,
        };

Tutaj inaczej dla Siły, którą nie dość że rzucamy z użyciem k100 to jest także zdolnością profesyjną i mamy możliwość wybrania większego z dwóch rzutów
    internal StatDefinition Strength { get; } =
        new()
        {
            Name = StatDefinition.StatName.SF,
            LongName = "Strength",
            BaseValue = 50,
            ProffStat = true,
            RollCode = Generator.RollCode.D100,
        };

A tutaj oparta o ten sam szablon odporność na iluzję
internal StatDefinition Illusion { get; } =
        new()
        {
            Name = StatDefinition.StatName.ILLUSION,
            LongName = "Illusion",
            BaseValue = 10,
            RollCode = Generator.RollCode.D10Premium,
        };

Powyższe pozwala szybko definiować statystyki i wrzucać do wspólnego kodu genrującego. Poprzedni kod w JavaScript nie dawał takich możliwości.

I druga klasa która wyszła dosyć zgrabnie - definiująca kostkę 

 public class RollDefinition
    {
        /* nazwa kostki */
        public string Name;
        /* min wartość dla kości */
        public int minValue;
        /* max wartość dla kości */
        public int maxValue;
        /* chyba do wyrzucenia */
        public int toAdd;
        /* czy kość premiowa */
        public bool premium;
        /* czy to pojedyncza kosc */
        public bool onedice;
        private Random rollStat = new Random();
        public int Roll()
        {
            var rolledValue = 0;
            if (minValue > -1)
            {
                if (premium)
                {
                    rolledValue = RollPremium();
                }
                else
                {
                    rolledValue = rollStat.Next(minValue, maxValue);
                }
            }
            return rolledValue;
        }

        private int RollPremium()
        {
            var rolledValue = rollStat.Next(minValue, maxValue);
            if (rolledValue == maxValue - 1)
            {
                rolledValue += RollPremium();
            }
            return rolledValue;
        }
    }


oraz przykładowa implementacja - tutaj k10 premiowe
 internal RollDefinition PremiumD10 { get; } =
            new()
            {
                Name = "PremiumD10",
                onedice = true,
                minValue = 1,
                maxValue = 11,
                premium = true,
            };

 A jakie zmiany jeszcze wejdą do kodu?

Poza wydaje się oczywistymi elementami czyli refaktorem nie używanych rzeczy (np. dwa pola w klasie RollDefinition  nigdzie nie zostały użyte czy wspomniane zlanie w jedno kontrolera ekranu z generatorem cech ) to obowiązkowe będzie wczytywanie charakterystyk dla cech czy definicji profesji z plików json. Aktualnie jest to zaszyte w kodzie (co widać po sposobie definiowania cech postaci podanym powyżej) i nie jest to nie jest optymalna metoda pracy. 
Docelowo oczywiście wrzucenie kodu do głównego projektu małej przygody Sladuma i uwzględnienie w mechanice walki. 

To na tyle.
Miłego!














01 stycznia 2025

Inventory, podejście pierwsze

 Rozpocząłem prace nad zrobieniem inventory. Wstępna wersja wygląda ...yyy... źle, ale przynajmniej wiem gdzie mniej-więcej trafią poszczególne elementy oraz jak nimi zarządzać podczas tworzenia. Pooglądałem youtubów o tworzeniu gui w Godot i nie powiem - przydały się żeby zobaczyć jak w miarę sensownie poukładać elementy na ekranie. Jeśli wystarczy mi cierpliwości to celuję wykonanie czegoś na podobieństwo jakiegoś Diablo, ale co wyjdzie to czas pokaże.

Na tę chwilę nie ma w podglądzie postaci i inventory żadnej funkcjonalności (poza tym że się pokazuje i ukrywa) tylko placeholdery na to co gdzie ma wylądować.

Pięknie nie jest, ale od czegoś trzeba zacząć.