
에임 오프셋(AimOffsets)플레이어가 정면을 바라보고 사격하면 에임이 정상적이지만,위나 아래를 보고 사격하면 그에 맞게 방향이 돌아가지 않는다.이를 수정하기위해 에임 오프셋을 적용해주자.이는 애니메이션에서 확인할 수 있다. 해당 애니메이션은 additive 애니메이션으로 기존 애니메이션에 더하여 사용된다.따라서 달리는 와중에도 에임 조정이 가능해진다. 이를 위해 AnimGraph에서 해당 에임 오프셋을 배치해주자.그리고 Pitch 값을 180으로 두고 컴파일 하면 위를 바라보는 것을 볼 수 있다. pitch 값을 변수로 승격시켜주고, event graph에서 해당 값을 적용해주자. 기존 Event graph에 더해 너무 길어져서 Sequence 노드를 통해 약가느이 정리를 해주었다.그리고 Get ..

체력 바 게임의 완성도를 추가적으로 높이기 위해 좌측 하단에 체력 바를 만들어주자.기존 HUD를 이용하여 만들어주는데 우리는 progress 바를 사용한다.progress 바에는 퍼센트가 존재하며, 이를 통해 체력을 조절하게 될 것이다. 색상도 원하는 대로 변경해주자. 플레이해보면 크로스헤어와 같이 체력 바도 같이 보인다.하지만 실제 체력과 연동은 되지 않은 상태이므로, 이에 대한 작업을 해주어야 한다. ShooterCharacter 클래스에 체력 퍼센트를 얻기 위한 함수를 선언해주자.블루프린트에서 접근해서 작업할 것 이기에, UFUNCTION으로 선언해준다. 구현 내용은 간단하다.현재 체력 / 최대 체력으로 비율을 구해주면 된다. 이제 이를 연동시켜주어야 하는데, Percent에 Create Bind..

크로스헤어와 HUD지금 총을 발사할 수 는 있지만, 조준점이 잘 보이지 않는다.이를 보완하기 위해 크로스헤러를 추가해주자.이를 위해 위젯을 생성해주자. 해당 위젯에서 텍스트를 통해 + 크로스 헤어를 생성해준다. 이제 해당 위젯을 생성해주어야 한다.크로스헤어는 게임 시작할 때부터 있어야 하므로 BeginPlay 함수 내에 생성해주어야 한다.ShooterPlayerController 클래스에는 BeginPlay 함수가 없으므로 먼저 생성해주자. 그리고 저번에 승리패배 화면과 마찬가지로 구현해주자. 마찬가지로 컴파일하고 할당해주자. 실행해보면 다음과 같이 크로스헤어가 생성되었다.너무 큰 것 같아서 크기를 더 작게 조정해주었다. 크로스헤어는 게임 종료시 필요가 없다.따라서 이겼거나 졌을 때 크로스 헤어를 삭제시..

사운드 공간화사운드에 추가적으로 해주면 좋은 작업이 남아 있는데, 그것은 바로 사운드 공간화이다.현재 사운드는 평면적으로 들리는 상태이며, 이에 헤드폰 같은 걸 사용하여 들어보면 공간감이 느껴지지 않는 것을 알 수 있다. 이는 사운드 큐 디테일 탭의 Attenuation에서 가능하다.Override Attenuation 기능을 활성화하면 관련된 많은 내용들이 새롭게 생기고 해당 내용들을 수정할 수도 있지만, 우리는 따로 에셋을 만들어서 적용할 것이다. 이후 해당 에셋을 통해 값을 수정하게 된다.에셋을 열고 우리가 중점적으로 볼 것을 아래와 같다. Volume은 거리에 따라 소리가 어떻게 들리는 지를 정하게 되며,Spatialization은 공간감을 조절하게 된다. 우선 Volume부터 보면 Attenua..

랜덤화된 사운드 큐현재 사운드가 구현이 되어있긴하지만 단일 사운드로 다소 심심하다.따라서 이번에 여러 사운드로 구성된 언리얼의 사운드 큐 기능을 사용해보게 된다.우선 사운드 탭에서 이를 생성해주자. 이후 우클릭하여 Wave Player를 누르면 할당할 사운드를 고를 수 있다. 그리고 또 우클릭하여 Random 노드를 사용하면 사운드 큐 여러개를 인풋으로 받아서 랜덤으로 재생 시킬 수 있다. 다음은 Modulator 노드이다.해당 노드를 통해 Pitch 값과 Volume을 랜덤하게 적용 시킬 수 있다. 지금은 직접 Wave Player 노드를 통해 사운드를 할당했지만,기존에 있던 사운드 여러개를 클릭하여 한번에 Random으로 묶을 수도 있다. 위와 같이 여러개 선택 후 Random:Multiple WAV..

무기 사운드 이펙트PullTrigger 함수를 리팩토링 해줬으니 사운드를 추가해줄 차례이다.우리가 추가할 사운드는 크게 2가지로, 총 발사 사운드와 히트사운드이다.우선 발사 사운드부터 생성해보자. 우리는 사운드 파일로 SoundWave 타입을 사용하게 된다.언리얼 타입으로는 USoundBase이므로, 헤더에 해당 사운드를 선언해주자. 사운드 생성의 경우 SpawnSoundAttached 함수를 사용한다.해당 함수는 전에 사용했던 SpawnEmitterAttached 함수와 거의 같은 함수로, 해당 함수는 MuzzleFlashSocket 위치에서 MuzzleFlash를 생성하는데 사용했지만 우리는 해당 위치에 사운드를 발생시킬 것이다.따라서 함수의 이름만 방식은 동일하다고 볼 수 있다. 이제 컴파일하고 B..

PullTrigger 리팩터링이제 총기 사운드를 넣어줄 것인데, 이에 앞서서 Gun 클래스에 위치한 PullTrigger 함수를 리팩토링 해줄 것이다.총기 사운드 특성상 해당 함수에 기능을 넣게 되는데, 지금도 해당 함수가 상당히 길기 때문에 가독성을 높이기 위해 미리 작업을 해주자. 우리가 함수로 분리할 부분은 크게 2가지로 Trace하는 내용과 OwnerController를 얻는 부분이다. OwnerController의 경우 Trace 함수에서도 체크가 필요한 부분이기 때문에 우선적으로 구현해주자.PullTrigger 함수 상단에 적었던 내용을 그대로 복사하여 넣고, 해당 OwnerPawn이 nullptr인지 아닌지만 각 함수에서 체크해주게 된다. 이제 Trace 하는 부분이다.해당 함수의 인풋인 H..

승리 조건 계산하기EndGame 함수를 통해 승리 케이스를 구현할 수 있도록 만들었으니,이제 패배 조건과 마찬가지로 승리 조건 또한 구현해주자. 우선 승리 조건은 AI가 모두 죽었을 때이다.따라서 AIController 클래스에서 죽었는지 여부 체크를 위한 IsDead() 함수를 만들어주자. 해당 함수에서 ShooterCharacter2 클래스에서 죽는 조건으로 이미 만들었던 IsDead() 함수를 호출해준다. 그리고 이제 이겼을 때 화면을 제작해주어야 한다.우선 PlayerController 클래스에서 선언해주자. 그리고 bIsWinner 값을 토대로 이겼을 때, 졌을 때를 구분하여 화면을 할당해주자. 이제 컴파일 하고 돌아가서 위젯을 생성해주자.기존 졌을 때 위젯을 복사하여 내용이랑 색깔만 변경해주었..

액터 반복하기현재 플레이어 컨트롤러에 대해서만 GameHadEnded 함수를 호출하고 있다.하지만 AI 에게도 마찬가지로 게임이 종료되었음을 알려줄 필요가 있다.이를 위해서 레벨에 존재하는 모든 컨트롤러에 대해 접근을 할 수 있어야 하는데, TActorRange 템플릿 클래를 통해 하게 된다. 우선 누가 이겼는지 판별을 위해 게임 종료 함수를 새롭게 만들어주자. 그리고 TActorRange를 통해 레벨에 존재하는 컨트롤러를 모두 찾게 된다.템플릿 클래스이므로 템플릿에 목표 대상인 AController를 넣어주고,for 반복문을 통해 모든 컨트롤러에 대해 접근하게 된다. 이후 해당 컨트롤러가 AI인지, 플레이어인지 체크하기 위해 IsPlayerController 함수를 사용하여 판별해주고,해당 함수를 통해..
문제링크 : https://www.acmicpc.net/problem/17291#include using namespace std;typedef long long ll;typedef pair pii;const int MAX = INT_MAX;int N;int dp[20];int main(){ ios_base::sync_with_stdio(0); cin.tie(0); cin >> N; dp[0] = dp[1] = 1; //초기값 for(int i=2; i 기본적으로 매년 분열하므로, dp식을 매번 직전 값에 2배를 해준다.이후 감소되는 케이스를 보면, 짝수년도 4번 분열 + 홀수년도 3번 분열이므로 사실상 짝수년도에서만 분열되었던 값들이 사라지게 되는 것을 알 수 있다. 이에 4번 ..

패배 화면 띄우기지금은 패배시 아무것도 뜨지 않고 5초 후에 레벨이 재시작된다.완성도를 높이기 위해 패배시 화면에 출력될 UI를 만들어보자. 이를 위해 우선 UI 폴더를 생성하고 위젯 블루프린트를 생성하자.그리고 이어서 화면에 띄울 Text를 생성해주자. 텍스트는 우측 디테일 패널을 통해 위치 앵커 설정, 색상, 글씨 크기 등이 조정 가능하다. 이제 해당 위젯을 출력하기 위해 PlayerController 클래스를 통해 해당 위젯을 설정하자.헤더에서는 TSubclassOf 클래스로 위젯을 설정하여 위젯만 할당하도록 범위를 제한해주었다. 이후 CreateWidget() 함수를 통해 위젯을 생성하고, AddToViewport() 함수를 이용하여 화면에 출력하도록 하자. 컴파일 하기에 앞서서 추가로 해야할 작..
문제링크 : https://www.acmicpc.net/problem/17391 #include using namespace std;typedef long long ll;typedef pair pii;const int MAX = INT_MAX;int N, M;int arr[301][301];bool visited[301][301];int dx[] = {0, 1};int dy[] = {1, 0};void bfs(){ queue>q; q.push({0, 0, 0}); visited[0][0] = 1; while(!q.empty()) { auto [y, x, cnt] = q.front(); q.pop(); if(y == N-1 && x == M..

C++에서 타이머 설정하기게임 종료에 대해서 더 구체화를 해보도록하자.기존에 PawnKilled를 통해 폰이 죽었을 시 로그메시지가 뜨도록 했지만, 이번에는 PlayerController에 속한 함수인 GameHasEnded 함수를 통하여 플레이어가 죽었을시 게임이 종료되는 로그메시지를 출력해보도록 하자. 이를 위해 PlayerController를 우선 얻고, 해당 컨트롤러를 통해 GameHadEnded 함수를 호출한다.해당 함수는 해당 플레이어에 대한 포커스 포인터와 bool 값(승패 여부)를 필요로 하는데, 여기서 포커스 기능은 필요없으므로 null로 넘겨준다. 그리고 이제 GameHadEnded 함수를 오버로딩해서 사용하기도하고, 레벨을 다시 시작하는 등의 동작 구현을 위해 PlayerControl..
문제링크 : https://www.acmicpc.net/problem/6571dp = [0 for i in range(1001)]dp[1] = 1dp[2] = 2for i in range(3, 1001) : dp[i] = dp[i-1] + dp[i-2]while(True): a, b = map(int,input().split()) if a == 0 and b == 0 : break cnt = 0 for i in range(1, 1001) : if a 피보나치 계산에 따라 수가 매우 커지므로 python으로 푸는 것이 용이한 문제이다.C++로 풀 경우 문자열로 바꾸어서 계산할 필요가 있다. 이외에는 사전에 피보나치를 dp를 통해 미리 계산해놓고 입력받은..
문제링크 : https://www.acmicpc.net/problem/14607#include using namespace std;typedef long long ll;typedef pair pii;const int MAX = INT_MAX;ll N;int main(){ ios_base::sync_with_stdio(0); cin.tie(0); cin >> N; cout 백준 14606번과 유사하지만 N의 범위 때문에 14606번을 풀었던 점화식을 그대로 사용한다면 메모리 초과가 발생하는 문제이다.참고링크 : https://blob-thinking.tistory.com/386 [백준 14606번] 피자 (Small) (C++)문제링크 : https://www.acmicpc.net/pr..