๐ Project Galaga ์์ํฉ๋๋ค.
Unreal C++๊ณผ ๊ฒ์์ํ์ ์ ๋ชฉํด์ ํ๋ก์ ํธ๋ฅผ ์งํํ์ต๋๋ค.
2024.05.04 ~ 2024.05.21์ ๊ฐ๋ฐ ๊ธฐ๊ฐ์ผ๋ก, ์ด 17์ผ ๋์ ๊ฐ๋ฐ์ ์๋ฃํ์์ต๋๋ค.
๊ฑฐ์ฐฝํ๊ฒ ์์ํ ํ๋ก์ ํธ๋ณด๋จ ์ง๊ธ๊น์ง ๋ฐฐ์ด ๊ฒ๋ค์ ์ข ํฉ์ ์ผ๋ก ์ฌ์ฉํด์ ๊ฒฐ๊ณผ๋ฌผ์ ๋ง๋ค์ด ๋ด๋ณด๊ฒ ๋ค๋ ๋ง์์ผ๋ก ์์ฑํ์์ต๋๋ค.
ํด๋น ์๋ฆฌ์ฆ์๋ ๊ฐ๋ฐ ์ผ์ง๋ฅผ ์ ๋ฆฌํ๋ฉฐ, ๊ฐ๋ฐ ๋ด์ฉ์ ๋ํ ์ค๋ช ๊ณผ ์ด์๋ฅผ ์ ๋ฆฌํ ์์ ์ ๋๋ค.
์์ ๋ง๋ Enemy Base Class์ Enemy FSM์ ์ฌ์ฉํ๋ฉด Stat ์ค์ ๋ง์ผ๋ก ํน์ฑ์ ๊ฐ์ง ์ ์ ๊ตฌํํด ๋ผ ์ ์์ต๋๋ค.
ํ์ง๋ง ์ด๋ ๋จ๋ฐ์ฑ์ ๋ถ๊ณผํฉ๋๋ค.
์คํ ์ด์ง์ ๋ณด์ค๋ ์ฌ๋ฌ๊ฐ์ง ํจํด์ด ์กด์ฌํ์ฃ .
๊ทธ๋์ ๋ณด์ค์ ์ํ์ ๋ฐ๋ผ ๋ค๋ฅธ ํจํด์ผ๋ก ๋ณํํ ์ ์๋๋ก Enemy Base Class๋ฅผ ์์ํ Boss Base Class๋ฅผ ์์ฑํด์ฃผ์์ต๋๋ค.
์ ๋ ๋ณด์ค๊ฐ ํ์ฌ ์ฒด๋ ฅ์ ๋ฐ๋ผ ํจํด์ ๋ณํํ๋๋ก ๊ตฌํํ์์ต๋๋ค.
์์ ์ค๋ช ํ๋ Enemy๊ฐ ๊ฐ์ง๋ ์ฌ๋ฌ ์์์ ๋ํ ๊ตฌ์กฐ์ฒด๋ฅผ Boss์๊ฒ๋ ์์ฑํด์ฃผ์์ต๋๋ค.
USTRUCT(BlueprintType)
struct FChangeByHp
{
GENERATED_BODY()
public:
// Set Enemy Stat
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ClampMin = "0"))
float changeHp;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ClampMin = "0"))
float changeMoveSpeed;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ClampMin = "0"))
float changeAttackSpeed;
// Set Enemy Attack Type
UPROPERTY(EditAnywhere, BlueprintReadWrite)
EEnemyAttackType changeAttackType;
// Set Enemy Moving Type
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (EditCondition = "changeAttackType != EEnemyAttackType::Suiside"))
EEnemyType changeMoveType;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
EEnemyFocus isFocusPlayer = EEnemyFocus::Front;
// Set Auto Fixed Move
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (EditCondition = "changeMoveType == EEnemyType::Fixed"))
bool AutoFixedMove = true;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(EditCondition = "!AutoFixedMove && changeMoveType == EEnemyType::Fixed", ClampMin = "0"))
int FixedMovingPointIndex = 0;
// Set Auto Patrol Move
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (EditCondition = "changeMoveType == EEnemyType::Patrol"))
bool AutoPatrolMove = true;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (EditCondition = "!AutoPatrolMove && changeMoveType == EEnemyType::Patrol", ClampMin = "0", ClampMax = "3"))
float PatrolDelayTime = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (EditCondition = "!AutoPatrolMove && changeMoveType == EEnemyType::Patrol", ClampMin = "0"))
int FirstPatrolMovingPointIndex = 0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (EditCondition = "!AutoPatrolMove && changeMoveType == EEnemyType::Patrol", ClampMin = "0"))
int SecondPatrolMovingPointIndex = 0;
// Wave Range
UPROPERTY(EditAnywhere, Category = EnemyStat, meta = (EditCondition = "changeAttackType == EEnemyAttackType::Wave", ClampMin = "300", ClampMax = "800"))
float BossWaveRange = 300;
// Angle Bullet Count
UPROPERTY(EditAnywhere, Category = EnemyStat, meta = (EditCondition = "changeAttackType == EEnemyAttackType::Angle", ClampMin = "3", ClampMax = "13"))
float BossBulletCount = 3;
};
๋ํ ํด๋น ๊ตฌ์กฐ์ฒด์ ๋ํ ๋ฐฐ์ด์ ์์ฑํ์์ต๋๋ค.
UPROPERTY(EditAnywhere,BlueprintReadWrite,Category=TypeChange)
TArray<FChangeByHp> TypeChangeByHp;
์๋์ฒ๋ผ ๋ฐฐ์ด์ ์์ฑํ๊ณ ๋์ผํ๊ฒ ๊ฐ๋ง ๋ฃ์ด ์ค๋ค๋ฉด, ํด๋น ํจํด์ ๊ฐ๋ค์ ์ฌํ ๋นํ๋๋ก ๊ตฌํํ์ต๋๋ค.
๋ํ ๊ฐ ์ค์ ์์ ์ค๋ฅ๋ฅผ ์ค์ด๊ธฐ ์ํด์ ์ฐ๊ด๋ ๋ณ์๋ผ๋ฆฌ๋ UPROPERTY()์ meta = (EditCondition = "")์ ์ ๊ทน์ ์ผ๋ก ์ฌ์ฉํ์์ต๋๋ค.
์๋ฅผ ๋ค์ด ๊ณต๊ฒฉํดํด์ด Suiside๋ผ๋ฉด ๋ค๋ฅธ ๊ฐ์ ์์ ํ ํ์๊ฐ ์์ผ๋ ๋ชจ๋ ๋นํ์ฑํ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
์ถ๊ฐ๋ก ๊ณต๊ฒฉ ํจํด์ ํ๋ํ(Wave)๋ก ์ค์ ์์๋ง Wave์ ์งํญ๊ฐ์ ์ค์ ํด์ค ์ ์๋๋ก ํ์์ต๋๋ค.
๋ณด์ค์๊ฒ ํ์ฌ ํจํด ๋ณํ ๋ฐฐ์ด์ ๋ํ Index๋ฅผ ๊ฐ์ง๋๋ค.
๊ทธ๋ฆฌ๊ณ ํ์ฌ ์ฒด๋ ฅ๊ณผ ๋ค์ ํจํด์ ์ฒด๋ ฅ๋ฅผ ๊ณ์ํด์ ๋น๊ตํด์ค๋๋ค.
void ABossBase::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
SeeHp();
}
์ฌ๊ธฐ์ ํ์ฌ ์ฒด๋ ฅ์ด ๋ค์ ํจํด์ด ์คํ๋ ์ฒด๋ ฅ ์ดํ๊ฐ ๋์๋ค๋ฉด, ํด๋น Index์ ์ค์ ๋ ๊ฐ์ผ๋ก ์ฌํ ๋นํด์ค๋๋ค.
๊ทธ๋ฆฌ๊ณ Index๋ฅผ 1์ฆ๊ฐํ์ฌ ๋ ๋ค์ ๋ค์ ํจํด์ ๊ธฐ์ค ์ฒด๋ ฅ์ ๋ณด๊ฒ ๋ฉ๋๋ค.
void ABossBase::SeeHp()
{
if (GetEnemyHp() > 0) // Is Boss Alive
{
if (TypeChangeByHp.Num() > SeeHpIndex) // Exception Handling Index Out of Bound
{
if (GetEnemyHp() <= TypeChangeByHp[SeeHpIndex].changeHp) // If Boss Hp under next pattern hp first time
{
// ์๋ต
SeeHpIndex += 1;
}
} // SeeHpIndex is bigger than size of TypeChangeByHp array
}
else
{
// ์๋ต
}
}
ํด๋น ๊ธฐ๋ฅ์ ์ฌ์ฉํ์ฌ ๋ณด์ค๋ ์ฒด๋ ฅ์ ๊ฐ์์ ๋ฐ๋ผ ๋ค์ฑ๋ก์ด ์์ง์, ๊ณต๊ฒฉ ํจํด์ ๊ฐ์ง๋๋ค.
์์ง์ ํจํด 6๊ฐ์ง, ๊ณต๊ฒฉ ํจํด 7๊ฐ์ง๋ก Suiside๊ณผ ๊ฐ์ด ํน์ํ ๊ฒฝ์ฐ๋ฅผ ์ ์ธํ๋๋ผ๊ณ 5*6์ผ๋ก 30๊ฐ์ ํจํด์ ๊ตฌ์ฌํ ์ ์๊ฒ ๋๋ ๊ฒ์ ๋๋ค.
์ฌ๊ธฐ๊น์ง๊ฐ Enemy Base Class๋ฅผ ์์ํด ์ถ๊ฐ์ ์ผ๋ก ๊ธฐ๋ฅ์ ๊ตฌํํ Boss Base Class์ ๋ํ ์ค๋ช ์ด์์ต๋๋ค.