[UE5] ShootWonban #3 - Stage 1 최고 스코어 관리 및 총기 시스템 구현 완료

ChangJin·2024년 8월 12일
0

Unreal Engine5

목록 보기
97/114
post-thumbnail

2024.08.12

이번 글에서는 ShootWonban 게임의 Stage 1을 완성한 내용을 정리합니다. 최고 스코어 관리 방법과 총기 시스템 구현에 대한 상세 설명을 다룹니다. 게임 오버 처리와 관련된 UI 및 전체 게임 개발 과정을 간략하게 정리합니다.


github
https://github.com/ChangJin-Lee/ShootWonban

1. Stage 1 개요

Stage 1에서는 기본적인 게임 플레이 메커니즘을 완성했습니다. 원반이 던져지고 플레이어가 이를 맞추면 점수가 증가하며, 게임 오버 시 GameOver 위젯이 표시됩니다. 게임 플레이 도중의 점수는 최고 스코어로 저장되며, 총기 시스템을 통해 플레이어가 원반을 맞출 수 있도록 구현했습니다.

2. 최고 스코어 관리

최고 스코어는 플레이어의 게임 기록을 유지하기 위해 매우 중요합니다. 이를 위해 SaveGame 클래스를 사용하여 스코어를 저장하고 불러오는 기능을 구현했습니다.

코드 예시: 최고 스코어 저장 및 불러오기

// ShootWonbanSaveGame.h
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/SaveGame.h"
#include "ShootWonbanSaveGame.generated.h"

UCLASS()
class SHOOTWONBAN_API UShootWonbanSaveGame : public USaveGame
{
    GENERATED_BODY()

public:
    UShootWonbanSaveGame();

    UPROPERTY(VisibleAnywhere, Category = "Score")
    int32 HighScore;

    UPROPERTY(VisibleAnywhere, Category = "Score")
    TArray<int32> StageClearScore;
};

// ShootWonbanSaveGame.cpp
#include "ShootWonbanSaveGame.h"

UShootWonbanSaveGame::UShootWonbanSaveGame()
{
    HighScore = 0;
    StageClearScore = {10, 15, 20};
}

// ShootWonBanPlayerController.cpp
void AShootWonBanPlayerController::SaveHighScore(int32 Score)
{
    UShootWonbanSaveGame* SaveGame = Cast<UShootWonbanSaveGame>(UGameplayStatics::CreateSaveGameObject(UShootWonbanSaveGame::StaticClass()));

    if (SaveGame)
    {
        SaveGame->HighScore = Score;
        UGameplayStatics::SaveGameToSlot(SaveGame, TEXT("WonbanScoreSlot"), 0);
    }
}

int32 AShootWonBanPlayerController::LoadHighScore()
{
    if (UGameplayStatics::DoesSaveGameExist(TEXT("WonbanScoreSlot"), 0))
    {
        UShootWonbanSaveGame* LoadGame = Cast<UShootWonbanSaveGame>(UGameplayStatics::LoadGameFromSlot(TEXT("WonbanScoreSlot"), 0));

        if (LoadGame)
        {
            return LoadGame->HighScore;
        }
    }

    return -1;
}
  • UShootWonbanSaveGame: 게임의 최고 스코어와 각 스테이지의 클리어 점수를 관리하는 클래스입니다.
  • SaveHighScore: 새로운 점수를 최고 스코어로 저장합니다.
  • LoadHighScore: 저장된 최고 스코어를 불러옵니다.

3. 총기 시스템 구현

게임 내에서 총기를 관리하는 시스템을 구현하여 플레이어가 원반을 맞출 수 있도록 했습니다. 플레이어는 총기를 사용해 원반을 맞출 수 있으며, 총기의 탄약이 줄어드는 방식을 구현했습니다.

코드 예시: 총기 시스템

// ShootWonbanCharacter.h
UCLASS()
class SHOOTWONBAN_API AShootWonbanCharacter : public ACharacter
{
    GENERATED_BODY()

public:
    AShootWonbanCharacter();

    UFUNCTION(BlueprintCallable, Category = "Weapon")
    void Fire();

private:
    int32 CurrentAmmo;
    int32 MaxAmmo;
};

// ShootWonbanCharacter.cpp
AShootWonbanCharacter::AShootWonbanCharacter()
{
    MaxAmmo = 30;
    CurrentAmmo = MaxAmmo;
}

void AShootWonbanCharacter::Fire()
{
    if (CurrentAmmo > 0)
    {
        CurrentAmmo--;
        // 총알 발사 로직
    }
}
  • Fire: 탄약이 남아 있는지 확인하고 남아있다면 총알을 발사합니다.

4. GameOver 위젯 생성 및 UI 처리

게임이 종료되었을 때 GameOver 위젯을 생성하여 결과를 표시하고, 플레이어가 결과를 확인할 수 있도록 했습니다.

코드 예시: GameOver 위젯 생성

void AShootWonBanPlayerController::CreateGameOverWidget()
{
    GameOverWidget = CreateUIWidget(GameOverWidgetClass);
    
    APlayerController* PlayerController = GetWorld()->GetFirstPlayerController();
    
    if (PlayerController)
    {
        FInputModeUIOnly InputMode;
        PlayerController->SetInputMode(InputMode);
        PlayerController->bShowMouseCursor = true;
    }
}

UUserWidget* AShootWonBanPlayerController::CreateUIWidget(TSubclassOf<UUserWidget> WidgetClass)
{
	if(WidgetClass)
	{
		UUserWidget* Widget = CreateWidget<UUserWidget>(GetWorld(), WidgetClass);

		if(Widget && GetCurrentStageName() != FString("MainMenu"))
		{
			Widget->AddToViewport();
			return Widget;
		}
	}
	return nullptr;
}
  • CreateGameOverWidget: 게임 종료 시 GameOver 위젯을 생성하여 화면에 표시하고, UI 전용 입력 모드로 전환하여 마우스 커서를 표시했습니다.

5. 에임 시스템 구현

ShootWonban 게임에서는 정밀한 사격을 위해 조준 기능을 추가했습니다. 플레이어가 마우스 우클릭을 통해 조준을 시작하면 화면이 확대되며, 이를 통해 더욱 정확하게 사격할 수 있습니다.

코드 예시: 에임 기능

void AShootWonBanCharacter::Aim()
{
    AimTimeline.Play();
}

void AShootWonBanCharacter::CancelAim()
{
    AimTimeline.Reverse();
}

void AShootWonBanCharacter::UpdateZoom(float Value)
{
    float TargetFOV = FMath::Lerp(DefaultFOV, ZoomedFOV, Value);
    FirstPersonCameraComponent->SetFieldOfView(TargetFOV);
}
  • Aim / CancelAim: 플레이어가 조준을 시작하거나 종료할 때 타임라인을 통해 FOV를 조절합니다.
  • UpdateZoom: 조준 중 화면 확대를 부드럽게 처리하여 보다 정밀한 사격을 가능하게 합니다.

6. 무기 전환 시스템 구현

플레이어는 1번무기, 2번무기를 전환하며 사용할 수 있도록 구현했습니다. 숫자 키 1번, 2번을 이용해 무기를 변경할 수 있으며, 각 무기는 고유한 특성을 가지고 있습니다.

코드 예시: 무기 전환

void AShootWonBanCharacter::SelectWeaponSlot1()
{
    if (CurrentWeaponIndex != 0)
    {
        ChangeWeaponState(CurrentWeaponIndex, 0);
    }
}

void AShootWonBanCharacter::SelectWeaponSlot2()
{
    if (CurrentWeaponIndex != 1 && Weapons.Num() >= 2)
    {
        ChangeWeaponState(CurrentWeaponIndex, 1);
    }
}

void AShootWonBanCharacter::ChangeWeaponState(int32 CurrentIndex, int32 NewIndex)
{
    if (CurrentWeapon == nullptr)
    {
        return;
    }

    Weapons[CurrentIndex]->SetActorHiddenInGame(true);
    Weapons[NewIndex]->SetActorHiddenInGame(false);
    CurrentWeapon = Weapons[NewIndex];
    CurrentWeaponIndex = NewIndex;
}
  • SelectWeaponSlot1 / SelectWeaponSlot2: 플레이어가 선택한 무기를 활성화하고 전환합니다.
  • ChangeWeaponState: 현재 무기를 비활성화하고, 새로운 무기를 활성화합니다.

7. 전체 게임 개발 요약

ShootWonban 게임의 Stage 1 개발은 다음과 같은 주요 단계를 거쳐 완료되었습니다:

  • 원반 스폰 및 이동: 원반이 포물선을 그리며 이동하도록 타임라인을 사용하여 구현했습니다.
  • 충돌 처리: 원반이 총에 맞으면 점수를 올리고, 파괴되도록 했습니다.
  • 최고 스코어 관리: 플레이어의 최고 점수를 SaveGame 클래스를 사용하여 저장하고 관리했습니다.
  • 총기 시스템 구현: 플레이어가 사용할 수 있는 총기의 탄약 관리 기능을 추가하고 총기를 전환할 수 있게 만들었습니다.
  • 에임 시스템 구현: 조준 기능을 통해 정밀한 사격을 가능하게 했습니다.
  • GameOver 처리: 게임이 종료되었을 때 GameOver 위젯을 생성하고, UI 모드로 전환하여 플레이어가 결과를 확인할 수 있도록 했습니다.

이번 Stage 1의 완성으로 ShootWonban 게임의 기본적인 메커니즘이 완성되었습니다. 다음 스테이지에서는 다른 맵을 추가할 계획이고, 게임의 전반적인 완성도를 높일 수 있는 작업들을 진행할 예정입니다.


이 글이 ShootWonban 게임의 개발 과정을 이해하는 데 도움이 되길 바라며, 다음 단계의 프로젝트에서도 이러한 경험이 유용하게 활용될 수 있기를 기대합니다. 피드백이나 질문이 있으면 언제든지 남겨주세요!

profile
게임 프로그래머

0개의 댓글