Ten wpis będzie poświęcony
zapisywaniu informacji o żetonach w skrypcie, co dokonamy za pomocą
zmiennych.
Zmienne
Schemat deklaracji zmiennych jest
prosty: najpierw piszemy typ zmiennej, a potem nazwę zmiennej. Typ
zmiennej określa jaki to będzie rodzaj danych, oraz służy do
deklaracji tej zmiennej, zaś nazwa zmiennej będzie pozwalała nam
się do niej odwoływać. Przykładowa deklaracja zmiennej:
int
x;
Int oznacza tutaj zmienną całkowitą, zaś x jest jej nazwą i odtąd za każdym razem gdy napiszemy w programie jej nazwę, program wstawi w jej miejsce wartość zmiennej. Jeśli chcemy, możemy przypisać do zmiennej jakąś wartość już w chwili deklaracji:
int
x = 5;
W takiej sytuacji zmienna znajdująca się po lewej zostanie znaku równości zastąpiona wartością znajdującą się po prawej stronie znaku równości. Jeśli jakaś zmienna została przez nas zadeklarowana, to nie możemy jej ponownie zadeklarować, ale możemy modyfikować ją i odwoływać się do niej dowolna liczbę razy.
Zmienne automatyczne
Zmienne automatyczne są automatycznie
zwalniane, gdy wyjdzie się poza blok w którym zostały
zadeklarowane. W prosty sposób opisując: jeśli jakaś zmienna
została zadeklarowana w nawiasie klamrowym {} lub jest jego
argumentem, to zostaje zwolniona gdy wyjdzie się poza ten nawias.
Przykład:
Dodatkowo zmienne deklarowane
bezpośrednio w klasie trwają tak długo, jak długo trwa cały
skrypt.
Tablice zmiennych
Tablice zmiennych mogą mieć dowolną
liczbę wymiarów i umożliwiają zapis całej serii zmiennych. Jeśli
chcemy utworzyć 10 różnych zmiennych o nazwie x, to deklarujemy
zmienne w ten sposób:
int
[] x = new
int
[10];
Po typie zmiennej pojawia się nawias kwadratowy który oznacza deklarację tablicy, a po prawej stronie znajduje się informacja o wymiarach tablicy. Tablicę wielowymiarową deklaruje się dodając przecinki w nawiasach kwadratowych, które po lewej stronie informują ile wymiarów będzie miała tablica, a po prawej stronie oddzielają od siebie rozmiar poszczególnych wymiarów:
int
[,,] y = new
int
[10, 5, 4];
Podana przeze mnie tablica jest tablicą trójwymiarową o wymiarach 10x5x4, czyli zawiera w sobie łącznie 10*5*4=200 zmiennych całkowitych.
Aby odwołać się do zmiennej z
tablicy musimy napisać jej nazwę, oraz nawias kwadratowy w którym
podamy indeksy tej zmiennej, np.: y
[3, 2, 1].
Indeksy elementów tablicy są
ponumerowane od 0 do n-1, gdzie n jest rozmiarem poszczególnego
wymiaru. Oznacza to, że jeśli chcemy się odwołać do pierwszego
elementu tablicy x, to musimy odwołać się do zerowego indeksu,
czyli x
[0]. Jeśli tablica ma 10 elementów, a odwołalibyśmy się
do elementu o indeksie 10, to odwołalibyśmy się do 11 elementu,
czyli wyszlibyśmy poza tablice, więc trzeba zwracać uwagę na to,
do jakich elementów się odwołuje.
Zmienne jako funkcje
Jeśli wielokrotnie korzystamy z
jakiegoś wzoru matematycznego, warto jest go opakować w funkcje. W
poprzednim wpisie omówiłem funkcje typu void, które nie zwracają
żadnej wartości, ale prócz nich możemy tworzyć funkcje o typie
dowolnej zmiennej, która zwróci swoją wartość w miejscu jej
wywołania. Przykład funkcji typu float:
float
PitagorasKwadrat (float
x, float
y) {
return x * x + y * y;
}
Zmienne x i y są tutaj argumentami funkcji, które trzeba podawać w trakcie wywoływania tej funkcji. Przykładowe wywołanie:
PitagorasKwadrat (WymiarPierwszegoBoku, WymiarDrugiegoBoku + 3)
Po takim wywołaniu uruchomi się nasza funkcja, która za zmienną x podstawi wartość zmiennej WymiarPierwszegoBoku, a za zmienną y podstawi wartość wyrażenia (WymiarDrugiegoBoku + 3), a w miejsce całej funkcji zostanie wstawiona wartość występująca po wyrazie "return". Takie wywołanie funkcji jest wygodniejsze, niż napisanie takiego wyrażenia:
WymiarPierwszegoBoku * WymiarPierwszegoBoku + (WymiarDrugiegoBoku + 3) * (WymiarDrugiegoBoku + 3)
Struct
Struct jest czymś co może zawierać dowolną liczbę zmiennych i funkcji i właściwie można ją traktować jako zmienną. Structy przydają się jeśli chcemy uporządkować nasze dane, a także umożliwiają tworzenie nietypowych struktur danych. Przykładowa struct:
struct
DaneOsoby {
string
Imie;
string
Nazwisko;
int
Wzrost;
int
Waga;
}
String jest zmienną typu ciąg znaków, czyli służy do zapisywania tekstów. Structy deklaruje się w taki sam sposób jak inne zmienne:
DaneOsoby
[] NoweOsoby = new
DaneOsoby
[100];
Jeśli chcemy się odwołać do jakiegoś elementu znajdującego się w zmiennej typu struct, to najpierw musimy podać nazwę zmiennej, a po kropce napisać nazwę elementu do którego chcemy się odwołać. Przykład zmiany wartości takiego elementu:
NoweOsoby[0].Imie
= "Jan";
Zmienne publiczne
Jeśli chcemy, aby możliwy był dostęp do zmiennej spoza jej skryptu, to musimy oznaczyć ją jako zmienną publiczną. Robi się to w trakcie jej deklaracji, poprzez dodanie słowa "public" przed typem zmiennej, np.:
public
int
x;
Dodatkowo klasowe zmienne publiczne są wyświetlane w inspektorze Unity, czyli można je modyfikować poza kodem oraz w trakcie trwania gry. Wyjątkiem są tutaj zmienne, które trudno przedstawić w inspektorze, czyli np. zmienne znajdujące się w tablicy dwuwymiarowej. Warto też pamiętać, że jeśli zwiększamy uprawnienia jakiegoś elementu, to musimy też zwiększyć uprawnienia elementów do których można się odwołać w tym elemencie, czyli przykładowo jeśli tworzymy structa publicznego, to jego elementy też muszą być publiczne.
Tworzenie sposobu zapisu danych żetonów
No i teraz powrót do mojego projektu: zapiszemy w nim dane żetonów. Podstawowe informacje o żetonach będą wyświetlane na kartach i będą zawierać 4 podstawowe informacje:
- Wartość żetonu,
- Typ żetonu,
- Typ umiejętności,
- Obszar działania umiejętności.
Dane te zapiszemy w formie structu, aby można je było w łatwy sposób powielać:
public
struct
BasicCard
{
public
int
TokenValue;
public
int
TokenType;
public
int
AbilityType;
public
int
AbilityArea;
}
Wiele różnych kart może mieć ten sam typ żetonów, typ umiejętności lub obszar działania umiejętności, więc zapisałem te dane pod postacią zmiennych całkowitych. Dzięki temu nie będę musiał powielać tych samych danych i będę mógł po prostu się do nich odwołać.
Teraz zajmijmy się obszarem działania umiejętności. Różne umiejętności mogą wpływać na różną ilość pól, przeważnie będą wpływać na 2, 4 lub 8 pól. Wygląda więc na to, że dla każdego obszaru warto byłoby przypisać inną liczbę pamięci. Rozgrywka do gry będzie odbywała się na dwuwymiarowej planszy, a więc i pola zasięgu umiejętności muszą być opisywane za pomocą 2 wymiarów:
public
struct
AbilityPosition
{
public
int
x;
public
int
y;
}
Zmienna x będzie tutaj oznaczała odległość pola od żetonu na osi X i w analogiczny sposób będzie działała druga zmienna. Skoro już opracowaliśmy sposób zapisu poszczególnych pól obszaru działania umiejętności, to możemy stworzyć sposób zapisu całego obszaru umiejętności:
public
struct
BasicAbility
{
public
int
AbilitySize;
public
AbilityPosition
[] Pos;
}
Struct ten zawiera 2 informacje: na ile pól będzie wpływał, oraz jak te pola są rozmieszczone. Dla każdego obszaru umiejętności możemy stworzyć osobną tablicę pól.
Teraz należy zadeklarować zmienne klasowe, abyśmy mieli do nich stały dostęp:
public
BasicCard
[] Card = new
BasicCard
[100];
public
BasicAbility
[] Ability = new
BasicAbility
[20];
Wypełnianie informacji o żetonach
Informacje o żetonach warto jest zapisać w jakiejś funkcji typu void, aby w kodzie panował porządek. Każda karta żetonu zawiera 4 informacje, a tych kart może być sporo. Schemat jest dosyć prosty:
void
LoadCardData () {
Card
[0].TokenValue = 4;
Card
[0].TokenType = 0;
Card
[0].AbilityArea = 0;
Card
[0].AbilityType = 0;
Card [1].TokenValue = 3;
Card [1].TokenType = 0;
Card [1].AbilityArea = 1;
Card [1].AbilityType = 1;
}
Schemat ten można łatwo kopiować, ale szybko zauważamy, że za każdym razem musimy zmienić w nim do 8 wartości (4 indeksy i 4 wartości zmiennych). Aby zmniejszyć nakład pracy warto jest dodać zmienną pomocniczą i odpowiednio zmodyfikować schemat:
void
LoadCardData () {
BasicCard
TCard = new
BasicCard
();
TCard.TokenValue
= 4;
TCard.TokenType
= 0;
TCard.AbilityArea
= 0;
TCard.AbilityType
= 0;
Card
[0] = TCard;
TCard.TokenValue
= 3;
TCard.TokenType = 0;
TCard.AbilityArea
= 1;
TCard.AbilityType
= 1;
Card
[1] = TCard;
}
Gdy do jednego structa przypisujemy wartość innego structa, to przenoszona jest cała jego zawartość. Z jednej strony kod ma teraz więcej linijek, ale z drugiej strony samo powielanie danych stało się szybsze - teraz zamiast modyfikować do 8 różnych wartości musimy zmodyfikować do 5 różnych wartości. Jeśli w trakcie projektu stworzymy 100 różnych kart żetonów, to "zaoszczędzimy" 300 wartości które musielibyśmy podmieniać. Leniwy programista to wydajny programista. Dodatkowo warto zauważyć, że jeśli z jakiegoś powodu będziemy chcieli zamienić indeks żetonu, to będziemy musieli zmienić tylko 1 indeksy w kodzie, a nie 4.
No to teraz czas na zapis obszarów umiejętności, którego dokonamy w podobny sposób:
void
LoadAbilityData () {
BasicAbility
TAbility = new
BasicAbility
();
TAbility.AbilitySize = 0;
Ability
[0] = TAbility;
TAbility.AbilitySize
= 2;
TAbility.Pos
= new
AbilityPosition
[2];
TAbility.Pos
[0].x = -1;
TAbility.Pos
[0].y = 0;
TAbility.Pos
[1].x = 1;
TAbility.Pos
[1].y = 0;
Ability
[1] = TAbility;
TAbility.AbilitySize
= 2;
}
W tym kodzie dla każdego obszaru umiejętności możemy zadeklarować zupełnie inny rozmiar tablicy pól, dzięki czemu możemy zaoszczędzić nieco pamięci komputera.
No dobra, a co robić, jeśli będziemy chcieli pobrać rozmiar obszaru umiejętności karty x? Musimy więc zastosować taką linijkę kodu:
Ability
[Card [x].AbilityArea].AbilitySize
Nie da się jednak ukryć, że taki jest dosyć złożony, a częste używanie go w kodzie będzie niewygodne. Dlatego warto jest go opakować w funkcję:
public
int AbilitySize (int
CardNumber) {
return
Ability [Card [CardNumber].AbilityArea].AbilitySize;
}
Dzięki temu pożądaną przez nas wartość można uzyskać wpisując taką linijkę kodu:
AbilitySize (x)
Zdecydowanie wygodniejsze. W podobny sposób można postąpić z danymi pól:
public
int AbilityX (int
CardNumber, int Number) {
return
Ability [Card [CardNumber].AbilityArea].Pos[Number].x;
}
public
int
AbilityY (int
CardNumber, int
Number) {
return
Ability [Card [CardNumber].AbilityArea].Pos[Number].y;
}
Brak komentarzy:
Prześlij komentarz