[UE5] ๐Ÿš€ Project Galaga (7)

Singery00ยท2024๋…„ 5์›” 21์ผ
0

Project Galaga

๋ชฉ๋ก ๋ณด๊ธฐ
7/15
post-thumbnail

๊ฐœ์š”

๐Ÿš€ Project Galaga ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

Unreal C++๊ณผ ๊ฒŒ์ž„์ˆ˜ํ•™์„ ์ ‘๋ชฉํ•ด์„œ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.

2024.05.04 ~ 2024.05.21์˜ ๊ฐœ๋ฐœ ๊ธฐ๊ฐ„์œผ๋กœ, ์ด 17์ผ ๋™์•ˆ ๊ฐœ๋ฐœ์„ ์™„๋ฃŒํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๊ฑฐ์ฐฝํ•˜๊ฒŒ ์‹œ์ž‘ํ•œ ํ”„๋กœ์ ํŠธ๋ณด๋‹จ ์ง€๊ธˆ๊นŒ์ง€ ๋ฐฐ์šด ๊ฒƒ๋“ค์„ ์ข…ํ•ฉ์ ์œผ๋กœ ์‚ฌ์šฉํ•ด์„œ ๊ฒฐ๊ณผ๋ฌผ์„ ๋งŒ๋“ค์–ด ๋‚ด๋ณด๊ฒ ๋‹ค๋Š” ๋งˆ์Œ์œผ๋กœ ์™„์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

ํ•ด๋‹น ์‹œ๋ฆฌ์ฆˆ์—๋Š” ๊ฐœ๋ฐœ ์ผ์ง€๋ฅผ ์ •๋ฆฌํ•˜๋ฉฐ, ๊ฐœ๋ฐœ ๋‚ด์šฉ์— ๋Œ€ํ•œ ์„ค๋ช…๊ณผ ์ด์Šˆ๋ฅผ ์ •๋ฆฌํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

๐Ÿš€ Project Galaga Github Repository


๋ณธ๋ก 


์Šคํ…Œ์ด์ง€ ๋ณด์Šค ๊ตฌํ˜„

์•ž์„œ ๋งŒ๋“  Enemy Base Class์™€ Enemy FSM์„ ์‚ฌ์šฉํ•˜๋ฉด Stat ์„ค์ •๋งŒ์œผ๋กœ ํŠน์„ฑ์„ ๊ฐ€์ง„ ์ ์„ ๊ตฌํ˜„ํ•ด ๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์ด๋Š” ๋‹จ๋ฐœ์„ฑ์— ๋ถˆ๊ณผํ•ฉ๋‹ˆ๋‹ค.

์Šคํ…Œ์ด์ง€์˜ ๋ณด์Šค๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€ ํŒจํ„ด์ด ์กด์žฌํ•˜์ฃ .

๊ทธ๋ž˜์„œ ๋ณด์Šค์˜ ์ƒํƒœ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ํŒจํ„ด์œผ๋กœ ๋ณ€ํ™”ํ•  ์ˆ˜ ์žˆ๋„๋ก Enemy Base Class๋ฅผ ์ƒ์†ํ•œ Boss Base Class๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

์ €๋Š” ๋ณด์Šค๊ฐ€ ํ˜„์žฌ ์ฒด๋ ฅ์— ๋”ฐ๋ผ ํŒจํ„ด์„ ๋ณ€ํ™”ํ•˜๋„๋ก ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.


Stat ์„ค์ • ๊ตฌ์กฐ์ฒด

์•ž์„œ ์„ค๋ช…ํ–ˆ๋˜ 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์˜ ์ง„ํญ๊ฐ’์„ ์„ค์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

See Hp()

๋ณด์Šค์—๊ฒ ํ˜„์žฌ ํŒจํ„ด ๋ณ€ํ™” ๋ฐฐ์—ด์— ๋Œ€ํ•œ 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์— ๋Œ€ํ•œ ์„ค๋ช…์ด์˜€์Šต๋‹ˆ๋‹ค.

profile
๊ฒŒ์ž„ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜์–ด๋ณด์ž

0๊ฐœ์˜ ๋Œ“๊ธ€