1. Day40

  • 알고리즘 코드카타
  • C++과 Unreal Engine으로 3D 게임 개발
  • 스탠다드 클래스
  • TA 클래스

2. CH3 - C++과 Unreal Engine으로 3D 게임 개발(Day40)

  • 6번, 7번 과제 해설 코드 복습

3. 알고리즘 코드카타

  • 최소직사각형(초기 코드)
    • sort를 이용 백터들의 원소를 [큰값, 작은값] 으로 전부 정렬한다음 큰값 중의 최대값과 작은값 중의 최대값을 곱한값을 반환
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

int solution(vector<vector<int>> sizes) {
    int maxW = 0;
    int maxH = 0;
    for (auto& v : sizes)
    {
        sort(v.begin(), v.end(), greater<>());
        maxW = max(maxW, v[0]);
        maxH = max(maxH, v[1]);
    }

    return maxW * maxH;
}
  • 최소직사각형(개선코드)
    • sort 대신 max(maxW, max()) 로 배열안의 큰수들중 큰수를 가져오고 max(maxH, min())으로 배열안의 짧은 수중 큰 수를 가져와서 곱함
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

int solution(vector<vector<int>> sizes) {
    int maxW = 0;
    int maxH = 0;
    for (auto& v : sizes)
    {
        maxW = max(maxW, max(v[0], v[1]));
        maxH = max(maxH, min(v[0],v[1]));
    }

    return maxW * maxH;
}

4. 스탠다드 클래스

  • 컴퓨터 구조를 알아야 하는 이유
  • 데이터의 표현 - 비트와 인코딩
  • 소스코드와 명령어

5. TA 클래스

  • 렌더링 파이프라인
  • 렌더링 파이프라인 흐름 정리
CPU (준비)
├── 메시, 텍스처, 셰이더 등 리소스 로드
├── 어떤 오브젝트를 그릴지 결정
└── GPU한테 "렌더링" 명령 (Draw Call)
        ↓
GPU (렌더링 파이프라인 실행)
├── Input Assembler (정점 데이터 조립)
├── Vertex Shader (좌표 변환) ← Local→World→View→Clip 
├── Rasterizer (삼각형 → 픽셀) ← Clipping, NDC, Screen 변환 
├── Pixel Shader (픽셀 색상 계산)
└── Output Merger (최종 출력)
        ↓
Frame Buffer → 모니터 출력

Local Space
    ↓ Model Matrix (월드 배치)
World Space  
    ↓ View Matrix (카메라 기준 정렬)
View Space
    ↓ Projection Matrix (Frustum 정의 + w에 깊이 저장)
Clip Space
    ↓ Clipping (시야 밖 잘라냄) ← GPU가 자동 처리
    ↓ w로 나누기 (원근감 적용)
NDC (-1 ~ 1)
    ↓ Viewport Transform (해상도에 맞게)
Screen Space (픽셀 좌표)
  • 최종 Defferd Rendering 흐름 정리
CPU (준비)
├── 메시, 텍스처, 셰이더 등 리소스 로드
├── 어떤 오브젝트를 그릴지 결정
└── GPU한테 "렌더링" 명령 (Draw Call)
        ↓
========================================
   Deferred 렌더링 시작
========================================
        ↓
GPU 파이프라인(렌더링 파이프라인) 1회차: Geometry Pass
├── Input Assembler (정점 데이터 조립)
├── Vertex Shader (좌표 변환) ← Local→World(Model)→View(View)→Clip(Projection)
├── Rasterizer (삼각형 → 픽셀) ← Clipping, NDC, Screen 변환
├── Pixel Shader (표면 속성 계산)
└── Output → G-Buffer에 저장 (화면 출력 X)
        ↓
G-Buffer (여러 텍스처)
├── Diffuse (기본 색)
├── Normal (법선)
├── Metallic / Roughness
├── Specular
└── Depth (깊이)
        ↓
GPU 파이프라인(렌더링 파이프라인) 2회차: Lighting Pass
├── Input Assembler (화면 전체 quad)
├── Vertex Shader (단순 좌표 전달)
├── Rasterizer (픽셀화)
├── Pixel Shader (G-Buffer 읽고 조명 계산)
└── Output → 중간 렌더 타겟에 저장
        ↓
GPU 파이프라인(렌더링 파이프라인) 3회차: Post Process
├── Input Assembler (화면 전체 quad)
├── Vertex Shader (단순 좌표 전달)
├── Rasterizer (픽셀화)
├── Pixel Shader (블룸, 색보정, SSAO 등)
└── Output Merger (최종 출력)
        ↓
Frame Buffer → 모니터 출력

6. 다음주 : CH3 강의 학습, 알고리즘 문제 집중 CS50x 2주차 진행, 베이직 실전 클래스 과제 진행

1. Day39

  • 알고리즘 코드카타
  • C++과 Unreal Engine으로 3D 게임 개발
  • 베이직 실전 클래스

2. CH3 - C++과 Unreal Engine으로 3D 게임 개발(Day39)

  • [7번 과제] Pawn 클래스로 3D 캐릭터 만들기(제출)
    • Tick 사용 false, Tick() 함수 삭제
    • 해설 세션
  • [8번 과제] 게임 루프 및 UI 재설계하기 발제
    • 과제 발제 2월 3일 까지 제출

3. 알고리즘 코드카타

  • 삼총사
    • 3중 for문으로 모든 3개 원소를 조합하는 모든 경우의 수를 체크 후 0이 되는 경우 answer++
#include <string>
#include <vector>

using namespace std;

int solution(vector<int> number) {
    int answer = 0;
    for (int i = 0; i < number.size() - 2; i++)
    {
        for (int j = i + 1; j < number.size() - 1; j++)
        {
            for (int k = j + 1; k < number.size(); k++)
            {
                if (number[i] + number[j] + number[k] == 0)
                {
                    answer++;
                }
            }
        }
    }
    return answer;
}
  • 크기가 작은 부분 문자열(초기 코드)
    • string s에 부분 문자열을 for 문으로 추가하고 s ≤ p 면 answer++
#include <string>
#include <vector>

using namespace std;

int solution(string t, string p) {
    int answer = 0;
    int l = p.size();

    for (int i = 0; i <= t.size() - l; ++i)
    {     
        string s = "";

        for (int j = i; j < i + l; ++j)
        {
            s += t[j];
        }

        if (s <= p)
            answer++;
    }
    return answer;
}
  • 크기가 작은 부분 문자열(개선 코드)
    • string s에 t의 부분 문자열을 substr로 추가하고 s ≤ p 면 answer++
#include <string>
#include <vector>

using namespace std;

int solution(string t, string p) {

    int answer = 0;
    int l = p.size();

    for (int i = 0; i <= t.size() - l; ++i)
    {
        string s = t.substr(i, l);

        if (s <= p)
            answer++;
    }
    return answer;
}

4. 베이직 실전 클래스

- 언리얼엔진, UCLASS와 게임의 구성
- [과제 - 01/28(수) 제출] AGameModeBase, UGameInstance, AGameState, APlayerState, AHUD, APlayerController 객체들을 선언하고 엔진 내부 분석해서 어떻게 활용할지 리포트 작성

5. 내일 계획 : CH3 강의 학습, 알고리즘 문제 집중 CS50x 2주차 진행, 베이직 실전 클래스 과제 진행

1. Day38

  • 알고리즘 코드카타
  • C++과 Unreal Engine으로 3D 게임 개발
  • 스탠다드 클래스
  • Collision & Trace 세션

2. CH3 - C++과 Unreal Engine으로 3D 게임 개발(Day38)

  • Chapter 3 C++과 Unreal Engine으로 3D 게임 개발(2-3)
  • [7번 과제] Pawn 클래스로 3D 캐릭터 만들기
    • 코드 정리 및 최적화
      • SetSimulatePhysics 생성자에서 한번만 처리, Input값 const 활용(수정방지)
// Sets default values
AMyCharacter::AMyCharacter()
{
     // Set this pawn to call Tick() every frame.
    PrimaryActorTick.bCanEverTick = true;

    // 캡슐(루트 컴포넌트)
    CapsuleComp = CreateDefaultSubobject<UCapsuleComponent>(TEXT("CapsuleComp"));
    RootComponent = CapsuleComp;
    CapsuleComp->SetSimulatePhysics(false);
    // 메시
    MeshComp = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("MeshComp"));
    MeshComp->SetupAttachment(RootComponent);
    MeshComp->SetSimulatePhysics(false);
    // 스프링 암
    SpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArmComp"));
    SpringArmComp->SetupAttachment(RootComponent);
    // 카메라
    CameraComp = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComp"));
    CameraComp->SetupAttachment(SpringArmComp);
}

void AMyCharacter::Move(const FInputActionValue& Value)
{
    // 키보드 입력값 X, Y 2D 벡터값으로 저장
    const FVector2D MoveInput = Value.Get<FVector2D>();
    // Tick밖에서 DeltaTime을 쓰는 방식
    const float DeltaTime = GetWorld()->GetDeltaSeconds();
    // 로그 출력
    if (IsValid(GEngine))
    {
        GEngine->AddOnScreenDebugMessage(-1, 0.f, FColor::Red, FString::Printf(TEXT("X: %f, Y: %f"), MoveInput.X, MoveInput.Y));
    }
    // Move 구현
    const FVector Movement = FVector(MoveInput.X, MoveInput.Y, 0.f) * MoveSpeed * DeltaTime;
    AddActorLocalOffset(Movement);
}

void AMyCharacter::Look(const FInputActionValue& Value)
{
    // 마우스 입력값 X, Y 2D 벡터값으로 저장
    const FVector2D MouseInput = Value.Get<FVector2D>();
    // Tick밖에서 DeltaTime을 쓰는 방식
    const float DeltaTime = GetWorld()->GetDeltaSeconds();

    // Look 구현
    // YawRotation 적용
    const FRotator YawRotation = FRotator(0.f, MouseInput.X * LookSensitivity * DeltaTime, 0.f);
    AddActorLocalRotation(YawRotation);
    //PitchRotation 적용 Pawn은 그대로 SpringArmComp의 Pitch값만 회전
    FRotator ArmRotation = SpringArmComp->GetRelativeRotation();
    ArmRotation.Pitch = FMath::Clamp(ArmRotation.Pitch - MouseInput.Y * LookSensitivity * DeltaTime, -80.f, 80.f);
    SpringArmComp->SetRelativeRotation(ArmRotation);

    // 로그 출력
    if (IsValid(GEngine))
    {
        GEngine->AddOnScreenDebugMessage(-1, 0.f, FColor::Red, FString::Printf(TEXT("X: %f, Y: %f"), MouseInput.X, MouseInput.Y));
    }
}

3. 알고리즘 코드카타

  • 3진법 뒤집기(초기 코드)
    • 입력 갑 n을 3진법으로 바꾸는 과정에 sting으로 변환(자동으로 뒤집힘) 다시 for문을 이용해 10진법으로 변환
#include <string>
#include <vector>

using namespace std;

int solution(int n) {
    string s;
    int answer;
    while (n != 0)
    {
        int temp = n % 3;
        s.push_back(temp + '0');
        n /= 3;
    }

    int base = 1;

    for (int i = s.size() - 1; i >= 0; --i)
    {
        answer += (s[i] - '0') * base;
        base *= 3;
    }

    return answer;
}
  • 3진법 뒤집기(개선 코드)
    • string을 stoi로 다시 10진법으로 int값으로 바꾸는 과정에서 stoi함수의 변환 기능이용
#include <string>
#include <vector>

using namespace std;

int solution(int n) {
    string s;
    int answer;
    while (n != 0)
    {
        int temp = n % 3;
        s.push_back(temp + '0');
        n /= 3;
    }

    answer = stoi(s, nullptr, 3);

    return answer;
}
  • 이상한 문자 만들기(초기 코드)
    • count가 문자열의 인덱스로 1부터 시작해 count % 2 ≠ 0(홀수) 이면 대문자 짝수이면 소문자로 변환 공백을 만나면 1로 초기화
    • ctype.h 헤더를 가져와 홀수면 toupper() 함수로 대문자 변환 짝수면 tolower()함수로 소문자 변환
#include <string>
#include <vector>
#include <ctype.h>

using namespace std;

string solution(string s) {
    string answer = "";
    int count = 1;
    for (auto& c : s)
    {
        if (count % 2 != 0)
        {
            answer.push_back(toupper(c));
        }
        else
        {
             answer.push_back(tolower(c));
        }
        count++;
        if (c == ' ')
        {
            count = 1;
        }
    }
    return answer;
}
  • 이상한 문자 만들기(개선 코드)
    • string answer 를 따로 두지않고 입력받은 s 문자열을 수정한 다음 s 를 반환
    • 기존의 공백 체크, 문자열 수정 입력, count 수정 등을 매번 다 하지않고 공백이라면 count = 0만 수행 나머지는 else안에 구현해 넘어감
    • else 부분의 문자열의 홀수 짝수 문자를 대소문자 변환하여 다시 입력해주는 코드를 삼항연산자 c = (count % 2 == 0) ? toupper(c) : tolower(c)로 수정해도 코드 자체는 줄어드나 명시적으로 표현해주는 것이 좋을 것 같아 유지함
    • 문자에서 문자열의 0번째는 짝수 취급이라 대문자 변환이라 했으니 조건을 다시 수정하고 count = 0 부터 시작하도록 수정
#include <string>
#include <vector>
#include <cctype>  

using namespace std;

string solution(string s) {
    int count = 0;
    for (auto& c : s)
    {
        if (c == ' ')
        {
            count = 0;
        }
        else
        {
            if (count % 2 == 0)
            {
                c = toupper(c);
            }
            else
            {
                c = tolower(c);
            }
            count++;
        }



    }
    return s;
}

4. Collision & Trace 세션

  • Collision & Trace 기초
  • 라인트레이스(발사), 한 점 판정(아이템 인터랙트) 구현

5. 스탠다드 클래스

  • 간단한 OT(커리큘럼 및 과제 관련)

6. 내일 계획 : CH3 강의 학습, 알고리즘 문제 집중 CS50x 2주차 진행, 과제6 & 과제7 제출

+ Recent posts