#include <iostream>
using namespace std;
long long solution(int price, int money, int count) // 매개변수는 초기화 안 해도 됨
{
long long total = 0; // 지역변수는 초기화 안 하면 쓰레기값 들어감
for (int i = 1; i <= count; ++i)
{
total += price * i; // 각 회차마다 가격을 누적
}
if (total > money)
{
return total = money; // 부족한 금액 계산
}
return 0; // 부족하지 않으면 0 반환
}
#include <string>
#include <vector>
using namespace std;
bool solution(string s)
{
// 길이가 4 또는 6이 아니면 false
if (s.length() != 4 && s.length() != 6)
{
return false;
}
// 문자 하나씩 돌면서 숫자인지 확인
for (int i = 0; i < s.length(); ++i)
{
if (s[i] <'0' || s[i] > '9') // 각 문자가 숫자가 아닌 경우, 숫자는 문자로 되어있음
{
return false; // 숫자가 아닌 문자가 있으면 false
}
}
return true; // 길이가 4나 6이고, 모두 숫자이면 true
}
s.length()s[i]s[i] <'0' || s[i] > '9'
📍 3주차 2강
충돌 처리를 통한 아이템 상호작용 활성화
protected:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item") // 리플렉션으로 에디터에 노출
FName ItemType; // 아이템의 타입을 저장하는 변수
// 컴포넌트 선언
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Item|Component") // 객체 자체 변경 x, 내부 속성은 에디터에서 조정 가능
USceneComponent* Scene;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Item|Component")
USphereComponent* Collision;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Item|Component")
UStaticMeshComponent* StaticMesh;
#include "BaseItem.h"
#include "Components/SphereComponent.h" // 스피어 컴포넌트 헤더 포함
ABaseItem::ABaseItem()
{
PrimaryActorTick.bCanEverTick = false;
Scene = CreateDefaultSubobject<USceneComponent>(TEXT("Scene")); // 객체 생성
SetRootComponent(Scene); // 항상 Scene을 루트 컴포넌트로 설정
Collision = CreateDefaultSubobject<USphereComponent>(TEXT("Collision")); // 스피어 컴포넌트 생성
Collision->SetupAttachment(Scene); // Scene(Root Component)에 붙임
StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh")); // 스태틱 메시 컴포넌트 생성
StaticMesh->SetupAttachment(Collision); // Collision에 붙임
}
실질적으로 구현할 아이템들만 블루프린트 상속하도록 만들기

ItemBase에서 Component 생성했기 때문에 나머지 자손클래스들도 모두 생성됨

Spehere Component가 어떤 종류의 충돌을 감지하고 무시할지 설정

| Preset 이름 | 설명 |
|---|---|
| NoCollision | 충돌 무시, 겹쳐지거나 막지도 않음, 액터랑 상호작용 ❌ 🧩 하늘에 있는 것 (구름), 장식용 |
| BlockAll | 모든 것과 충돌(막음), Overlap 없음 🧩 벽, 바닥 |
| BlockAllDynamic | 움직이는 객체만 막음 🧩 플레이어랑만 상호작용 하고 싶을 때 - 문 or 굴러오는 물체 |
| OverlapAll | 모든 것과 겹침(Overlap), 충돌 없음 🧩 투명한 객체, 트리거 존 - 감지 센서 |
| OverlapAllDynamic | 정적 객체는 무시, 움직이는 객체와 오버랩 이벤트 🧩 감지 센서 ✅ Item들 이거 적용 |
| Custom 설정 | 충돌 감지 (Query: Overlap, Hit) | 물리적 반응 (Physics) |
|---|---|---|
| Collision Enabled (Query and Physics) | ✅ | ✅ |
| Query Only | ✅ | ❌ |
| Physics Only | ❌ | ✅ |
Collision Prestets 설정하고 Collision Component에 추가하기
BaseItem.cpp
Collision = CreateDefaultSubobject<USphereComponent>(TEXT("Collision")); // 스피어 컴포넌트 생성
Collision->SetCollisionProfileName(TEXT("OverlapAllDynamic")); // 충돌 프리셋 설정
Collision->SetupAttachment(Scene); // Scene(Root Component)에 붙임
public:
virtual void OnItemOverlap( // 아이템과 겹쳤을 때 호출되는 함수
UPrimitiveComponent* OverlappedComp, // 오버랩이 발생한 자기 자신 = SphereComponent
AActor* OtherActor, // 겹친 다른 액터 = 플레이어 캐릭터
UPrimitiveComponent* OtherComp, // 충돌 원인 컴포넌트 = 플레이어 캐릭터의 CapsuleComponent
int32 OtherBodyIndex,
bool bFromSweep,
const FHitResult& SweepResult) = 0;
virtual void OnItemEndOverlap( // 아이템과 겹침이 끝났을 때 호출되는 함수
UPrimitiveComponent* OverlappedComp,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex, ) = 0;
virtual void OnItemOverlap(
UPrimitiveComponent* OverlappedComp,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex,
bool bFromSweep,
const FHitResult& SweepResult) override;
virtual void OnItemEndOverlap(
UPrimitiveComponent* OverlappedComp,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex) override;
#include "BaseItem.h"
#include "Components/SphereComponent.h" // 스피어 컴포넌트 헤더 포함
ABaseItem::ABaseItem()
{
PrimaryActorTick.bCanEverTick = false;
Scene = CreateDefaultSubobject<USceneComponent>(TEXT("Scene")); // 객체 생성
SetRootComponent(Scene); // 항상 Scene을 루트 컴포넌트로 설정
Collision = CreateDefaultSubobject<USphereComponent>(TEXT("Collision")); // 스피어 컴포넌트 생성
Collision->SetCollisionProfileName(TEXT("OverlapAllDynamic")); // 충돌 프리셋 설정
Collision->SetupAttachment(Scene); // Scene(Root Component)에 붙임
StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh")); // 스태틱 메시 컴포넌트 생성
StaticMesh->SetupAttachment(Collision); // Collision에 붙임
// 이벤트 바인딩
Collision->OnComponentBeginOverlap.AddDynamic(this, &ABaseItem::OnItemOverlap); // 겹쳤을 때 호출되는 함수
Collision->OnComponentEndOverlap.AddDynamic(this, &ABaseItem::OnItemEndOverlap); // 겹침이 끝났을 때 호출되는 함수
}
void ABaseItem::OnItemOverlap(
UPrimitiveComponent* OverlappedComp,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex,
bool bFromSweep,
const FHitResult& SweepResult)
{
if (OtherActor && OtherActor->ActorHasTag("Player")) // ✅ 플레이어 태그
{
ActivateItem(OtherActor); // 플레이어와 겹쳤을 때 아이템 활성화 함수 호출
}
}
void ABaseItem::OnItemEndOverlap(UPrimitiveComponent* OverlappedComp,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex)
{
}
public:
UFUNCTION() // 엔진의 리플렉션 시스템에 함수 등록 -> 엔진이 런타임 때 이 함수를 호출할 수 있도록
virtual void OnItemOverlap( // 아이템과 겹쳤을 때 호출되는 함수
UPrimitiveComponent* OverlappedComp, // 오버랩이 발생한 자기 자신 = SphereComponent
AActor* OtherActor, // 겹친 다른 액터 = 플레이어 캐릭터
UPrimitiveComponent* OtherComp, // 충돌 원인 컴포넌트 = 플레이어 캐릭터의 CapsuleComponent
int32 OtherBodyIndex,
bool bFromSweep,
const FHitResult& SweepResult) = 0;
UFUNCTION()
virtual void OnItemEndOverlap( // 아이템과 겹침이 끝났을 때 호출되는 함수
UPrimitiveComponent* OverlappedComp,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex, ) = 0;
virtual void ActivateItem(AActor* Activator) = 0; // 아이템을 활성화할 때 호출되는 함수
virtual FName GetItemType() const = 0; // 아이템의 타입을 반환하는 함수 -> return만 하기 때문에 const
// String 말고 빠른 FName을 사용
| 구분 | 목적 |
|---|---|
| 이벤트 바인딩 | 이벤트 발생 시 자동으로 함수를 실행하기 위해 |
| 플레이어 태그 | 이벤트의 대상이 플레이어인지 확인하기 위해 |
| 둘을 함께 쓰는 이유 | 상호작용 이벤트가 "플레이어가 했는지" 확인해서 조건에 맞는 행동을 하도록 하기 위해 |
if (OtherActor && OtherActor->ActorHasTag("Player")) // ✅ 플레이어 태그
{
ActivateItem(OtherActor); // 플레이어와 겹쳤을 때 아이템 활성화 함수 호출
}

if (OtherActor && OtherActor->ActorHasTag("Player"))
{
GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Green, FString::Printf(TEXT("Overlap!!!")));
ActivateItem(OtherActor); // 플레이어와 겹쳤을 때 아이템 활성화 함수 호출
}
Overlap 이벤트 발생 시 Destroy() + 로그 출력됨
override 해야 아이템마다 각자의 동작 설정할 수 있음
헤더파일에서 선언
virtual void ActivateItem(AActor* Activator) override;
소스파일에서 구현 (초기화도 해주기)
#include "CoinItem.h"
ACoinItem::ACoinItem() // 생성자
{
PointValue = 0; // 초기화
ItemType = "DefaultCoin"; // 아이템 타입 초기화
}
void ACoinItem::ActivateItem(AActor* Activator)
{
if (Activator && Activator->ActorHasTag("Player"))
{
GEngine->AddOnScreenDebugMessage(
-1,
2.0f,
FColor::Green,
FString::Printf(TEXT("Player gained %d points!"), PointValue));
DestroyItem();
}
}
자식클래스(Big & Small)에선 불러오기만 하면 됨
void ABigCoinItem::ActivateItem(AActor* Activator)
{
// DestroyItem(); -> CoinItem에서 DestroyItem()을 호출
Super::ActivateItem(Activator); // 부모 클래스의 ActivateItem 호출
}
#pragma once
#include "CoreMinimal.h"
#include "BaseItem.h"
#include "HealingItem.generated.h"
UCLASS()
class SPARTAPROJECT_API AHealingItem : public ABaseItem
{
GENERATED_BODY()
public:
AHealingItem(); // 생성자
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item")
int32 HealAmount; // 회복량 ✅int로 변경
virtual void ActivateItem(AActor* Activator) override; // ✅
};
반경을 Collision Component로 추가
그 안에 오버랩된 게 플레이어다 -> 플레이어한테 데미지 입힘
Collision Component로 추가

추가했던 Collision 컴포넌트 지우고
#pragma once
#include "CoreMinimal.h"
#include "BaseItem.h"
#include "MineItem.generated.h"
UCLASS()
class SPARTAPROJECT_API AMineItem : public ABaseItem
{
GENERATED_BODY()
public:
AMineItem(); // 생성자
USphereComponent* ExplosionCollision; // ✅ 폭발 범위 콜리전 컴포넌트
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item")
float ExplosionDelay; // 폭발 지연 시간
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item")
float ExplosionRadius; // 폭발 범위
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item")
int32 ExplosionDamage; // 폭발 피해 ✅ int로 변경
virtual void ActivateItem(AActor* Activator) override;
void Explode(); // ✅ 폭발 함수
};
#include "MineItem.h"
#include "Components/SphereComponent.h"
AMineItem::AMineItem()
{
ExplosionDelay = 5.0f; // 기본 폭발 지연 시간 설정
ExplosionRadius = 300.0f; // 기본 폭발 범위 설정
ExplosionDamage = 30.0f; // 기본 폭발 피해 설정
ItemType = "Mine"; // 아이템 타입 설정
// ✅ 콜리전 컴포넌트 추가 (반경)
ExplosionCollision = CreateDefaultSubobject<USphereComponent>(TEXT("ExplosionCollision"));
ExplosionCollision->InitSphereRadius(ExplosionRadius); // 300.0f 넣기
ExplosionCollision->SetCollisionProfileName(TEXT("OverlapAllDynamic")); // 모든 동적 오버랩 허용
ExplosionCollision->SetupAttachment(Scene); // 루트 컴포넌트인 씬 컴포넌트에 부착
}
// ✅ 타이머 추가 : 5초 뒤 폭발
void AMineItem::ActivateItem(AActor* Activator) // 활성화되고 5초 후에 폭발
{
// 게임 월드에는 각자의 타이머를 관리하는 타이머 매니저가 있음
// 타이머 핸들러 : 각자의 타이머를 갖고 있음
// 월드에서 타이머 매니저 부름
GetWorld()->GetTimerManager().SetTimer(
ExplosionTimerHandle, // 타이머 달아줌
this, // 타이머가 끝나면 호출할 대상 : 이 객체에
&AMineItem::Explode, // 호출할 함수
ExplosionDelay, // 지연 시간
false // 반복 여부 (false면 한 번만 실행)
);
}
// ✅ 태그 찾기
void AMineItem::Explode()
{
TArray<AActor*> OverlappingActors; // 범위 내 겹치는 액터 검색
ExplosionCollision->GetOverlappingActors(OverlappingActors);
// 범위 내 돌면서 태그 확인
for (AActor* Actor : OverlappingActors)
{
if (Actor && Actor->ActorHasTag("Player")) // Actor가 nullptr이 아니고 플레이어 태그가 있는지 확인
{
GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Green, FString::Printf(TEXT("Player damaged %d by MineItem"), ExplosionDamage));
}
}
DestroyItem();
}


각 아이템들마다 오버랩 이벤트 & 출력 완료
예전엔 블루프린트로만 오버랩을 구현했는데, 이번엔 C++로 해보니까 일일이 설정하던 걸 인터페이스랑 부모 클래스 덕분에 좀 더 깔끔하게 만들 수 있어서 좋았다!
… 근데 아직 어렵긴 하다