1. Player 클래스

플레이어가 몬스터와 상호작용 (공격)

void Player::TickSkill()
{
	if (_flipbook == nullptr)
	{
		return;
	}
	if (IsAnimationEnded())
	{
		DevScene* scene = dynamic_cast<DevScene*>(GET_SINGLE(SceneManager)->GetCurrentScene());
		if (scene == nullptr)
			return;
		if (_weaponType == WeaponType::Sword)
		{
			Creature* creature = scene->GetCreatureAt(GetFrontCellPos());
			if (creature)
			{
				scene->SpawnObject<HitEffect>(GetFrontCellPos());
				creature->OnDamaged(this);
			}
		}
		else if (_weaponType == WeaponType::Bow)
		{
			Arrow* arrow = scene->SpawnObject<Arrow>(_cellPos);
			arrow->SetDir(_dir);
		} 

		SetState(ObjectState::IDLE);
	}
}
  1. if (_flipbook == nullptr)

    • 애니메이션(플립북)이 없으면 바로 종료.
    • 스킬 동작은 애니메이션이 있어야 실행 가능.
  2. if (IsAnimationEnded())

    • 현재 스킬 애니메이션이 끝났는지 확인.
  3. DevScene* scene = dynamic_cast<DevScene*>(GET_SINGLE(SceneManager)->GetCurrentScene());

    • 현재 씬을 가져옵니다. DevScene이 아닌 경우, 동작 중단.
  4. if (_weaponType == WeaponType::Sword)

    • 무기가 Sword인 경우 근접 공격.
    • scene->GetCreatureAt(GetFrontCellPos()): 현재 플레이어 앞에 몬스터가 있는지 확인.
    • 몬스터가 존재하면:
      • 해당 위치에 타격 효과를 생성 (SpawnObject<HitEffect>).
      • 몬스터에 피해를 입힙니다 (OnDamaged(this)).
  5. else if (_weaponType == WeaponType::Bow)

    • 무기가 Bow인 경우 원거리 공격.
    • 화살 객체를 생성하고 (SpawnObject<Arrow>), 방향 설정.
  6. SetState(ObjectState::IDLE)

    • 스킬이 끝난 후 상태를 IDLE로 전환.

2. Monster 클래스

몬스터의 기본 구현

Monster::Monster()
{
	_flipbookMove[DIR_UP] = GET_SINGLE(ResourceManager)->GetFlipbook(L"FB_SnakeUp");
	_flipbookMove[DIR_DOWN] = GET_SINGLE(ResourceManager)->GetFlipbook(L"FB_SnakeDown");
	_flipbookMove[DIR_LEFT] = GET_SINGLE(ResourceManager)->GetFlipbook(L"FB_SnakeLeft");
	_flipbookMove[DIR_RIGHT] = GET_SINGLE(ResourceManager)->GetFlipbook(L"FB_SnakeRight");
	_stat.hp = 50;
	_stat.maxHp = 50;
	_stat.attack = 10;
	_stat.defence = 0;
}
  1. _flipbookMove 초기화

    • 몬스터의 이동 애니메이션 플립북을 방향별로 초기화 (UP, DOWN, LEFT, RIGHT).
  2. 스탯 설정

    • 몬스터의 기본 체력(HP), 공격력(Attack), 방어력(Defence)을 초기화:
      • 체력: 50
      • 공격력: 10
      • 방어력: 0

3. DevScene 클래스

몬스터 생성

template<typename T>
T* DevScene::SpawnObject(Vec2Int pos)
{
	auto isGameObject = std::is_convertible_v<T*, GameObject*>;
	assert(isGameObject);

	T* ret = new T();
	ret->SetCellPos(pos, true);
	AddActor(ret);

	ret->BeginPlay();

	return ret;
}
  1. 템플릿 함수

    • 제네릭 방식으로 GameObject 또는 이를 상속받은 객체를 생성.
  2. auto isGameObject = std::is_convertible_v<T*, GameObject*>

    • 생성하려는 객체가 GameObject 기반인지 확인.
  3. assert(isGameObject)

    • GameObject가 아니라면 프로그램 종료.
  4. 객체 생성 및 초기화:

    • T* ret = new T();: 객체 생성.
    • SetCellPos(pos, true);: 위치를 설정하고, 필요 시 바로 이동.
    • AddActor(ret);: 씬에 객체 추가.
    • ret->BeginPlay();: 초기화 호출.
  5. return ret;

    • 생성된 객체 반환.

랜덤 위치에서 몬스터 생성

template<typename T>
T* DevScene::SpawnObjectAtRandomPos()
{
	Vec2Int randPos = GetRandomEmptyCellPos();
	return SpawnObject<T>(randPos);
}
  1. GetRandomEmptyCellPos()

    • 랜덤한 빈 타일의 위치를 반환.
  2. SpawnObject<T>(randPos)

    • 빈 위치에 객체를 생성.

몬스터 스폰 관리

void DevScene::TickMonsterSpawn()
{
	if (_monsterCount < DESIRED_MONSTER_COUNT)
	{
		SpawnObjectAtRandomPos<Monster>();
	}
}
  1. _monsterCount

    • 현재 씬에 있는 몬스터 수.
  2. DESIRED_MONSTER_COUNT

    • 씬에서 유지하려는 몬스터의 목표 개수 (30).
  3. 조건 확인

    • 현재 몬스터 수가 목표치보다 적으면, 랜덤 위치에서 몬스터를 생성.

몬스터 추가 및 제거

void DevScene::AddActor(Actor* actor)
{
	Super::AddActor(actor);

	Monster* creature = dynamic_cast<Monster*>(actor);
	if (creature)
	{
		_monsterCount++;
	}
}

void DevScene::RemoveActor(Actor* actor)
{
	Super::RemoveActor(actor);

	Monster* creature = dynamic_cast<Monster*>(actor);
	if (creature)
	{
		_monsterCount--;
	}
}
  1. AddActor

    • 몬스터를 추가하면 _monsterCount 증가.
  2. RemoveActor

    • 몬스터를 제거하면 _monsterCount 감소.

랜덤 빈 타일 위치 찾기

Vec2Int DevScene::GetRandomEmptyCellPos()
{
	Vec2Int ret = { -1, -1 };

	if (_tilemapActor == nullptr)
		return ret;

	Tilemap* tm = _tilemapActor->GetTilemap();
	if (tm == nullptr)
		return ret;

	Vec2Int size = tm->GetMapSize();

	while (true)
	{
		int32 x = rand() % size.x;
		int32 y = rand() % size.y;
		Vec2Int cellPos{ x, y };

		if (CanGo(cellPos))
			return cellPos;
	}
}
  1. Tilemap 확인

    • 타일맵이 존재하지 않으면 종료.
  2. 랜덤 위치 찾기

    • 타일맵의 크기 내에서 랜덤 좌표 생성.
    • CanGo(cellPos): 해당 위치가 이동 가능한지 확인.
    • 이동 가능하면 해당 좌표 반환.

profile
李家네_공부방

0개의 댓글