Powrót do strony głównej

Siatkowy inwentarz GameMaker: kod i JSON

Przewodnik po tworzeniu siatkowego inwentarza w GameMaker z użyciem ds_grid i bazy JSON przedmiotów. Opisano inicjalizację, ładowanie danych, przechowywanie z ref-koordynatami i podstawowe operacje. Nadaje się dla middle/senior programistów.

GameMaker: siatka inwentarza jak w S.T.A.L.K.E.R.
Advertisement 728x90

# Implementacja siatkowego inwentarza w GameMaker: analiza krok po kroku

System siatkowego inwentarza pozwala na umieszczanie przedmiotów o różnych rozmiarach w ds_grid, podobnie jak mechaniki w Deus Ex lub S.T.A.L.K.E.R. Na początek utwórz obiekt gracza oPlayer ze sprite'em oraz obiekt kontenera oContainer bez sprite'a domyślnie. Przygotuj sprite'y przedmiotów: spApple (32x32), spWaterBottle (32x64), spMysteriousPackage (64x64), spItemError (32x32). Umieść w pokoju rTest warstwy Instances i UI, dodaj instancje oPlayer i oContainer.

Utwórz persistent-obiekt oGameManager w początkowym pokoju rInit. W zdarzeniu Create:

global.inventoryDebugMode = true;
#macro InteractionDistance 100
global.ItemDB = {};
loadItemDefinitions();
room_goto(rTest);

To inicjalizuje tryb debugowania, stałą odległości interakcji oraz bazę przedmiotów.

Google AdInline article slot

Ładowanie bazy przedmiotów z JSON

Umieść plik items.json w datafiles. Struktura przedmiotu obejmuje Name, Type, Width, Height, MaxStack, Sprite, Description. Skrypt scItemDatabase zawiera loadItemDefinitions():

function loadItemDefinitions()
{
	var _filename = "items.json";
	if (!file_exists(_filename) && global.inventoryDebugMode)
	{
		show_debug_message("Fayl " + _filename + " nie znaleziony!");
		return;
	}
	
	var _buffer = buffer_load(_filename);
	var _jsonString = buffer_read(_buffer, buffer_string);
	buffer_delete(_buffer);

	var _parsedData = json_parse(_jsonString);

	var _itemIDs = struct_get_names(_parsedData);

	for (var i = 0; i < array_length(_itemIDs); ++i)
	{
		var _id = _itemIDs[i];
		var _item = _parsedData[$ _id];

		if (variable_struct_exists(_item, "Sprite"))
		{
			_item.Sprite = asset_get_index(_item.Sprite);
            
			if (_item.Sprite == -1)
			{
				_item.Sprite = spItemError;
				if (global.inventoryDebugMode)
					show_debug_message("Withprayt nie znaleziony dla przedmiotu " + _id);
			}
		}

		global.ItemDB[$ _id] = _item;
	}
    
	if (global.inventoryDebugMode)
		show_debug_message("Baza przedmiotów załadowana. Liczba: " + string(array_length(_itemIDs)));
}

Funkcja getItemData(_itemID) zwraca strukturę przedmiotu lub undefined.

  • Zalety ds_struct: dynamiczny dostęp po kluczach stringowych za pomocą [$ _id].
  • Obsługa błędów: fallback na spItemError przy braku sprite'a.
  • Akcesory: dla ds_grid — [# i, j], dla struct — [$ key].

Podstawy przechowywania przedmiotów w siatce

Inwentarz to ds_grid, gdzie:

Google AdInline article slot
  • Główna komórka przedmiotu przechowuje struct {itemID, quantity}.
  • Pomocnicze komórki — {refX, refY} z współrzędnymi głównej.
  • Puste komórki — noone.

Przedmioty uwzględniają Width/Height z bazy oraz MaxStack dla stosów.

Skrypt scInventory zaczyna od podstawowych funkcji:

Tworzenie i niszczenie inwentarza

function inventoryCreate(_width, _height)
{
	var grid = ds_grid_create(_width, _height);
	ds_grid_clear(grid, noone);
	return grid;
}

function inventoryDestroy(_inventory)
{
	if (ds_exists(_inventory, ds_type_grid))
	{
		ds_grid_destroy(_inventory);
		return true;
	}
	else
	{
		return false;
	}
}

Funkcje sprawdzania i manipulacji siatką

Następnie zaimplementuj sprawdzenie pustości:

Google AdInline article slot
  • inventoryIsEmpty(_inventory): skanuje grid pod kątem noone.

Kluczowe operacje na przedmiotach:

  • Dodawanie: poszukiwanie wolnego miejsca według Width/Height, umieszczenie głównej komórki i ref w pozostałych.
  • Przemieszczanie: sprawdzenie kolizji, aktualizacja refX/refY.
  • Usuwanie: czyszczenie głównej i komórek ref.

Do interakcji: sprawdzenie odległości < InteractionDistance od oPlayer do oContainer.

Wyświetlanie UI inwentarza

Na warstwie UI rysuj siatkę za pomocą draw_sprite_part dla przedmiotów. Obsługuj mouse-over do podświetlenia, drag-and-drop za pomocą global.dragItem.

W oPlayer dodaj inventoryPlayer = inventoryCreate(10, 6); analogicznie dla kontenerów.

Co ważne

  • Używaj ds_grid do efektywnego 2D-przechowywania z akcesorami [#x,y].
  • Przechowuj tylko itemID/quantity w głównej komórce, resztę — za pomocą getItemData.
  • Zapewnij atomowość operacji: sprawdzaj wszystkie komórki przed umieszczeniem.
  • DebugMode ułatwia debugowanie ładowania i manipulacji.
  • Persistent oGameManager gwarantuje globalny stan ItemDB.

— Editorial Team

Advertisement 728x90

Czytaj dalej