#ifndef _ItemManager_H
#define _ItemManager_H
#include<vector>
#include "Item.h"
#include "CollisionManager.h"
using namespace std;
class ItemManager
{
public:
ItemManager(vector<IDraw*>& drawableObjects );
~ItemManager();
void GenerateItem(Item* item,int posX,int posY, bool isPoison);
void CheckIfUnusedItemExist();
private:
CollisionManager& colMgr=CollisionManager::GetInstance();
vector<Item*> Items;
//int maxItemCnt; 동시에 세개까지라는게 동시에 두개도 허용인지 모르겠어서 일단 보류
};
#endif
멤버 변수로는 싱글턴으로 관리되는 충돌처리매니저의 인스턴스를 가지고,
[충돌처리매니저 구현]
Item객체들을 관리하는 vector를 가진다.
[아이템 구현]
#include"../Include/ItemManager.h"
#include<cstdlib>
using namespace std;
ItemManager::ItemManager(vector<IDraw*>& drawableObjects){
Items.push_back(new Item());
Items.push_back(new Item());
Items.push_back(new Item());
for(int i=0;i<3;i++){
drawableObjects.push_back(Items[i]);
}
}
ItemManager::~ItemManager(){
Items.clear();
vector<Item*>().swap(Items);
}
void ItemManager::GenerateItem(Item* item,int tmpPosX,int tmpPosY,bool tmpIsPoison){
//벽에 생성되면 안됨 나머지연산이라 0이 나올수 있음ㄴ
if(tmpPosX==0)tmpPosX++;
if(tmpPosY==0) tmpPosY++;
item->SetItem(tmpPosX,tmpPosY,tmpIsPoison);
item->SetState(true);
//스네이크바디와 안겹치게 랜덤으로 나타내려면 스네이크의 전체몸을 큰 직사각형으로 하고 그 직사각형 범위외부에서 짜는게 좋을듯
}
void ItemManager::CheckIfUnusedItemExist(){
int tmpPosX,tmpPosY,tmpIsPoison;
for(Item* elem: Items){
//item중에 사용중이 아닌 아이템이라면 해당 아이템 세팅하고 표시
if(!elem->GetState()) {
tmpPosX=rand()%20,tmpPosY=rand()%20,tmpIsPoison=rand()%2;
//collider제거
colMgr.DisableCollider(elem->getPos());
//아이템 새로 생성
GenerateItem(elem,tmpPosX,tmpPosY,tmpIsPoison);
colMgr.SetNewCollider(make_pair(tmpPosX,tmpPosY),elem);
}
}
}
생성자의 인자로 Idraw인터페이스를 상속받는 객체들을 관리하는 벡터를 받는다.
매 아이템 생성마다 새로운 객체를 생성하고 파괴하면 효율이 안 좋을 것이다.
유니티의 object pooling기법에서 착안해서
생성자에서 아이템을 최대 사용량만큼 미리 만들어놓는다.
여기선 세 개로 정했다.
그 후, vector<Item*> items에 넣고, vector<IDraw*> drawableObjects에 넣어준다.
소멸자에서는 items벡터를 clear해주고 빈 벡터와 swap연산으로 초기화해준다.
GenerateItem함수에서는
인자값으로 받은 아이템을 해당 위치에 생성한 후, 사용중을 true로 변경해준다.
주의할 점은 현재 아이템 생성위치를 random에서 나온값을 나머지연산을 통해
0~19까지 좌표값이 나오는데 0이면 벽에 생성되므로 곤란하다.
0일땐 ++연산을 해줬다.
CheckIfUnusedItemExist함수에서는
아이템벡터를 순회하며 사용중이 아닌 아이템은
기존 위치의 콜라이더 제거 후, 좌표를 랜덤으로 뽑는다.
해당 랜덤 위치에 GenerateItem함수로 생성하고, 충돌체 지정을 해준다.
따라서 SnakeGame함수에서 매 주기마다 CheckIfUnusedItemExist를
호출하기만 하면 된다.
아이템 위치를 마구 랜덤으로 뽑아서 아이템끼리 겹칠수 도 있고,
게이트랑 겹치거나 플레이어 몸 중간에 나올수도 있다.
떠오르는 방법은
(1,1)부터 (20,20)까지 모든 좌표를 pair형으로 관리하며,
게이트 위치만 빼놓은 후 벡터에 넣어놓는다.
그 후, 벡터 sort함수에 랜덤을 적용해서 랜덤정렬을 시킨 후,
앞에서부터 좌표를 빼서 사용하는 방식도 좋을 것 같다.
Snake객체에도 isSnakeBody라는 함수가 있으므로
앞에서 좌표를 뺄때 isSnakeBody로 체크하면서 snakeBody가 아닌 좌표만 호출하면 플레이어 몸에서 아이템이 생성하는 문제도 해결 할 수 있을 것이다.