GameMaker에서 그리드 인벤토리 구현: 단계별 분석
그리드 기반 인벤토리 시스템은 Deus Ex나 S.T.A.L.K.E.R.의 메커니즘과 유사하게 다양한 크기의 아이템을 ds_grid에 배치할 수 있게 합니다. 시작하려면 스프라이트가 있는 플레이어 오브젝트 oPlayer와 기본 스프라이트가 없는 컨테이너 오브젝트 oContainer를 만듭니다. 아이템 스프라이트를 준비하세요: spApple (32x32), spWaterBottle (32x64), spMysteriousPackage (64x64), spItemError (32x32). rTest 룸에서 Instances와 UI 레이어를 설정하고 oPlayer와 oContainer의 인스턴스를 추가합니다.
시작 룸 rInit에 영속적인 오브젝트 oGameManager를 만듭니다. Create 이벤트에서:
global.inventoryDebugMode = true;
#macro InteractionDistance 100
global.ItemDB = {};
loadItemDefinitions();
room_goto(rTest);
이 코드는 디버그 모드, 상호작용 거리 상수, 아이템 데이터베이스를 초기화합니다.
JSON에서 아이템 데이터베이스 불러오기
datafiles에 items.json 파일을 배치합니다. 아이템 구조에는 Name, Type, Width, Height, MaxStack, Sprite, Description이 포함됩니다. scItemDatabase 스크립트에 loadItemDefinitions() 함수가 있습니다:
function loadItemDefinitions()
{
var _filename = "items.json";
if (!file_exists(_filename) && global.inventoryDebugMode)
{
show_debug_message("Fayl " + _filename + " not found!");
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 not found for predmeta " + _id);
}
}
global.ItemDB[$ _id] = _item;
}
if (global.inventoryDebugMode)
show_debug_message("Baza predmetov zagruzhena. Count: " + string(array_length(_itemIDs)));
}
getItemData(_itemID) 함수는 아이템 struct를 반환하거나 undefined를 반환합니다.
- ds_struct의 장점: [$ _id]를 통해 문자열 키로 동적 접근 가능.
- 오류 처리: 스프라이트가 없으면 spItemError로 대체.
- 접근자: ds_grid의 경우 [# i, j], struct의 경우 [$ key].
그리드에 아이템 저장 기본
인벤토리는 ds_grid로 구성되며:
- 아이템의 주 셀에는 {itemID, quantity} struct가 저장됩니다.
- 보조 셀에는 주 셀 좌표 {refX, refY}가 저장됩니다.
- 빈 셀은 noone입니다.
아이템은 데이터베이스의 Width/Height를 고려하며 MaxStack으로 스택킹합니다.
scInventory 스크립트는 기본 함수로 시작합니다:
인벤토리 생성 및 소멸
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;
}
}
그리드 확인 및 조작 함수
다음으로 빈 상태 확인을 구현합니다:
- inventoryIsEmpty(_inventory): 그리드를 스캔하여 noone 확인.
주요 아이템 작업:
- 추가: Width/Height에 기반한 빈 공간 찾기, 주 셀 배치 및 다른 셀에 ref 배치.
- 이동: 겹침 확인, refX/refY 업데이트.
- 제거: 주 셀과 ref 셀 지우기.
상호작용을 위해 oPlayer에서 oContainer까지의 거리가 InteractionDistance 미만인지 확인합니다.
인벤토리 UI 표시
UI 레이어에서 draw_sprite_part를 사용하여 그리드를 그리고 아이템을 표시합니다. 마우스 오버로 하이라이트 처리, global.dragItem을 통한 드래그 앤 드롭을 구현합니다.
oPlayer에 inventoryPlayer = inventoryCreate(10, 6);을 추가하고 컨테이너에도 동일하게 적용합니다.
주요 포인트
- ds_grid를 사용하여 [#x,y] 접근자로 효율적인 2D 저장.
- 주 셀에 itemID/quantity만 저장; 나머지는 getItemData로 가져옴.
- 배치 전에 모든 셀 확인하는 원자적 작업 보장.
- DebugMode로 로딩 및 조작 디버깅 간소화.
- 영속적인 oGameManager로 global ItemDB 상태 유지.
— Editorial Team
아직 댓글이 없습니다.