#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> arr = {1, 2, 3};
int n = arr.size();
// 0부터 2^n - 1까지 부분집합의 모든 경우 탐색
for (int i = 0; i < (1 << n); i++) {
cout << "{ ";
for (int j = 0; j < n; j++) {
if (i & (1 << j)) {
// i번째 원소가 포함되었는지 확인
// bit는 정수지만, 2진수로 보면 비트의 집합
// (1 << j)의 역할: 특정 비트만 체크
// i & (1 << j) != 0 이면 True 이기 때문에 해당 자리 원소 출력
cout << arr[j] << " ";
}
}
cout << "}\n";
}
}
정수 n(1 ≤ n ≤ 100)이 주어질 때, 다음 식을 만족하는 (a, b, c)의 개수를 구하는 문제를 불필요한 중복 제거를 하여 풀어보세요. (제출 + 발표)
a + b^2 + c^3 = n
#include <iostream>
using namespace std;
int main() {
int n = 10000; // 입력값
int count = 0;
for (int b = 1; b * b <= n; b++) { // b^2가 n을 초과하지 않는 범위까지만 탐색
for (int c = 1; b * b + c * c * c <= n; c++) { // b^2 + c^3이 n을 초과하지 않는 범위까지만 탐색
int a = n - (b * b + c * c * c);
if (a >= 1 && a <= 100) { // a가 자연수(1~100) 범위 내에 있어야 유효한 해
count++;
}
}
}
cout << count;
}
오늘도 다름없이 몬스터를 구현에 몰두했습니다. 몬스터 중 은신 스킬을 사용하는 친구를 만들어보자는 계획이 있었는데 잘 다뤄본적이 없는 머티리얼을 조작해야되기 때문에 조금 미루고 있었습니다만.. 오늘 마주하게 됐습니다. 먼저 C++로 작성한 은신 스킬을 담당 컴포넌트를 보겠습니다.
#include "Monster/Component/StealthModeSkillComponent.h"
#include "Monster/Component/MonsterStatComponent.h"
#include "GameFramework/Actor.h"
UStealthModeSkillComponent::UStealthModeSkillComponent()
{
PrimaryComponentTick.bCanEverTick = false;
}
void UStealthModeSkillComponent::BeginPlay()
{
Super::BeginPlay();
}
void UStealthModeSkillComponent::ActivateSkill()
{
if (bIsStealthMode || !IsCooldownOver())
{
UE_LOG(LogTemp, Warning, TEXT("Cooldown not over yet or already in Stealth Mode"));
return;
}
bIsStealthMode = true;
StartCooldown();
PlaySkillMontage();
BoostSpeed(SpeedMultiplier);
// 블루프린트에서 머티리얼 Dissolve 적용
OnStealthActivated();
// StealthTime 후 속도 복구 타이머 설정
GetWorld()->GetTimerManager().SetTimer(
StealthTimerHandle,
this,
&UStealthModeSkillComponent::ResetSpeed,
StealthTime,
false
);
UE_LOG(LogTemp, Warning, TEXT("Stealth mode activated. Speed boosted by %.2f for %.2f seconds."), SpeedMultiplier, StealthTime);
}
void UStealthModeSkillComponent::BoostSpeed(float Amount)
{
if (AActor* Owner = GetOwner())
{
if (UMonsterStatComponent* StatComp = Owner->FindComponentByClass<UMonsterStatComponent>())
{
StatComp->IncreaseSPD(Amount);
}
}
}
void UStealthModeSkillComponent::ResetSpeed()
{
if (AActor* Owner = GetOwner())
{
if (UMonsterStatComponent* StatComp = Owner->FindComponentByClass<UMonsterStatComponent>())
{
StatComp->IncreaseSPD(1.0f / SpeedMultiplier);
UE_LOG(LogTemp, Warning, TEXT("Stealth Mode End"));
}
}
// 블루프린트에서 머티리얼 복원 처리
OnStealthDeactivated();
bIsStealthMode = false;
}
은신 모드 중 몬스터의 속도를 조금 빨라지게 해주자 하여 Speed 조작 관련 코드가 있습니다. 무엇보다 눈여겨봐야하는 것은 UFUNCTION 매크로 중 "Blueprintimplementable"로 선언된 OnStealthActivated()와 OnStealthDeactivated()입니다. 잠시 관련 지식을 짚고 넘어가겠습니다.
BlueprintImplementable 이란?
C++에서 정의한 함수나 메서드를 블루프린트에서 구현할 수 있도록 하는 UFUNCTION 매크로
다른 비슷한 UFUNCTION 매크로와의 차이
BlueprintCallable: C++에서 함수 정의. 블루프린트에서 호출 가능.
BlueprintPure: 상태를 변경하지 않고 계산만 하는 순수 함수. 입력값에만 의존해 값을 반환
BlueprintImplementable: C++에서 함수 시그니처만 정의, 로직은 블루프린트에서 구현
다시 한번 말하자면 은신 모드를 활성화하고 비활성화하는 동작은 결국 머티리얼 조작을 필요로 합니다. 하지만 머티리얼 조작은 Blueprint로 하는 것이 효과적입니다. 그래서 해당 동작 역할을 담당하는 두 함수의 정의를 Blueprint에서 해주겠다는 저의 의도가 담겨 있습니다. 참고로 UCLASS 선언에 Blueprintable (Blueprint 클래스로 상속 가능) 매크로를 추가하여야 OnStealthActivated()와 OnStealthDeactivated()가 제대로 Blueprint에 반영됩니다. 이제 머티리얼 부분을 보겠습니다.
2. 머티리얼 그래프 작업
Texture의 각 픽셀에는 RGB에 해당하는 값이 들어있고 그 값은 0~1에 사이 값입니다. 검은색에 가까울수록 RGB 값은 (0, 0, 0)에 가까워지고 반대로 흰색에 가까울수록 해당 픽셀에 들어있는 값은 (1, 1, 1)에 가깝다고 할 수 있습니다. 머티리얼 그래프 작업은 0~1까지의 값들을 사칙연산을 통해 조작하는 작업이라고 느꼈습니다. 이를 바탕으로 아래 노드들을 구성하였습니다.
우선 사라지는 효과를 담당하는 머티리얼 노드는 Opacity(투명도)와 Opacity Mask입니다. 특히 Opacity Mask는 마스크로 사용된 텍스처의 검은 부분을 투명하게 만듭니다.
1번 박스의 노드들을 살펴보겠습니다.
우선 일정하지 않은 패턴의 Noise Texture를 활용했고 검은색-회색-흰색들로만 분포된 픽셀들을 볼 수 있었습니다. 여기서 어떠한 값(Dissolve)를 빼게 되면 그 값만큼 픽셀 값이 작아져 점점 더 어두워질 것이고 결국 검은색에 해당하는 픽셀들이 많아집니다. 그래서 Dissolve 값을 조절하면 머티리얼의 투명한 부분의 양 또한 조절할 수 있게 됩니다. 그 결괏값을 Cheap Contrast 노드에연결해 주어 간편하게 대비 효과를 줄 수 있었습니다. 그렇게 뚜렷한 경계가 표현된 결과를 Opacity Mask 노드에 연결해주어 Dissolve 값에 따라 머티리얼의 부분 부분을 서서히 투명하게 만들 수 있는 효과를 얻었습니다.
다음은 2번 박스입니다.
대비 효과를 준 결과를 1에서 빼주어 흑백 반전 시켜주었습니다. 그리고 특정 색(빨간색)에해당하는 값을 곱해주었는데, 곱셈은 1에 가까운 값에 더 반영이 잘 되기 때문에 원래 검은색에 해당했던 부분들이 특정 색을 더 잘 띠게 됩니다. 그리고 다시 한번 특정 값(Emissive)를 곱해주면 값들이 더 커지게 됩니다. Emissive는 발광 효과를 낼 수 있고 최고 값이 없기 때문에 그 값이 더 커질수록 더 발광합니다.
이렇게 만든 Emissive와 Opacity Mask를 활용하면 투명한 부분과 아직 Texture가 남아 있는 부분에 테두리 효과를 줄 수 있습니다. 비록 대비 효과를 주었지만, 비교적 0이나 1에 가깝지 않던, 회색에 가깝던 부분들에 특정 색이 입혀졌고 그 부분들이 미쳐 Opacity Mask로 투명화되지 않았기 때문입니다.
이렇게 연결한 노드를 Material Function으로 만들어 기존 Material에 연결해주었습니다.
3. Blueprint Event Graph 작업
아래와 같이 C++에서 BlueprintImplementable 매크로로 선언한 OnStealthActivated()와 OnStealthDeactivated() 함수를 구현했습니다. Dynamic Material Instance를 만들어 그 Material의 Dissolve 값을 Loop와 Timer를 사용하여 조절하였습니다.
map<int, string> mp;
mp.insert({1, "Apple"}); //키-값 쌍 삽입
mp[2] = "Banana"; // operator[key]키로 값에 접근 또는 삽입
if (mp.find(1) != mp.end()) // 키로 요소 검색 (iterator 반환)
mp.erase(2); // 키로 요소 제거
int size = mp.size(); // 요소 개수 반환