Inventory / Ewipunek / Plecak - proste rozwiązanie
Poniedziałek, 10 Czerwca 2024, 18:47
Czas czytania 11 minut, 21 sekund
Zgodne z GM:
W tym artykule dowiesz się, jak stworzyć bardzo proste inventory (plecak) z itemami (ekwipunkiem) w GameMakerze.
Jeśli chodzi o inventory, jest tyle rozwiązań, ile programistów. Nawet to w jaki sposób jest przechowywane - czy będzie to tablica, czy jakaś inna struktura, jest kwestią wyboru. Jeszcze więcej możliwości istnieje jeśli chodzi o listę dostępnych itemów - mogą to być nazwy sprite, nazwy obiektów, liczby rzeczywiste wskazujące na jakąś bazę przedmiotów (i tu znów - albo tablice dwuwymiarowe, albo structy).
Wskazówka:
Link do gotowego projektu znajduje się na samym dole.
W tej wersji artykułu skorzystamy z listy itemów opartej na nazwie sprite, dzięki czemu poziom skomplikowania nie będzie za wysoki - to rozwiązanie może jednak być niewystarczające dla wielu osób. Na koniec artykułu podpowiem gdzie można by się wpiąć, aby wykonywać akcje zależnie od wybranego itemu.
Obiekt itemów / przedmiotów
Tutaj sprawa jest prosta. Stwórzcie sobie kilka sprite'ów, ja dla wygody nazwałem swoje prefixem
Funkcje obsługi inventory
Nasz ekwipunek będzie prosty, stworzymy więc raptem 3 funkcje:
- dodawanie do inventory
- usuwanie z inventory
- tworzenie itemów "na ziemi"
Stwórzcie nowy skrypt i nazwijcie go
Po pierwsze, sprawimy, że nasze inventory stworzy się w momencie startu gry, umieszczając prosty kod poza jakąkolwiek funkcją w skrypcie:
kod#macro INVENTORY_SIZE 20 // rozmiar inventory
global.inventory = array_create(INVENTORY_SIZE, -1); // kazda komorka jest na razie pustaSkorzystamy z makro, aby w przypadku zmiany rozmiaru inventory nie trzeba było przepisywać kodu i szukać każdego możliwego miejsca, gdzie wpisaliśmy rozmiar.
Domyślnie tworzymy tablicę o rozmiarze 20 (tablica taka ma indeksy 0 - 19), a każdy jej element będzie mieć wartość domyślną -1. Taką wartość będziemy uznawać za "brak przedmiotu". W innym wypadku, w danej komórce tabeli będzie referencja na sprite.
Tworzenie przedmiotów
Zaczniemy od funkcji, która stworzy nam przedmiot w losowym miejscu na mapie. Jej argumentem będzie nazwa sprite, jaki ten item otrzyma.
Funkcja przyda nam się przy usuwaniu rzeczy z inventory, oraz na starcie gry, aby wygenerować kilka losowych przedmiotów.
Jej zasada działania jest prosta - stworzy
kod/// Tworzy item w świecie gry
/// @param {Asset.GMSprite} _spr jaki sprite będzie mieć item
/// @return {Id.Instance}
function inventory_item_create(_spr) {
return instance_create_layer(irandom(room_width), irandom(room_height), layer, obj_item, {sprite_index: _spr});
}
Przykład użycia tej funkcji:
kodinventory_item_create(item_key);
Dodawanie przedmiotów
Teraz stworzymy funkcję, która dodaje przedmiot do inventory.
- najpierw sprawdźmy, czy w tablicy jest jeszcze jakieś pole z wartością -1 i zapamiętajmy indeks tej komórki (
- jeśli ten indeks jest inny niż -1 (a zatem został znaleziony), zmieńmy wartość tego elementu tablicy na sprite naszego itemu; zwracamy
- jeśli nie udało się wstawić itemu, zwróćmy
kod/// @desc Dodaje item do inventory jeśli jest miejsce
/// @param {Asset.GMSprite} _spr jaki sprite
/// @return {Bool}
function inventory_add(_spr) {
var _place = array_get_index(global.inventory, -1); // znajdz czy jest jakies wolne miejsce
if (_place > -1) {
global.inventory[_place] = _spr;
return true;
}
return false;
}
Przykład użycia tej funkcji:
kodinventory_add(item_key);
Usuwanie przedmiotów
Następnie czas na funkcję, która usuwa przedmioty. Tym razem, podajemy slot, z którego chcemy usunąć przedmiot, sprawdzamy czy faktycznie coś tam jest:
- jeśli tak: tworzymy przedmiot "na ziemi" w grze i ustawiamy dany slot na -1; zwracamy
- jeśli nie: zwracamy
kod/// Usuwa item z inventory
/// @param {Real} _slot numer slotu
/// @return {Bool}
function inventory_remove(_slot) {
if (global.inventory[_slot] != -1) {
inventory_item_create(global.inventory[_slot]); // stwórz przedmiot
global.inventory[_slot] = -1; // ustaw ze ten slot jest pusty
return true;
}
return false;
}
Dodawanie przedmiotu po kliknięciu
Wracamy teraz do obiektu
W evencie Left Pressed dodajemy bardzo prostą logikę - próbujemy dodać item do inventory, jeśli funkcja zwróci true i item dodano, to niszczymy obecny obiekt. Jeżeli nie - nic się nie dzieje.
kodif (inventory_add(sprite_index)) {
instance_destroy();
}Wskazówka:
Zauważ, że funkcję inventory_add() można też użyć w dowolnym kontekście z dowolnego innego obiektu - np. za przejście etapu czy na koniec dialogu - nie trzeba kliknąć w item aby go dostać.
Rysowanie inventory
To najtrudniejsza część. Cała trudność polega tutaj jednak głównie na matematyce.
Moje założenie jest takie, że narysujemy prostokąt, w którym będą sloty, w których rysowane będą itemy, a odstęp między każdym z tych slotów to 10 pikseli od brzegu inventory oraz innych slotów.
Warto więc zauważyć, że odstępów między slotami jest o 1 mniej niż kolumn/wierszy (np. 10 slotów oznacza, że między nimi jest 9 odstępów), oraz 2 odstępy od brzegów. Możemy więc uznać, że przerw jest:
- ilość slotów w danej osi minus 1 + 2
- ilość slotów w danej osi + 1 (i ten wariant wybierzemy)
(A) - Cała szerokość inventory to zatem ilość slotów poziomo (ilość kolumn) razy szerokość slotów + margines, plus jeszcze jeden margines.
(B) - Cała wysokość inventory to zatem ilość slotów pionowo (ilość rzędów) razy szerokość slotów + margines, plus jeszcze jeden margines.
Do narysowania inventory wstępnie ustawimy sobie pomocnicze zmienne tymczasowe:
- i, do pętli która rysuje itemy
- row, col - aktualny wiersz i kolumna
- slots_per_row - ile itemow chcemy mieć w jednym rzędzie
- rows_total - na podstawie poprzedniej zmiennej oraz rozmiaru inventory dynamicznie liczymy ile jest wierszy
- slot_size - rozmiar slotu w px (u mnie 64)
- margin - rozmiar marginesu
- slot_x, slot_y - ponieważ potrzebujemy pozycji slotu do rysowania ramki i rysowania itemu, żeby nie powielać matematyki i nie zaczerniać kodu, wstępnie je sobie obliczymy w każdym przejściu pętli
- hovered - sprawdzamy, czy kursor myszy najechał na slot
Tworzymy obiekt
kodvar i; // iteracja pętli for
var row = 0, col = 0; // obceny wiersz i kolumna inventory
var slots_per_row = 10; // co ile itemow nowa linia
var rows_total = ceil(INVENTORY_SIZE/slots_per_row); // liczba wierszy, zaokr. w gore
var slot_size = 64; // rozmiar slotu w px
var margin = 10; // margines
var slot_x = 0, slot_y = 0; // pozycje obecnej komorki
var hovered = false; // czy kursor w slocie
Mamy już nasze zmienne, teraz czas na narysowanie "tła", zgodnie z założeniami (A) i (B) opisanymi wcześniej. Ta część może wydawać się skomplikowna i można ją zapisać na kilka sposobów (np. osobno szerokość slotów razy ilość slotów w kolumnie/wierszu plus liczbę marginesów (czyli ilość slotów +1) razy margines):
kod// rysuj tlo
draw_set_color(c_gray);
draw_set_alpha(1);
draw_rectangle(10, 10, 10 + margin + (slots_per_row*(slot_size+margin)), 10 + margin + (rows_total*(slot_size+margin)), false);
Teraz najdłuższy fragment - rysowanie inventory.
W pętli, item po itemie, wykonamy:
- wyliczenie aktualnej kolumny i wiersza, korzystając z funkcji modulo i division. Pierwsza zwraca resztę z dzielenia i umożliwi nam znalezienie kolumny, druga to liczba całkowita bez reszty z dzielenia i pozwoli nam uzyskać informację o aktualnym rzędzie
- ustalenie x i y obecnej komórki
- sprawdzenie czy nastąpiło najechanie mszą
- ustalenie tła slotu (czarne; czerwone jeśli najechano)
- usunięcie itemu jeśli klikniemy prawym przyciskiem myszy
- narysowanie tła slotu
- narysowanie itemu (jeśli jakiś jest na tej pozycji)
Wskazówka:
Inventory można by też rysować korzystając z dwóch pętli i trzymać itemy w tablicy 2D, ale... wtedy jego rozmiar musiałby być równy liczbie slotów w rzędzie razy liczbę rzędów. Skorzystanie z jednej pętli i wyliczanie rzędu i kolumny na bieżąco umożliwia nam mieć dowolną liczbę slotów, w tym nieparzystą, a ostatni rząd nie musi być pełen - gra mimo to nie rzuci błędami, gdyż rysuje tyle komórek ile jest itemów, nie więcej.
kod// rysuj itemy
for(i = 0; i < INVENTORY_SIZE; i++) {
// wylicz jaka jest teraz kolumna i rząd
col = i mod slots_per_row; // reszta z dzielenia całkowitego
row = i div slots_per_row; // dzielenie całkowite (bez reszty)
// ustal x i y obecnego slotu
slot_x = 10 + margin + col * (slot_size+margin);
slot_y = 10 + margin + row * (slot_size+margin);
// ustal, ze obecnie kursor nie najechał na komórkę
hovered = false;
if (mouse_x >= slot_x and mouse_x < slot_x + slot_size) {
if (mouse_y >= slot_y and mouse_y < slot_y + slot_size) {
// ustal, że jednak najechał
hovered = true;
}
}
// zresetuj kolor na czarny (jeśli poprzednio były inny)
draw_set_color(c_black);
// jeśli kursor najechał
if (hovered) {
// zmień kolor rysowania na czerwony
draw_set_color(c_red);
// sprawdź czy kliknięto przycisk
if (mouse_check_button_pressed(mb_right)) {
// usuń item (o ile jakiś jest)
inventory_remove(i);
}
}
// narysuj ramkę slotu
draw_rectangle(
slot_x, slot_y,
slot_x + slot_size, slot_y + slot_size,
true );
// narysuj item, jeśli jakiś jest
if (global.inventory[i] != -1) {
draw_sprite(global.inventory[i], 0, slot_x, slot_y);
}
}
Teraz w
kod// stworz randomowe 5 itemow
repeat(5) {
inventory_item_create(choose(item_phones, item_wheel, item_key, item_compass, item_gamepad));
}
Dodajemy teraz
Cyk, wszystko działa :)
Dodatkowe zmiany:
Użycie przedmiotów.
Aby "użyć przedmiot", można dodać event na lewy przycisk myszy w warunku
kod/// Uzywa itemu z inventory
/// @param {Real} _slot numer slotu
function inventory_use(_slot) {
if (global.inventory[_slot] != -1) {
var _remove = true; // czy usunąć przedmiot - domyślnie - tak
var _create = false; // czy stworzyć przedmiot na ziemi - domyślnie - nie
switch (global.inventory[_slot]) {
case item_key:
// kod gdy uzyjemy klucza
break;
case item_compass:
// kod gdy uzyjemy kompasu
break;
default:
_create = true; // nie wykonano zadnej akcji, jednak zespawnuj item
}
if (_create) {
inventory_item_create(global.inventory[_slot]); // stwórz przedmiot
}
if (_remove) {
global.inventory[_slot] = -1; // ustaw ze ten slot jest pusty
}
}
}
Ukrywanie inventory
Wystarczy dodać event Key Pressed I (nie Key Down) i dać tam:
kodvisible = !visible;Kod z Draw Gui nie wykonuje się gdy obiekt nie jest widoczny, nie uda się więc usunąć przedmiotów.
W obiekcie
kodif (not instance_exists(obj_inventory) or obj_inventory.visible = false) naokoło istniejącego kodu, co zapobiegać będzie dodawaniu itemów gdy otwarte jest inventory, zwłaszcza, gdy pod nim jest item i wykonać mogłyby się dwa eventy myszy na lewy przycisk. Oczywiście obiekt inventory można też usuwać zamiast ukrywać - to już wasz wybór.
Baza itemów
Zamiast sprite, można by zapisywać liczby naturalne i stworzyć jakąś tablicę z przedmiotami, np.:
kodglobal.inventory = [
{spr: item_wheel, name: "Kierownica", price: 100},
{spr: item_compass, name: "Kompas", price: 200},
];Co pozwoli nam trzymać więcej parametrów danego itemu. Oczywiście wtedy należy podmienić draw_sprite w inventory na
Sortowanie itemów.
Po usunięciu itemu można wykonać
Gotowy projekt:
gmclan.org/upload/gm/gmclan_inventory.yyz - przygotowany w GM 2024.4 .
Polecam też artykuł o tym, jak zrobić ekwipowanie itemów ze statystykami: gmclan.org/artykul/110 .
Wskazówka:
Link do gotowego projektu znajduje się na samym dole.
W tej wersji artykułu skorzystamy z listy itemów opartej na nazwie sprite, dzięki czemu poziom skomplikowania nie będzie za wysoki - to rozwiązanie może jednak być niewystarczające dla wielu osób. Na koniec artykułu podpowiem gdzie można by się wpiąć, aby wykonywać akcje zależnie od wybranego itemu.
Obiekt itemów / przedmiotów
Tutaj sprawa jest prosta. Stwórzcie sobie kilka sprite'ów, ja dla wygody nazwałem swoje prefixem
item_
, moje będą mieć rozmiar 64x64px. Stwórzcie obiekt o nazwie obj_item
i ustawcie mu jako sprite jeden z wybranych przez was przedmiotów. Na razie to wszystko.Funkcje obsługi inventory
Nasz ekwipunek będzie prosty, stworzymy więc raptem 3 funkcje:
- dodawanie do inventory
- usuwanie z inventory
- tworzenie itemów "na ziemi"
Stwórzcie nowy skrypt i nazwijcie go
scr_inventory
. Można wywalić domyślną funkcję która tam będzie.Po pierwsze, sprawimy, że nasze inventory stworzy się w momencie startu gry, umieszczając prosty kod poza jakąkolwiek funkcją w skrypcie:
kod#macro INVENTORY_SIZE 20 // rozmiar inventory
global.inventory = array_create(INVENTORY_SIZE, -1); // kazda komorka jest na razie pustaSkorzystamy z makro, aby w przypadku zmiany rozmiaru inventory nie trzeba było przepisywać kodu i szukać każdego możliwego miejsca, gdzie wpisaliśmy rozmiar.
Domyślnie tworzymy tablicę o rozmiarze 20 (tablica taka ma indeksy 0 - 19), a każdy jej element będzie mieć wartość domyślną -1. Taką wartość będziemy uznawać za "brak przedmiotu". W innym wypadku, w danej komórce tabeli będzie referencja na sprite.
Tworzenie przedmiotów
Zaczniemy od funkcji, która stworzy nam przedmiot w losowym miejscu na mapie. Jej argumentem będzie nazwa sprite, jaki ten item otrzyma.
Funkcja przyda nam się przy usuwaniu rzeczy z inventory, oraz na starcie gry, aby wygenerować kilka losowych przedmiotów.
Jej zasada działania jest prosta - stworzy
obj_item
na losowej pozycji, korzystając z funkcji irandom (czyli losowa liczba całkowita), w przedziale 0 do wysokość/szerokość rooma. Korzystając z opcjonalnego argumentu w GameMakrze 2023+, od razu ustawimy sprite, na ten podany w argumencie funkcji.kod/// Tworzy item w świecie gry
/// @param {Asset.GMSprite} _spr jaki sprite będzie mieć item
/// @return {Id.Instance}
function inventory_item_create(_spr) {
return instance_create_layer(irandom(room_width), irandom(room_height), layer, obj_item, {sprite_index: _spr});
}
Przykład użycia tej funkcji:
kodinventory_item_create(item_key);
Dodawanie przedmiotów
Teraz stworzymy funkcję, która dodaje przedmiot do inventory.
- najpierw sprawdźmy, czy w tablicy jest jeszcze jakieś pole z wartością -1 i zapamiętajmy indeks tej komórki (
array_get_index
)- jeśli ten indeks jest inny niż -1 (a zatem został znaleziony), zmieńmy wartość tego elementu tablicy na sprite naszego itemu; zwracamy
true
- jeśli nie udało się wstawić itemu, zwróćmy
false
kod/// @desc Dodaje item do inventory jeśli jest miejsce
/// @param {Asset.GMSprite} _spr jaki sprite
/// @return {Bool}
function inventory_add(_spr) {
var _place = array_get_index(global.inventory, -1); // znajdz czy jest jakies wolne miejsce
if (_place > -1) {
global.inventory[_place] = _spr;
return true;
}
return false;
}
Przykład użycia tej funkcji:
kodinventory_add(item_key);
Usuwanie przedmiotów
Następnie czas na funkcję, która usuwa przedmioty. Tym razem, podajemy slot, z którego chcemy usunąć przedmiot, sprawdzamy czy faktycznie coś tam jest:
- jeśli tak: tworzymy przedmiot "na ziemi" w grze i ustawiamy dany slot na -1; zwracamy
true
- jeśli nie: zwracamy
false
kod/// Usuwa item z inventory
/// @param {Real} _slot numer slotu
/// @return {Bool}
function inventory_remove(_slot) {
if (global.inventory[_slot] != -1) {
inventory_item_create(global.inventory[_slot]); // stwórz przedmiot
global.inventory[_slot] = -1; // ustaw ze ten slot jest pusty
return true;
}
return false;
}
Dodawanie przedmiotu po kliknięciu
Wracamy teraz do obiektu
obj_item
i dodajemy w nim event "left pressed" (ważne - nie left press, gdyż chodzi nam o moment gdy mysz przechodzi ze stanu nieklikniętego w kliknięty; nie chodzi też o event global, gdyż wtedy każdy item dodałby się gdziekolwiek nie klikniemy)W evencie Left Pressed dodajemy bardzo prostą logikę - próbujemy dodać item do inventory, jeśli funkcja zwróci true i item dodano, to niszczymy obecny obiekt. Jeżeli nie - nic się nie dzieje.
kodif (inventory_add(sprite_index)) {
instance_destroy();
}Wskazówka:
Zauważ, że funkcję inventory_add() można też użyć w dowolnym kontekście z dowolnego innego obiektu - np. za przejście etapu czy na koniec dialogu - nie trzeba kliknąć w item aby go dostać.
Rysowanie inventory
To najtrudniejsza część. Cała trudność polega tutaj jednak głównie na matematyce.
Moje założenie jest takie, że narysujemy prostokąt, w którym będą sloty, w których rysowane będą itemy, a odstęp między każdym z tych slotów to 10 pikseli od brzegu inventory oraz innych slotów.
Warto więc zauważyć, że odstępów między slotami jest o 1 mniej niż kolumn/wierszy (np. 10 slotów oznacza, że między nimi jest 9 odstępów), oraz 2 odstępy od brzegów. Możemy więc uznać, że przerw jest:
- ilość slotów w danej osi minus 1 + 2
- ilość slotów w danej osi + 1 (i ten wariant wybierzemy)
(A) - Cała szerokość inventory to zatem ilość slotów poziomo (ilość kolumn) razy szerokość slotów + margines, plus jeszcze jeden margines.
(B) - Cała wysokość inventory to zatem ilość slotów pionowo (ilość rzędów) razy szerokość slotów + margines, plus jeszcze jeden margines.
Do narysowania inventory wstępnie ustawimy sobie pomocnicze zmienne tymczasowe:
- i, do pętli która rysuje itemy
- row, col - aktualny wiersz i kolumna
- slots_per_row - ile itemow chcemy mieć w jednym rzędzie
- rows_total - na podstawie poprzedniej zmiennej oraz rozmiaru inventory dynamicznie liczymy ile jest wierszy
- slot_size - rozmiar slotu w px (u mnie 64)
- margin - rozmiar marginesu
- slot_x, slot_y - ponieważ potrzebujemy pozycji slotu do rysowania ramki i rysowania itemu, żeby nie powielać matematyki i nie zaczerniać kodu, wstępnie je sobie obliczymy w każdym przejściu pętli
- hovered - sprawdzamy, czy kursor myszy najechał na slot
Tworzymy obiekt
obj_inventory
, w którym dajemy event Draw GUI.kodvar i; // iteracja pętli for
var row = 0, col = 0; // obceny wiersz i kolumna inventory
var slots_per_row = 10; // co ile itemow nowa linia
var rows_total = ceil(INVENTORY_SIZE/slots_per_row); // liczba wierszy, zaokr. w gore
var slot_size = 64; // rozmiar slotu w px
var margin = 10; // margines
var slot_x = 0, slot_y = 0; // pozycje obecnej komorki
var hovered = false; // czy kursor w slocie
Mamy już nasze zmienne, teraz czas na narysowanie "tła", zgodnie z założeniami (A) i (B) opisanymi wcześniej. Ta część może wydawać się skomplikowna i można ją zapisać na kilka sposobów (np. osobno szerokość slotów razy ilość slotów w kolumnie/wierszu plus liczbę marginesów (czyli ilość slotów +1) razy margines):
kod// rysuj tlo
draw_set_color(c_gray);
draw_set_alpha(1);
draw_rectangle(10, 10, 10 + margin + (slots_per_row*(slot_size+margin)), 10 + margin + (rows_total*(slot_size+margin)), false);
Teraz najdłuższy fragment - rysowanie inventory.
W pętli, item po itemie, wykonamy:
- wyliczenie aktualnej kolumny i wiersza, korzystając z funkcji modulo i division. Pierwsza zwraca resztę z dzielenia i umożliwi nam znalezienie kolumny, druga to liczba całkowita bez reszty z dzielenia i pozwoli nam uzyskać informację o aktualnym rzędzie
- ustalenie x i y obecnej komórki
- sprawdzenie czy nastąpiło najechanie mszą
- ustalenie tła slotu (czarne; czerwone jeśli najechano)
- usunięcie itemu jeśli klikniemy prawym przyciskiem myszy
- narysowanie tła slotu
- narysowanie itemu (jeśli jakiś jest na tej pozycji)
Wskazówka:
Inventory można by też rysować korzystając z dwóch pętli i trzymać itemy w tablicy 2D, ale... wtedy jego rozmiar musiałby być równy liczbie slotów w rzędzie razy liczbę rzędów. Skorzystanie z jednej pętli i wyliczanie rzędu i kolumny na bieżąco umożliwia nam mieć dowolną liczbę slotów, w tym nieparzystą, a ostatni rząd nie musi być pełen - gra mimo to nie rzuci błędami, gdyż rysuje tyle komórek ile jest itemów, nie więcej.
kod// rysuj itemy
for(i = 0; i < INVENTORY_SIZE; i++) {
// wylicz jaka jest teraz kolumna i rząd
col = i mod slots_per_row; // reszta z dzielenia całkowitego
row = i div slots_per_row; // dzielenie całkowite (bez reszty)
// ustal x i y obecnego slotu
slot_x = 10 + margin + col * (slot_size+margin);
slot_y = 10 + margin + row * (slot_size+margin);
// ustal, ze obecnie kursor nie najechał na komórkę
hovered = false;
if (mouse_x >= slot_x and mouse_x < slot_x + slot_size) {
if (mouse_y >= slot_y and mouse_y < slot_y + slot_size) {
// ustal, że jednak najechał
hovered = true;
}
}
// zresetuj kolor na czarny (jeśli poprzednio były inny)
draw_set_color(c_black);
// jeśli kursor najechał
if (hovered) {
// zmień kolor rysowania na czerwony
draw_set_color(c_red);
// sprawdź czy kliknięto przycisk
if (mouse_check_button_pressed(mb_right)) {
// usuń item (o ile jakiś jest)
inventory_remove(i);
}
}
// narysuj ramkę slotu
draw_rectangle(
slot_x, slot_y,
slot_x + slot_size, slot_y + slot_size,
true );
// narysuj item, jeśli jakiś jest
if (global.inventory[i] != -1) {
draw_sprite(global.inventory[i], 0, slot_x, slot_y);
}
}
Teraz w
obj_inventory
dodamy jeszcze funkcję, która na start gry zespawnuje nam kilka losowych itemów, korzystając ze znanej już funkcji inventory_item_create
- event Create.kod// stworz randomowe 5 itemow
repeat(5) {
inventory_item_create(choose(item_phones, item_wheel, item_key, item_compass, item_gamepad));
}
Dodajemy teraz
obj_inventory
do roomu w grze i odpalamy ją:Cyk, wszystko działa :)
Dodatkowe zmiany:
Użycie przedmiotów.
Aby "użyć przedmiot", można dodać event na lewy przycisk myszy w warunku
if (hovered) {}
. Najlepiej stworzyć nową funkcję, np. inventory_use(i);
:kod/// Uzywa itemu z inventory
/// @param {Real} _slot numer slotu
function inventory_use(_slot) {
if (global.inventory[_slot] != -1) {
var _remove = true; // czy usunąć przedmiot - domyślnie - tak
var _create = false; // czy stworzyć przedmiot na ziemi - domyślnie - nie
switch (global.inventory[_slot]) {
case item_key:
// kod gdy uzyjemy klucza
break;
case item_compass:
// kod gdy uzyjemy kompasu
break;
default:
_create = true; // nie wykonano zadnej akcji, jednak zespawnuj item
}
if (_create) {
inventory_item_create(global.inventory[_slot]); // stwórz przedmiot
}
if (_remove) {
global.inventory[_slot] = -1; // ustaw ze ten slot jest pusty
}
}
}
Ukrywanie inventory
Wystarczy dodać event Key Pressed I (nie Key Down) i dać tam:
kodvisible = !visible;Kod z Draw Gui nie wykonuje się gdy obiekt nie jest widoczny, nie uda się więc usunąć przedmiotów.
W obiekcie
obj_item
można wtedy dodać warunek:kodif (not instance_exists(obj_inventory) or obj_inventory.visible = false) naokoło istniejącego kodu, co zapobiegać będzie dodawaniu itemów gdy otwarte jest inventory, zwłaszcza, gdy pod nim jest item i wykonać mogłyby się dwa eventy myszy na lewy przycisk. Oczywiście obiekt inventory można też usuwać zamiast ukrywać - to już wasz wybór.
Baza itemów
Zamiast sprite, można by zapisywać liczby naturalne i stworzyć jakąś tablicę z przedmiotami, np.:
kodglobal.inventory = [
{spr: item_wheel, name: "Kierownica", price: 100},
{spr: item_compass, name: "Kompas", price: 200},
];Co pozwoli nam trzymać więcej parametrów danego itemu. Oczywiście wtedy należy podmienić draw_sprite w inventory na
global.inventory[i].sprite
itp., można też wtedy wyświetlać opis i cenę przedmiotu jeśli hovered = true
. Można też dodać dowolne inne parametry, jak funkcja która wykona się gdy użyjemy przedmiotu, czy obiekt jaki ma się stworzyć - znów, to już wasz wybór.Sortowanie itemów.
Po usunięciu itemu można wykonać
array_sort(global.inventory);
.Gotowy projekt:
gmclan.org/upload/gm/gmclan_inventory.yyz - przygotowany w GM 2024.4 .
Polecam też artykuł o tym, jak zrobić ekwipowanie itemów ze statystykami: gmclan.org/artykul/110 .