짧은 설명
- 리스트 - 인트형
- 컨테인 함수 - 인스 리스트 받고 인트로 찾는다.
- 마우스 입력시 키코드에 키 카운트만큼 더한 값을 넣는다.
마우스 입력
- 키는 열거기에 키마다 할당되어있는게 있다.
- 키 카운트와 마우스 버튼의 열거형을 더하면 특정 키의 코드가 나온다.
- 열거형으로 구분 가능한 키의 수 : KeyCount (ex. 200이면 199까지의 인덱스에 할당되어있다.)
- 마우스 열거형이 0 ~ 4니까 키 카운트와 더하면 200 ~ 204까지의 새로운 인덱스가 생긴다.
축값까지 점진적 증가
//축 가져오기
static float GetAxisRaw(Axis axis); //해당 축의 -1 0 1 반환
static float GetAxis(Axis axis);
- GetAxis는 -1 ~ 1 까지의 값이 sensi의 속도만큼 점진적으로 바뀌는값으로 반환된다.
float InputMgr::GetAxis(Axis axis)
{
auto findIt = axisInfoMap.find(axis); //축을 키로 해당 키의 구조체 axisinfo 반환
if (findIt == axisInfoMap.end())
{
//키값이 없을 경우
return 0.0f;
}
return findIt->second.value;
}
- 축 값까지 점진적으로 증가하는것을 실행하기위해 사용
- 업데이트에서 계산된 값이 반환되는 것이다.
void InputMgr::Update(float dt)
{
mousePosition = sf::Mouse::getPosition(FRAMEWORK.GetWindow());
for (auto& pair : axisInfoMap)
{
AxisInfo& axisInfo = pair.second;
float raw = GetAxisRaw(axisInfo.axis); //축값 -1 0 1 중 하나가 반환되어 저장된다.
float dir = raw; //dir과 raw는 다른 용도다. / raw : 축값 , dir : 반환될 축값
if (raw == 0.f && axisInfo.value != 0.f)
{
//raw == 0.f -> 아무것도 안눌린경우 / 안눌렸는데 값이 0으로 안바뀐경우다. => 즉, 0으로 만들어야한다.
dir = axisInfo.value > 0.f ? -1.f : 1.f; //빼거나 더해서 0으로 만들어야한다.
}
//방향 * 속도 * 프레임간 시간 => 이동
//value -> 최소 : -1 , 최대 : 1
axisInfo.value += dir * axisInfo.sensi * dt; //-1 0 1에따라 방향과 속도가 달라진다.
if (axisInfo.value < -1.f)
{
axisInfo.value = -1.f;
}
else if (axisInfo.value > 1.f)
{
axisInfo.value = 1.f;
}
//0으로 돌리려면 -1에 가까워지거나 1에 가까워지는 등 왔다갔다 하는 경우가 있다 -> 0 근처면 0으로 바꾸는 작업을 해야한다.
float stopThreshold = std::abs(dir * axisInfo.sensi * dt);
if (raw == 0.f && std::abs(axisInfo.value) < stopThreshold)
{
axisInfo.value = 0.f;
}
}
}
최소, 최대 초과 미만 제한
static float Clamp(float value, float min, float max);
static float Clamp01(float value);
- Clamp : value를 최소, 최대로 반환하는 함수
- 최소, 최대를 넘어가지 못하게 제한하는 것이다
벡터
벡터의 길이
- 루트 x 제곱 + y 제곱
- 루트 : sqrt(스퀘어 루트) 함수가 있다.
- 제곱 계산하는 함수 1 , 스퀘어 루트 씌우는 함수 1 , 2개의 함수를 만든다.
- static float Magnitude(const sf::Vector2f& vec); static float SqrMagnitude(const sf::Vector2f& vec);
- Magnitude : 벡터의 실제 길이 반환 함수
- SqrMagnitude : 루트 안씌운 벡터 계산값
벡터 방향
//벡터의 정규화
static sf::Vector2f GetNormal(const sf::Vector2f& vec);
static void Normalize(sf::Vector2f& vec);
- GetNormal : 길이를 1로 만들어 방향을 구하는 함수
- Normalize : 직접 벡터의 길이를 1로 만드는 함수
두 점 사이의 거리
- 벡터 a - 벡터 b
- b에서 a를 향하는 방향이 반환된다.
static float Distance(const sf::Vector2f& p1, const sf::Vector2f& p2);
선형 보간 (Linear Interporation)
- 보간 : 시작부터 끝까지 선형적으로 값이 변하는데 기여하는 값이다.
- 최저 값 이전에는 최저값만 반환, 최대값 이후에는 최대값만 반환 , 그 중간은
//
//clamp : 최소와 최대를 넘지 못하도록 제한한다.
static float Lerp(float min, float max, float t, bool clamp = true);
static sf::Vector2f Lerp(const sf::Vector2f& min, const sf::Vector2f& max, float t, bool clamp = true);
static sf::Color Lerp(const sf::Color& min, const sf::Color& max, float t, bool clamp = true);
- t : 정규화된 값
- 0이면 최소, 1이면 최대라는 뜻이다.
- 0이면 min값 리턴, 1이면 max값, 0.5면 min과 max의 중간값 반환
- 0 ~ 1인 이유 : 0% ~ 100%(1) 이라는 뜻이다.
- t = 0.25 or 0.1 이런식으로 들어간다.
- clamp : 최소와 최대를 넘지 못하도록 제한한다.
핑퐁 게임
- 시작시 판과 공을 그린다.
- 시작하면 공이 튄다.
- 외벽 충돌체크 필요
- 공이 튕기는 방향 체크 필요
- 사망을 위해 바닥 충돌 체크 필요
- 원래 포지션, 회전, 스케일, 오리진, 오리진(오버라이드, 프리셋 사용) 을 게임오브젝트 상속 클래스마다 재구현을 해줘야한다.
- shape 클래스들은 이걸 꼭 해줘야하는것 같다.
막대 움직이기
sf::Vector2f size = shape.getSize();
minX = bounds.left + size.x * 0.5f; //왼쪽 경계 검사
maxX = (bounds.left + bounds.width) - size.x * 0.5f; //오른쪽 경계 검사
- minX : 화면 왼쪽 좌표(0) + 사각 박스 반절 → 왼쪽에서 사각박스 반까지가 최소가 된다.
- 이유 : 사각박스의 중앙이 피봇이기 떄문에 화면까지 가면 사각박스 반이 밖으로 나가게 된다.
direction.x = InputMgr::GetAxis(Axis::Horizontal);
sf::Vector2f pos = GetPosition() + direction * speed * dt;
pos.x = Utils::Clamp(pos.x, minX, maxX);
SetPosition(pos);
- Clamp 함수로 최대 최소를 제한을 두어서 화면 밖으로 나가지 못하게 막는다.
공 충돌
- 방향은 -1을 곱해서반전을 시키면 안된다.
- 이유 : -1이 계속 부딪혀서 벽에 붙어서 이동되는 경우가 생긴다.
- 해결책
- 부딪힌 방향의 반대를 구해서 방향으로 설정한다.
- 충돌시 포지션을 벽에 딱 붙게 한 다음 방향을 설정하고 이동시키면 붙지 않게된다.
AABB 충돌
- 충돌하는 박스를 서로 만든다.
- GetGlobalBound 함수가 이걸 가능하게 한다. ⇒ GameObject에서 상속해서 사용하면 좋다. → 알아서 구현해봐라
- 글로벌 좌표 기준으로 박스를 리턴하는 함수다.
- 이걸 겹치는지 true false로 반환하는 함수도 있다.