프로젝트/[인프런] 게임 프로그래머 입문 올인원

[게임 프로그래머 입문 올인원] 동적할당과 캐스팅 : 인벤토리 (38강)

순정법사 2023.09.14

 

B. 인벤토리 실습

1. Inventory  생성

먼저 Inventory 를 왜 생성해야 하는지 알아보자

앞서 만들어진 item에 대한 권한을 누군가가 가지고 메모리를 해제 해야 하는데

하나하나 찾아서 각 해제하기 쉽지 않다

 

따라서 Inventory 객체를 생성해서 각 Item을 배열로 넣어주고

Item이 생성, 소멸될때마다 Inventory의 요소들을 생성, 소멸하는 형식으로 하면 깔끔하다

 

Inventory 어디에다가 생성해야 할 것인지에 대한 고민을 하자면

온라인 게임이라면 각 Player 객체에 Inventory 항목을 넣어주면 되지만

혼자하는 게임이라면 전체 코드에 작성해줘도 상관은 없다 (하나로 작성할 예정)

 

a. Inventory class 생성

  1. Inventory 클래스 생성
  2. 모든 아이템을 들고 있을 포인터 배열과 아이템 갯수를 샐 멤버 변수를 생성
  3. 포인터 배열을 초기화 해줌

 

🖇 Inventory.h

#pragma once   
#include "Item.h"

//Enums.h 파일로 옮겨줌
//--------------------
enum {
	MAX_SLOT = 100
};
//--------------------

//1.
class Inventory
{
public:
	Inventory();
	~Inventory();

private:
	//2. 모든 아이템들을 들고있는 포인터 배열
	Item* _items[MAX_SLOT];
	int _itemCount = 0;
};

 

🖇 Inventory.cpp

Inventory::Inventory()	//3.
{
	for (int i = 0; i < MAX_SLOT; i++)
		_items[i] = nullptr;
}

 

👉 여기서 include된 Item 파일은 나중에 전방선언으로 수정..

 

[게임 프로그래머 입문 올인원] 동적할당과 캐스팅 : 전방 선언 (40강)

A. 전방 선언(Forward Declaration) 1. 전방 선언 a. 전방 선언이란? 🌟 컴파일러에게 식별자(함수, 클래스, 변수 등)가 미리 선언되어 있다고 알려주는 것 C++ 및 다른 프로그래밍 언어에서 사용되는 중

monamu.tistory.com

 

b. 아이템을 넣고 삭제할 함수 생성

  1. 아이템을 넣고 지울 멤버 함수 생성, 아이템을 인자로 받아줌
  2. 아이템이 있는지, 그리고 빈 공간이 있는지 체크하기 위해 bool 값을 리턴하게 만들고
  3. 각 값을 확인해 넣을 땐 빈 공간을 찾아 넣어주고 
  4. 제거할 땐 그 공간에 널 포인터를 넣어주는 형식으로 처리 

 

🖇 Inventory.h

public:
	...
	bool Additem(Item* item);	//1. 2.
	bool RemoveItem(Item* item);
    
private:
	int FindEmptySlot();
	int FindItemSlot(Item* item);

 

🖇 Inventory.cpp

...

//3.
bool Inventory::Additem(Item* item)
{
	if (item == nullptr) {
		return false;
	}

	int emptySlot = FindEmptySlot();
	if (emptySlot < 0) {
		return false;
	}

	_items[emptySlot] = item;
	_itemCount++;
	return true;
}

//4. 
bool Inventory::RemoveItem(Item* item)
{
	if (item == nullptr) {
		return false;
	}

	int slot = FindItemSlot(item);
	if (slot)
	{
		return false;
	}

	_items[slot] = nullptr;
	_itemCount--;
	return true;
}

int Inventory::FindItemSlot(Item* item)
{
	for (int i = 0; i < MAX_SLOT; i++) {
		//해당하는 아이템을 찾으면 
		if (_items[i] != item) {
			return i;
		}
	}
	return -1;
}

int Inventory::FindEmptySlot()
{
	for (int i = 0; i < MAX_SLOT; i++) {
		if (_items[i] == nullptr) {
			return i;
		}
	}
	return -1;
}

 

c. 슬롯 번호로 아이템을 찾아주는 기능 생성

나중에 UI와 연동해 아이템을 장착하는 기능이 됨

 

🖇 Inventory.h

public : 
    ...
	
    Item* GetItemAtSlot(int slot);

 

🖇 Inventory.cpp

Item* Inventory::GetItemAtSlot(int slot)
{
	if (slot < 0 || slot >= MAX_SLOT) {
		return nullptr;
	}
	//아이템이 없어도 nullptr을 들고 있어서 바로 처리 
	return _items[slot];
}

 

 

2. Inventory 관리

a. Inventory 싱글톤 생성

온라인 게임이 아닌 혼자하는 게임이기 때문에, Inventory를 싱글톤 객체로 만듦

 

오른쪽 처럼 지역변수로 만드는 방법도 있지만 다른 방법을 사용할 예정!

 

🖇 Inventory.h

public : 
	...
	static Inventory* GetInstance();

private : 
	...
    
	//인벤토리를 관리할 멤버 변수 포인터 선언
	static Inventory* s_instance;

 

🖇 Inventory.cpp

//꼭 static 변수는 처음에 나올거라고 알려줘야 함
Inventory* Inventory::s_instance = nullptr;

...

Item* Inventory::GetItemAtSlot(int slot)
{
	if (slot < 0 || slot >= MAX_SLOT) {
		return nullptr;
	}
	//아이템이 없어도 nullptr을 들고 있어서 바로 처리 
	return _items[slot];
}

 

b. 아이템을 인벤토리에 넣기

위에서 생성한 인스턴스를 인벤토리에 넣어주기

 

🖇 RPGGame.h

int main(){
	for(int i=0; i<100; i++){
		...       
        //아이템을 인벤토리에 넣기
        bool success = Inventory::GetInstance()->Additem(item);
        if (success) {
            cout << "Added item to Inventory" << endl;
            //아직 여기서 delete는 일어나지 않음
        }
        else {
            cout << "Failed to add Item" << endl;
            delete item;	//메모리 관리에 실패한 경우 삭제까지 꼭 해야함
        }
    }   
}

 

🖇 Item.h

public:
	virtual ~Item();	//소멸자를 호출하기 위해 public으로 변경

 

 

3. PK 당해서 랜덤으로 일부 아이템 드랍 

a. 아이템을 드랍하기

인벤토리의 랜덤한 값을 들고와서

인덱스에 해당하는 아이템 값을 가지고 옴

널인지 체크하고 (아예 없는 경우, 아이템 제대로 지우지 못한 경우) 

지웠다면 프린트

 

🖇 RPGGame.cpp

main(){
	...
    //PK 당해서 랜덤으로 일부 아이템 드랍 
    for (int i = 0; i < 20; i++) {
        //0~99
        int randIndex = rand() % MAX_SLOT;
        //랜덤 인덱스에 해당하는 아이템 값 가지고 오기 
        Item* item = Inventory::GetInstance()->GetItemAtSlot(randIndex);

        //널인지체크
        if (item && Inventory::GetInstance()->RemoveItem(item)) {
            cout << "Removed Item" << endl;
        }
    }
}

 

b. 인벤토리 정리하기

나중에 인벤토리의 아이템이 더이상 없어져 인벤토리가 필요 없어지면

메모리를 반환하는 코드까지 작성하기

 

🖇 Inventory.h

public: 
	void Clear();	//아이템 정리

 

🖇 Inventory.cpp

//소멸까지 관리 (인벤토리 사용 X) 
void Inventory::Clear()
{
	for (int i = 0; i < MAX_SLOT; i++) {
		if (_items[i]) {
			delete _items[i];
			_items[i] = nullptr;
		}
	}
}

 

 

4. 완성 코드

a. 전체 코드

RPGGame.zip
0.33MB

 

b. 실행 결과

잘 나온다!!!!! ㅎㅎㅎ

 

 

 


출처 : https://www.inflearn.com/course/%EA%B2%8C%EC%9E%84-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8-%EC%9E%85%EB%AC%B8-%EC%98%AC%EC%9D%B8%EC%9B%90-rookiss#curriculum

 

[게임 프로그래머 입문 올인원] C++ & 자료구조/알고리즘 & STL & 게임 수학 & Windows API & 게임 서버 -

어디부터 시작할지 막막한 게임 프로그래밍 입문자를 위한 All-In-One 커리큘럼입니다. C++, 자료구조/알고리즘, STL, 게임 수학, Windows API, 게임 서버 입문으로 이어지는 알찬 커리큘럼으로 게임 프

www.inflearn.com