쉐도우복싱일수도 있지만 미리 생각해보고 짜는 중인 내 액터 클래스들 구조!!
Actor
: (엔진의) 액터
Objects
: 맵에 표시될 수 있는 모든 오브젝트
LerpMoveObject
: 한 칸씩 Lerp 이동할 수 있는 모든 오브젝트
그리고 얘를 상속받아서
PlayerObject
: 그 중에도 입력에 의해 이동할 수 있는 애들(Push일 때도 있음)
TextObject
: (아직안만듦)Push에 의해서만 이동할 수 있는 TextObject들
그리고 PlayerObject 상속받아서 BabaObject
만들어놨음
근데 입력에 의해 이동하는 애들이랑 Push당해서 이동하는 애들 구분이 아니고 Type Switch하듯이 만들어야 하나??????
void ALerpMoveObject::Move(float _DeltaTime)
{
if (false == IsMove)
{
if (true == IsPress(VK_LEFT))
{
AddNextActorLocation(FVector::Left * TileSize);
NewInputDir = EInputDir::Left;
IsMove = true;
}
if (true == IsPress(VK_RIGHT))
{
AddNextActorLocation(FVector::Right * TileSize);
NewInputDir = EInputDir::Right;
IsMove = true;
}
if (true == IsPress(VK_UP))
{
AddNextActorLocation(FVector::Up * TileSize);
NewInputDir = EInputDir::Up;
IsMove = true;
}
if (true == IsPress(VK_DOWN))
{
AddNextActorLocation(FVector::Down * TileSize);
NewInputDir = EInputDir::Down;
IsMove = true;
}
if (true == IsMove)
{
InputCheck = true;
}
}
LerpMove(_DeltaTime);
}
void ALerpMoveObject::AddNextActorLocation(FVector _Add)
{
NextActorLocation = GetActorLocation() + _Add;
}
void ALerpMoveObject::LerpMove(float _DeltaTime)
{
if (LerpTime <= 1.f && true == IsMove)
{
LerpTime += _DeltaTime * 4;
SetActorLocation(LerpCal(LerpTime));
}
else
{
IsMove = false;
LerpTime = 0.f;
SetActorLocation(NextActorLocation);
CurActorLocation = NextActorLocation;
}
}
FVector ALerpMoveObject::LerpCal(float _Time)
{
return CurActorLocation * (1 - _Time) + NextActorLocation * _Time;
}
z키 누르면 이전으로 돌아감 ⇒ 이동 정보 받는 스택 필요함
스택에 넣는 데이터 : 방향이랑 애니메이션 번호 필요함
근데 넣는 기준? 입력 1회 있으면 스택에 넣어야 함. 모든 움직일 수 있는 오브젝트에 해당됨.
이동할 때 스택에 이동 전 정보를 넣음 → Z를 누르면 이전 상태로 돌아감.
void APlayerObject::Tick(float _DeltaTime)
{
Super::Tick(_DeltaTime);
Move(_DeltaTime);
if (true == IsMove)
{
LerpMove(_DeltaTime);
}
if (true == IsPress('Z') && false == IsMove)
{
if (true == MoveStack.empty())
{
return;
}
IsMove = true;
InputCheck = true;
// 이동 : 현재 방향의 반대로 이동
ReverseMoveSetting(NewInputDir, _DeltaTime);
// 애니메이션에 필요한 정보 : 이전 상태의 정보로 되돌리고 삭제
NewInputDir = MoveStack.top().second;
AnimationNumber = MoveStack.top().first;
MoveStack.pop();
return;
}
if (true == InputCheck)
{
// 새로운 입력의 이동을 반영하기 전 정보를 넣음
MoveStack.push(std::make_pair(AnimationNumber, CurDir));
AnimationNumber = (AnimationNumber + 1) % 4;
}
}
void ALerpMoveObject::ReverseMoveSetting(EInputDir _Dir, float _DeltaTime)
{
IsMove = true;
// 애니메이션 "방향"은 이전꺼여야 함.
// 이동은 반대로.
switch (_Dir)
{
case EInputDir::Right:
AddNextActorLocation(FVector::Left * TileSize);
NewInputDir = EInputDir::Right;
break;
case EInputDir::Left:
AddNextActorLocation(FVector::Right * TileSize);
NewInputDir = EInputDir::Left;
break;
case EInputDir::Up:
AddNextActorLocation(FVector::Down * TileSize);
NewInputDir = EInputDir::Up;
break;
case EInputDir::Down:
AddNextActorLocation(FVector::Up * TileSize);
NewInputDir = EInputDir::Down;
break;
default:
break;
}
}
원본게임 1920 x 1080 화면에서 한 블록 사이즈 54 x 54
창 크기 1280 x 720 으로 만들면 한 블록 36 x 36 사이즈.
128 * 128로 자른 리소스에 내부 한 칸은 24 * 24 인듯?
리소스를 한칸 36 * 36으로 자르자
와우 너무 낙서라서 정리할 자신은 없음.
"왜 검은색으로 나오냐?"
DestColor, SrcColor ← 이 두 개를 정확히 이해해야 블렌드에 대한 이해를 할 수 있음.
최초의 모니터 Clear색상 파랑일 때 Float4(0,0,1,1), 이걸 DestColor라고 한다.
이미지의 투명 부분 SrcColor라고 하는데 Float(0,0,0,0)일 것이다.
블렌드는 DESTCOLOR 연산자 SRCCOLOR
이다.
알파값은 따로 처리된다.
001 1 = 000 0 ⇒ DC가 000 됨. 덮어씌우는거
더하기가 아니라 옵션임. “+”말고 여러 연산자를 쓸 수 있다. 옵션 설정해서.
DESTCOLOR + SRCCOLOR
0011 + 0000
근데 알파값은 최종적으로 1이 된다. 우리가 윈도우 뒤가 보인 적이 있냐. 없음.
DestColor * DestFilter + SrcColor * SrcFilter
Float3 Float3 연산자 Float3 Float3
우리가 바꿀 수 있는 건 연산자 : 더할거냐 뺄거냐
알파값은 따로 계산.
UEngineBlend 클래스 만듦.
AlphaToCoverageEnable ⇒ true로 하면 투명처리가 투명이 될 것인데 연산량 높아서 잘 안쓴다고 함. 다렉의 기본 공식으로 계산.
IndependentBlendEnable ⇒ true로 해두면 8개 하나씩 다 세팅해주는것, false는 다 0번 세팅으로 모두 통일
렌더타겟은 한 번 에 최대 8장까지 세팅가능. SV_Target 그림그릴곳 8개 세팅할 수 있고 블렌드 8개 할 수 있음.
0번에는 캐릭터만 그려 1번에는 몬스터만 그려 2번에는 무기만 그려. 타겟을 여러개 세팅할 수 있다는 것의 이득은 무궁무진함. 몬스터만 회색으로 칠하는 게 편해지는 등등.. 컵헤드 지지직거리는 효과 등등…
다렉 함수는 왜 빠르냐?
내부에서 SIMD 연산을 사용한다.
CPU에서 그래픽 카드와 같이 한번에 XYZW를 동시에 연산처리하는 기술
행렬 연산 빠르게하라고? 다렉에서 만든 자료형이 있음 DirectX::XMMATRIX
, DirectX::XMVECTOR
언리얼에서도 씀. 다렉함수 쓰려면 이 자료형 써야 함.
내용은 SIMD연산 쓰는거 빼고 쌤이 계산하던거랑 다를 게 없다.
IdleStart함수에서는 Idle애니메이션 만들기만 한다. 이런 경우 람다를 이용해서 코드를 많이 줄일 수 있음.
람다캡처의 내용안에 =을 쓰면 현재 스택에서 사용가능한 복사본을 만든다.
메모리를 할당해서 Renderer를 같은 이름으로 복사한다. 그래서 주솟값이 다르다.
State.SetStartFunction("Idle", [=]
{
// 새로운 함수다.
// 스택이 달라진다.
Renderer->ChangeAnimation("Idle");
}
);