프로그래밍 공부

전체 글 700

카테고리 설명
프로그래밍 공부하는 블로그
  • ImageAiCon PP진행중인 작업프리뷰 로드아웃 제작중알고리즘 학습중...https://inradestrt.tistory.com/655 진행 예정 작업(예상)Unreal의 ImageAI공부하기CNN알고리즘 다시 복기하기알고리즘 선별( 현 예상안 으로는,DQN알고리즘 사용예정)알고리즘 관련 강의 학습( 자본이 준비되면 강의학습을 진행하며 정리사항 정리예정)Unreal ImageRetargeting 코드제작언리얼 함수 상으로 지정된 카메라의 타겟뷰를 이미지값으로 저장 반환하는 방식이 존재함.TCP방식으로 데이터 통신처리를 진행TensorFlow를 사용하여 전달받은 이미지로 학습 알고리즘 연산.연산결과를 다시 언리얼로 전달하여 학습된 데이터를 갱신.4번과 3번을 반복학습결과확인 후 재학습 5와 6을 원하는..

  • ImageAiCon PP진행중인 작업프리뷰 로드아웃 제작중 진행 예정 작업(예상)Unreal의 ImageAI공부하기Unreal ImageRetargeting 코드제작AI노드 재정렬노드기준 가중치수식 제작ViewTarget 에 대한 AI의 가중치학습학습결과확인 후 재학습 5와 6을 원하는 AI행동패턴이 나타날때까지 반복   완료된 작업

  • 목표점상점 구매 잠금효과 재정리카드 UI를 좀 더 보기 편하게 정리하기상점 구매 잠금효과 재정리 전에 만들어놓았던, 스테이지 세이브 데이터의 항목에 Shop의 데이터를 끼워넣고 로드만 해주면 되는 상황이라 큰 문제는 발생하지 않았다.  개선점 Load시, 비어있는 노드에는 새 카드 노드에서 객체를 호출해야 하는데. 비어있는 노드로 호출된다. 비어있을 경우, 로드할 때 새 카드를 로드하게 바꾸어야한다.카드 UI를 좀 더 보기 편하게 정리하기 UI를 재작업하였다. 초기에 작업했던 카드 UI라 오차가 많고 난잡하게 작성되어있어서 거의 새로 만드는 수준으로 제작하였다. 개선점카드의 FaceImage를 설정하여 종족이나 임의의 카드 표시 이미지를 띄워야한다.진행중인 작업0. 디테일화 ( 베이스를 기반으로 스킬, ..

  • 문제 설명두 수의 최소공배수(Least Common Multiple)란 입력된 두 수의 배수 중 공통이 되는 가장 작은 숫자를 의미합니다. 예를 들어 2와 7의 최소공배수는 14가 됩니다. 정의를 확장해서, n개의 수의 최소공배수는 n 개의 수들의 배수 중 공통이 되는 가장 작은 숫자가 됩니다. n개의 숫자를 담은 배열 arr이 입력되었을 때 이 수들의 최소공배수를 반환하는 함수, solution을 완성해 주세요. 제한 사항arr은 길이 1이상, 15이하인 배열입니다.arr의 원소는 100 이하인 자연수입니다.입출력 예arrresult[2,6,8,14]168[1,2,3]6문제 해설 최소공배수의 성질을 응용하자. 최소값의 최소공배수를 구해봐도 최댓값이 성립하지 않으면 최소공배수가 성립할 수 없다는 점을 기..

  • N진수 게임튜브가 활동하는 코딩 동아리에서는 전통적으로 해오는 게임이 있다. 이 게임은 여러 사람이 둥글게 앉아서 숫자를 하나씩 차례대로 말하는 게임인데, 규칙은 다음과 같다. 숫자를 0부터 시작해서 차례대로 말한다. 첫 번째 사람은 0, 두 번째 사람은 1, … 열 번째 사람은 9를 말한다.10 이상의 숫자부터는 한 자리씩 끊어서 말한다. 즉 열한 번째 사람은 10의 첫 자리인 1, 열두 번째 사람은 둘째 자리인 0을 말한다.이렇게 게임을 진행할 경우,0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 0, 1, 1, 1, 2, 1, 3, 1, 4, …순으로 숫자를 말하면 된다. 한편 코딩 동아리 일원들은 컴퓨터를 다루는 사람답게 이진수로 이 게임을 진행하기도 하는데, 이 경우에는0, 1, 1,..

  • 무기 객체에 애니메이션을 적용하고, 상태에 따라 애니메이션을 실행하게 할 수 있다.HUD를 띄우고, 조준점을 표시할 수 있다.HUD의 조준점과 총기의 방향Rotation을 연동할 수 있다.무기 애니메이션 적용. 무기객체 또한 엑터를 상속받아 동작하는만큼, 임의의 ABP를 배정하여 상태에 따라 애니메이션을 실행하게 조정할 수 있다.WeaponActor#pragma once#include "CoreMinimal.h"#include "Datas/WeaponDatas.h"#include "GameFramework/Actor.h"#include "Interface/IInteract.h"#include "BaseWeapon.generated.h"enum class EFireMode : uint8;/* * */cl..

작성일
2024. 6. 6. 21:49
작성자
WDmil
728x90

ImageAiCon PP

진행중인 작업

프리뷰 로드아웃 제작중

알고리즘 학습중...

https://inradestrt.tistory.com/655

 

진행 예정 작업
(예상)

  1. Unreal의 ImageAI공부하기
    1. CNN알고리즘 다시 복기하기
    2. 알고리즘 선별( 현 예상안 으로는,DQN알고리즘 사용예정)
    3. 알고리즘 관련 강의 학습( 자본이 준비되면 강의학습을 진행하며 정리사항 정리예정)
  2. Unreal ImageRetargeting 코드제작
    1. 언리얼 함수 상으로 지정된 카메라의 타겟뷰를 이미지값으로 저장 반환하는 방식이 존재함.
    2. TCP방식으로 데이터 통신처리를 진행
    3. TensorFlow를 사용하여 전달받은 이미지로 학습 알고리즘 연산.
    4. 연산결과를 다시 언리얼로 전달하여 학습된 데이터를 갱신.
    5. 4번과 3번을 반복
  3. 학습결과확인 후 재학습
  4.  5와 6을 원하는 AI행동패턴이 나타날때까지 반복

목표

  1. TensorFlow를 사용하여 알고리즘이 동작하는지 직접적인 확인을 진행.
  2. TensorFlow 를 사용하지 않고, 스스로의 C++코드로 알고리즘 함수 구현부를 직접 제작하여 사용하는것
    (파이썬만으로 k means clustering를 구현하였을 때, 구현객체가 C++의 연산처리속도를 따라잡지 못하는 상황이 있었음)
  3. UI관련 제작방식은 C#으로, 함수부는 DLL파일로 포팅하여 언리얼 엔진에 집어넣기.

완료된 작업

728x90

'작업사항 정리 > UnrealC++' 카테고리의 다른 글

UnrealC++ PP 20240618_6  (0) 2024.06.18
UnrealC++ PP 20240614_5  (0) 2024.06.14
UnrealC++ PP 20240609_4  (1) 2024.06.09
UnrealC++ PP 20240605_2  (0) 2024.06.05
UnrealC++ PP 20240603_1  (1) 2024.06.03
작성일
2024. 6. 5. 01:19
작성자
WDmil
728x90

ImageAiCon PP

진행중인 작업

프리뷰 로드아웃 제작중

 

진행 예정 작업
(예상)

  1. Unreal의 ImageAI공부하기

  2. Unreal ImageRetargeting 코드제작
  3. AI노드 재정렬
  4. 노드기준 가중치수식 제작

  5. ViewTarget 에 대한 AI의 가중치학습
  6. 학습결과확인 후 재학습
  7.  5와 6을 원하는 AI행동패턴이 나타날때까지 반복

 

 

 

완료된 작업

728x90

'작업사항 정리 > UnrealC++' 카테고리의 다른 글

UnrealC++ PP 20240618_6  (0) 2024.06.18
UnrealC++ PP 20240614_5  (0) 2024.06.14
UnrealC++ PP 20240609_4  (1) 2024.06.09
UnrealC++ PP 20240606_3  (0) 2024.06.06
UnrealC++ PP 20240603_1  (1) 2024.06.03
작성일
2024. 6. 5. 01:14
작성자
WDmil
728x90

 

목표점

  1. 상점 구매 잠금효과 재정리
  2. 카드 UI를 좀 더 보기 편하게 정리하기

상점 구매 잠금효과 재정리

 

전에 만들어놓았던, 스테이지 세이브 데이터의 항목에 Shop의 데이터를 끼워넣고 로드만 해주면 되는 상황이라 큰 문제는 발생하지 않았다.

상점에서 잠금처리가 이루어졌을 경우, 잠금된 카드만 세이브로 넘겨준다.

 

Load할 때는 다른 상점 존 로드할때와 같은 방식으로 로드한다.
LockEvnet는 잠금시, OnCard가 있을 경우 해당 노드를 잠가버린다.

 

개선점

 

Load시, 비어있는 노드에는 새 카드 노드에서 객체를 호출해야 하는데. 비어있는 노드로 호출된다. 비어있을 경우, 로드할 때 새 카드를 로드하게 바꾸어야한다.


카드 UI를 좀 더 보기 편하게 정리하기

 

UI를 재작업하였다.

 

초기에 작업했던 카드 UI라 오차가 많고 난잡하게 작성되어있어서 거의 새로 만드는 수준으로 제작하였다.

 

개선점

카드의 FaceImage를 설정하여 종족이나 임의의 카드 표시 이미지를 띄워야한다.


진행중인 작업

0. 디테일화 ( 베이스를 기반으로 스킬, 카드, 캐릭터, 적, 맵 추가작업 )

 

진행 예정 작업

NULL!!

 

완료된 작업

1. 캐릭터 베이스 구현

 

2. 베이스 구현

2.1 무기 베이스 구현

2.2 카드 베이스 구현

2.2.1 카드의 이동 에 따른 캐릭터 이동 구현

2.2.2 카드 내부의 객체 UI 세부출력

2.3 스킬 베이스 구현

2.3.1 카드 업그레이드 스킬 구현

 

3. 플레이어 상호작용 구현

 

4. 스테이지 이동 구현

4.1 스테이지 간 저장데이터 Save&Load구현

4.2 플레이어 데이터 세이브 구현

 

5. 스테이지 셀렉트 구현

5.1 스테이지 이벤트 베이스 구현( 이벤트는 보스를 제외하면 무작위 여야한다.

[Battle Event, Boss Event, Bonefit Event] )

5.2 스테이지 무작위 배치 구현 ( 규칙성 무작위, 다음 노드는 전 노드배열과 사이즈가 같거나 더 커야한다. )

5.3 스테이지 무작위 간선연결 구현 (규칙성 무작위, Self 노드는 항상 연결된 노드가 존재해야 한다. [고립성 배제])

5.4 플레이어의 노드이동 & 이벤트 처리 구현

5.5 플레이어의 시작시 스테이지 페이드인 페이드아웃 구현

 

6 상점 구현

 

7. 전투 준비단계 구현

7.1 플레이어와 자원, 카드메니저의 연동구현작업

7.2 상점레벨 업그레이드, 손쉬운 카드정보추가

7.3 카드잠금, 카드 구매&판매연동

 

8.9 세이브 안정화

EXTRA. 세이브데이터 세이브데이터로드 연동, 데이터 연동시 필요사항 추가 기입.

 

9. AI

9.0 공통EQS사용 처리

9.1 스킬 사용 판별여부를 위해, 공격가능한 스킬 데이터를 재정리중

9.2 AI공격행동 처리

 

 

728x90
작성일
2024. 6. 4. 00:51
작성자
WDmil
728x90

문제 설명

두 수의 최소공배수(Least Common Multiple)란 입력된 두 수의 배수 중 공통이 되는 가장 작은 숫자를 의미합니다. 예를 들어 2 7의 최소공배수는 14가 됩니다. 정의를 확장해서, n개의 수의 최소공배수는 n 개의 수들의 배수 중 공통이 되는 가장 작은 숫자가 됩니다. n개의 숫자를 담은 배열 arr이 입력되었을 때 이 수들의 최소공배수를 반환하는 함수, solution을 완성해 주세요.

 

제한 사항

arr은 길이 1이상, 15이하인 배열입니다.

arr의 원소는 100 이하인 자연수입니다.

입출력 예

arr result
[2,6,8,14] 168
[1,2,3] 6

문제 해설

 

최소공배수의 성질을 응용하자.

 

최소값의 최소공배수를 구해봐도 최댓값이 성립하지 않으면 최소공배수가 성립할 수 없다는 점을 기억하자.

 

예시에서 2와 6이 최소공배수를 만족해도,8이 만족할 수 없고, 2 6 8 이 만족해도 14가 만족할 수 없는것 처럼.


첫 번째 시도

#include <string>
#include <vector>
#include <algorithm>

using namespace std;

int solution(vector<int> arr) {
    int answer = 0;
    int maxA = *max_element(arr.begin(), arr.end());

    int i = 1;
    while (true)
    {
        answer = maxA * i;
        bool find = true;
        for (auto& def : arr)
        {
            if (find)
            {
                if (answer % def != 0) find = false;
            }
            else
                break;
        }
        if (find) return answer;
        i++;
    }
}

성공

 

최소공배수의 성질을 생각해서, 최댓값부터 N배수만큼 계속해서 만들고, 가지고있는 배열에 대해 해당 값을 계속해서 for문으로 0이 나타나는지 검사하면 된다.

만약, 한번이라도 false가 나타났다면 실패했다는 의미 임으로 다음 최소공배수를 시도한다.

728x90

'코딩테스트 문제 풀이 > 동적계획법(Dynamic Programming)' 카테고리의 다른 글

연속 부분 수열 합의 개수  (0) 2024.05.23
귤 고르기  (0) 2024.05.22
마법의 엘리베이터  (0) 2024.05.13
인사고과  (0) 2024.05.08
[카카오 인턴] 경주로 건설  (1) 2024.04.27
작성일
2024. 6. 4. 00:28
작성자
WDmil
728x90

 

N진수 게임

튜브가 활동하는 코딩 동아리에서는 전통적으로 해오는 게임이 있다. 이 게임은 여러 사람이 둥글게 앉아서 숫자를 하나씩 차례대로 말하는 게임인데, 규칙은 다음과 같다.

 

숫자를 0부터 시작해서 차례대로 말한다. 첫 번째 사람은 0, 두 번째 사람은 1, … 열 번째 사람은 9를 말한다.

10 이상의 숫자부터는 한 자리씩 끊어서 말한다. 즉 열한 번째 사람은 10의 첫 자리인 1, 열두 번째 사람은 둘째 자리인 0을 말한다.

이렇게 게임을 진행할 경우,

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 0, 1, 1, 1, 2, 1, 3, 1, 4, …

순으로 숫자를 말하면 된다.

 

한편 코딩 동아리 일원들은 컴퓨터를 다루는 사람답게 이진수로 이 게임을 진행하기도 하는데, 이 경우에는

0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, …

순으로 숫자를 말하면 된다.

 

이진수로 진행하는 게임에 익숙해져 질려가던 사람들은 좀 더 난이도를 높이기 위해 이진법에서 십육진법까지 모든 진법으로 게임을 진행해보기로 했다. 숫자 게임이 익숙하지 않은 튜브는 게임에 져서 벌칙을 받는 굴욕을 피하기 위해, 자신이 말해야 하는 숫자를 스마트폰에 미리 출력해주는 프로그램을 만들려고 한다. 튜브의 프로그램을 구현하라.

 

입력 형식

진법 n, 미리 구할 숫자의 갯수 t, 게임에 참가하는 인원 m, 튜브의 순서 p 가 주어진다.

 

  • 2 ≦ n ≦ 16
  • 0 < t ≦ 1000
  • 2 ≦ m ≦ 100
  • 1 ≦ p ≦ m

출력 형식

튜브가 말해야 하는 숫자 t개를 공백 없이 차례대로 나타낸 문자열. , 10~15는 각각 대문자 A~F로 출력한다.

 

입출력 예제

n t m p result
2 4 2 1 "0111"
16 16 2 1 "02468ACE11111111"
16 16 2 2 "13579BDF01234567"

문제 해설

 

임의의 진법으로 객체를 재구성하여 내가 말해야 할 단어를 출력해야 한다.

 

여기서 함정이 있는데, 단어는 항상 한개씩만 넣어야 한다는 점이다.

 

위에서 설명했듯, 10을 말할 때, 1번은 1 2번은 0 을 말하고, 숫자는 11로 넘어간다.

 

이런식으로 연산이 되어야 한다.

 

 

여기에서 우리가 사용해야할 객체를 정리해보자.

 

우선, String을 출력해야 함으로 string.

그리고, 연산과정 상 나온 string 문장을 reverse해야함으로 algorithm

숫자가 한자릿수 이상 나타날 경우 순서대로 말해야 함으로 queue에 숫자들을 전부 밀어넣고 연산해야 할것이다.

 

이제 코드를 작성해보자


첫 번째 시도

#include <string>
#include <iostream>
#include <vector>
#include <algorithm>  
#include <queue>

using namespace std;

void convertToBase(int number, int base, queue<char>& input) 
{
    if (number == 0) {
        input.push('0');
        return;
    }
    string result;

    const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    while (number > 0) 
    {
        int remainder = number % base;
        result += digits[remainder]; 
        number /= base;               
    }

    reverse(result.begin(), result.end());

    for (auto& def : result)
        input.push(def);
}


string solution(int n, int t, int m, int p) {
    string answer = "";
    int now = 0;
    queue<char> numberq;
    while (answer.size() < t)
    {
        for (int i = 1; i <= m; i++) {
            if (numberq.empty())
            {
                convertToBase(now, n, numberq);
                now++;
            }
            if (i == p) answer += numberq.front();

            numberq.pop();
            
        }
    }
    return answer;
}

성공

 

우선, 입력받은 숫자를 임의의 진법으로 재정리할 함수를 구현한다.

 

함수에서는 현재 문자를 while문으로 나머지값을 구하면서. 나머지값에 대한 지정된 숫자값을 넣어 연산하게 된다.

그리고, 나머짓값은 항상 끝값부터 나타남으로 결과값에서 reverse하여 숫자를 거꾸로 해주어야 한다.

 

그 후, 나타난 숫자는string에 저장됨으로 ,queue에 for문으로 한개씩 집어넣으면 된다.

 

아랫 solution에서는 while문으로 현재 지정된 string결과값이 출력사이즈보다 작은지 큰지 확인하고.

작다면 무한반복시킨다.

 

q가 비어있다면 새 숫자를 받아야 함으로. 새 숫자를 받고.

현재 p번째 출력이라면, 출력문장에 넣어야 함으로 answer에 맨 앞 숫자를 집어넣어준다.

 

항상 pop하여 순서마다 숫자를 한개씩 말했음을 명확히 한다.

728x90

'코딩테스트 문제 풀이 > 스텍&큐' 카테고리의 다른 글

주식 가격  (0) 2024.02.15
다리를 지나는 트럭  (0) 2024.02.14
프로세스  (0) 2024.02.08
올바른 괄호  (0) 2024.01.30
기능개발  (0) 2024.01.19
작성일
2024. 6. 3. 19:04
작성자
WDmil
728x90
  1. 무기 객체에 애니메이션을 적용하고, 상태에 따라 애니메이션을 실행하게 할 수 있다.
  2. HUD를 띄우고, 조준점을 표시할 수 있다.
  3. HUD의 조준점과 총기의 방향Rotation을 연동할 수 있다.

무기 애니메이션 적용.

 

무기객체 또한 엑터를 상속받아 동작하는만큼, 임의의 ABP를 배정하여 상태에 따라 애니메이션을 실행하게 조정할 수 있다.


WeaponActor

#pragma once

#include "CoreMinimal.h"
#include "Datas/WeaponDatas.h"
#include "GameFramework/Actor.h"
#include "Interface/IInteract.h"
#include "BaseWeapon.generated.h"

enum class EFireMode : uint8;

/*
 *	
 */

class UArrowComponent;
enum class EItemPositionType : uint8;

UCLASS()
class FTPSGAME_API ABaseWeapon : public AActor, public IInteract
{
	GENERATED_BODY()

protected:
	UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly)
	TObjectPtr<USkeletalMeshComponent> Body;
	
	UPROPERTY(VisibleDefaultsOnly)
	FWeaponAssets Assets;
	
	UPROPERTY(VisibleAnywhere)
	UWeaponDataAsset* MyWeaponData;

	UPROPERTY()
	FTimerHandle FireHandle;

	UPROPERTY(VisibleAnywhere, Category = FireMode, meta=(Bitmask="", BitmaskEnum="/Script/FTPSGame.EFireMode"))
	int32 CanFireMode;

	UPROPERTY(VisibleAnywhere, Category = FireMode)
	int32 CurrentFireMode = 2 ^ EFireMode::Single;

	bool bFire = false;
	bool bEmpty = false;
	
public:	
	ABaseWeapon();

	virtual void Interact(ABaseCharacter* InteractingActor) override;

	void ConversionItem(EItemPositionType Type, EAttachType InHolderType = EAttachType::Handle, USceneComponent* InParentComponent = nullptr);
	void SetCollisionEnable(bool bEnable);
	
	EFireMode GetCurrentFireMode();

	FORCEINLINE UWeaponDataAsset* GetWeaponData()					{ return MyWeaponData; }
	FORCEINLINE void SetWeaponData(UWeaponDataAsset* InWeaponData)  { MyWeaponData = InWeaponData; }

	FORCEINLINE bool IsFire()  const { return bFire;  }
	FORCEINLINE bool IsEmpty() const { return bEmpty; }
	
public:
	UFUNCTION()
	void SpawnProjectile();

	UFUNCTION()
	void SpawnShell();
	
	virtual void Fire();
	virtual void HoldFire();
	virtual void ChangeFireMode();
	
protected:
	virtual void BeginPlay() override;

	void LoadData(EWeaponName Name);
	void SetBody();

	void RotateToCrossHair();
};

 

Weapon의 헤더이다.

 

Fire과 HoldFire, ChangeFireMode를 적용하여 무기객체가 공격상태인지, 멈춤상태인지, 탄약이 없는 상태인지 의 상태변환을 적용할 수 있게 한다.

 

public으로 적용되어 있는, FORCEINLINE bool IsFire(), bool IsEmpty를 통해 현재 발사중인지, 탄약이 부족한지 의 객체상태를 반환받는다.

 

위 함수를 호출하는 주체는, Base_Character를 상속받는 AHero 엑터이다.

void ABaseWeapon::Fire()
{
	bFire = true;
}

void ABaseWeapon::HoldFire()
{
	bFire = false;
}

void ABaseWeapon::ChangeFireMode()
{
	while (true)
	{
		CurrentFireMode = CurrentFireMode << 1;
		if ((CanFireMode & CurrentFireMode) != 0 ||
			CurrentFireMode >= 2 ^ EFireMode::Max)
			break;
	}
	
	CurrentFireMode %= (2 ^ EFireMode::Max) - 2; // None + Max = 2
}

 

객체의 무기상태와 ChangeFireMode를 통해, 무기상태를 변환할 수 있게 한다.

void AHero::BindingDefaultActions(UEnhancedInputComponent* EnhancedInputComponent)
{
	// Jumping
	EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Started, this, &ACharacter::Jump);
	EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping);

	// Moving
	EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AHero::Move);

	// Looking
	EnhancedInputComponent->BindAction(ViewAction, ETriggerEvent::Triggered, this, &AHero::View);
}

void AHero::BindingCombatActions(UEnhancedInputComponent* EnhancedInputComponent)
{
	// Interact
	EnhancedInputComponent->BindAction(*CombatInput.InputActionMap.Find("Interact"), ETriggerEvent::Ongoing,  this, &AHero::Interact);
	EnhancedInputComponent->BindAction(*CombatInput.InputActionMap.Find("Interact"), ETriggerEvent::Canceled, this, &AHero::InteractCanceled);

	// Select Holder
	EnhancedInputComponent->BindAction(*CombatInput.InputActionMap.Find("MainHolder"), ETriggerEvent::Triggered, this, &AHero::SelectMainHolder);
	EnhancedInputComponent->BindAction(*CombatInput.InputActionMap.Find("SubHolder"),  ETriggerEvent::Triggered, this, &AHero::SelectSubHolder);

	// ADS
	EnhancedInputComponent->BindAction(*CombatInput.InputActionMap.Find("AimingDownSight"), ETriggerEvent::Ongoing,   this, &AHero::Aiming);
	EnhancedInputComponent->BindAction(*CombatInput.InputActionMap.Find("AimingDownSight"), ETriggerEvent::Completed, this, &AHero::HipFire);

	// Fire
	EnhancedInputComponent->BindAction(*CombatInput.InputActionMap.Find("Fire"), ETriggerEvent::Started, this, &AHero::Fire);
	EnhancedInputComponent->BindAction(*CombatInput.InputActionMap.Find("Fire"), ETriggerEvent::Completed, this, &AHero::HoldFire);

	// Fire Mode
	EnhancedInputComponent->BindAction(*CombatInput.InputActionMap.Find("ChangeFireMode"), ETriggerEvent::Triggered, this, &AHero::ChangeFireMode);
}

Input키 할당은, Base_Character를 할당받는, Hero에서 키값 할당을 받는다.


ABP설정


CPP로 기본적인 ABP값을 설정해준다. 틱마다 해당 객체를 가지는 무기에서 임의의 값을 가져온다.

#pragma once

#include "CoreMinimal.h"
#include "Animation/AnimInstance.h"
#include "Datas/WeaponDatas.h"
#include "WeaponAnimInstance.generated.h"

class ABaseWeapon;
enum class EFireMode : uint8;

UCLASS()
class FTPSGAME_API UWeaponAnimInstance : public UAnimInstance
{
	GENERATED_BODY()

	UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, meta=(AllowPrivateAccess="true"))
	TObjectPtr<ABaseWeapon> Weapon;

	UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, meta=(AllowPrivateAccess="true"))
	float SingleFirePlayRate;
	
	UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, meta=(AllowPrivateAccess="true"))
	float AutoFirePlayRate;

	UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, meta=(AllowPrivateAccess="true"))
	EFireMode FireMode;

	UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, meta=(AllowPrivateAccess="true"))
	bool bEmpty = false;

	UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, meta=(AllowPrivateAccess="true"))
	bool bFire = false;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta=(AllowPrivateAccess="true"))
	TObjectPtr<UAnimSequence> SingleFireAnimation;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta=(AllowPrivateAccess="true"))
	TObjectPtr<UAnimSequence> AutoFireAnimation;
	
public:
	virtual void NativeInitializeAnimation() override;
	virtual void NativeUpdateAnimation(float DeltaSeconds) override;
};

가져와야 하는 값은 위와 같다.

 

자기자신을 사용하는 무기,

단발 발사속도,

자동발사 속도

발사형태

발사여부

탄여부

그리고 애니메이션들 이다.

#include "Animation/Weapons/WeaponAnimInstance.h"
#include "Actors/BaseWeapon.h"
#include "Datas/Weapon/WeaponDataAsset.h"
#include "Utilities/Helper.h"

void UWeaponAnimInstance::NativeInitializeAnimation()
{
	Super::NativeInitializeAnimation();

	USkeletalMeshComponent* Skel = Cast<USkeletalMeshComponent>(GetOuter());
	Weapon = Cast<ABaseWeapon>(Skel->GetOwner());
}

void UWeaponAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
{
	Super::NativeUpdateAnimation(DeltaSeconds);
	
	if (Weapon == nullptr)
	{
		USkeletalMeshComponent* Skel = Cast<USkeletalMeshComponent>(GetOuter());
		Weapon = Cast<ABaseWeapon>(Skel->GetOwner());
		
		return;
	}

	float RPM = 60 / Weapon->GetWeaponData()->GetRoundPerMinute();
	
	if (SingleFireAnimation)
		SingleFirePlayRate = SingleFireAnimation->GetPlayLength() / RPM;

	if (AutoFireAnimation)
		AutoFirePlayRate = AutoFireAnimation->GetPlayLength() / RPM;
	
	FireMode = Weapon->GetCurrentFireMode();
	
	bFire = Weapon->IsFire();
	bEmpty = Weapon->IsEmpty();
}

 

RPM을 기준으로 FireRate를 정의해준다. 현재 애니메이션이 정의되어있을 때 만, 해당 값을 정의해주면 된다.


ABP 애님그래프 연결

애님 그래프는 위와같이 연결한다.

 

Idle상태 일 때, if값으로 현재 SIngle인지 Auto인지 판별하고 해당 애니메이션을 재생한다.

 

현재 Empty상태일 경우, NeedReload로 이동. Empty상태 애니메이션을 재생한다.

 


Hud띄우기

 

Hud를 제작한다.

 

임의의 코드를 설정할 수도 있음으로, CPP파일로 베이스를 생성하고 해당 CPP를 상속받는 HUD를 제작한다.

 

HUD의 경우 블루프린트 노드로 생성 정의하는것 이 더 효과적임으로 대부분의 작업은 블루프린트 로 진행한다.

 

 

생성한 HUD는 PlayerHudManager시스템을 사용하여 전역적으로 관리해준다.

 


#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "CrossHair.generated.h"

/**
 * 
 */
UCLASS()
class FTPSGAME_API UCrossHair : public UUserWidget
{
	GENERATED_BODY()

	
};

 

HUD를 정의만 해준다.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/HUD.h"
#include "PlayerHUD.generated.h"

class UCrossHair;

/**
 * 
 */
UCLASS()
class FTPSGAME_API APlayerHUD : public AHUD
{
	GENERATED_BODY()

	UPROPERTY()
	TObjectPtr<UCrossHair> CrossHair;

	UClass* CrossHairClass;

public:
	APlayerHUD();

protected:
	virtual void BeginPlay() override;
};

 

Player Hud를 생성해서. 만든 hud를 생성, 관리한다.

#include "Widgets/PlayerHUD.h"

#include "Actors/Characters/Hero/Hero.h"
#include "Blueprint/UserWidget.h"
#include "Kismet/GameplayStatics.h"
#include "Utilities/Helper.h"
#include "Widgets/CrossHair/CrossHair.h"

APlayerHUD::APlayerHUD()
{
	CrossHairClass = Helper::GetClass<UUserWidget>("/Game/Widget/CrossHair/WB_CrossHair");
}

void APlayerHUD::BeginPlay()
{
	Super::BeginPlay();

	AHero* Hero = Cast<AHero>(UGameplayStatics::GetPlayerCharacter(this, 0));
	
	CrossHair = CreateWidget<UCrossHair>(Hero->GetWorld(), CrossHairClass, "Cross Hair");

	CrossHair->AddToViewport(0);
	CrossHair->SetVisibility(ESlateVisibility::Visible);
}

CPP의 생성자에서 Class를 할당해주고, BeginPlay에서 할당된 Class를 생성 Viewport에 추가. Visible처리해준다.

 


위젯 블루프린트는, 캔버스 패널을 사용하여 내부에 3x3공간을 만들고 3x3공간에 각각의 이미지를 배정해준다.

 

이를통해 에임을 구현할 수 있다.

728x90