공부/SFML

마우스 입력, 축값까지 점진적 증가, 최소, 최대 초과 미만 제한, 벡터의 길이, 벡터의 방향, 두 점 사이의 거리, 선형 보간, AABB 충돌

월러비 2025. 7. 5. 22:30

짧은 설명

  • 리스트 - 인트형
    • 컨테인 함수 - 인스 리스트 받고 인트로 찾는다.
    • 마우스 입력시 키코드에 키 카운트만큼 더한 값을 넣는다.
      • 마우스 입력이 키와 같이 이동되게 된다.

마우스 입력

  • 키는 열거기에 키마다 할당되어있는게 있다.
    • 마우스도 열거형에 할당된 키가 있다.
  • 키 카운트와 마우스 버튼의 열거형을 더하면 특정 키의 코드가 나온다.
    • 열거형으로 구분 가능한 키의 수 : 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의 속도만큼 점진적으로 바뀌는값으로 반환된다.
    • 값의 변경은 update에서 진행된다.
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 : 루트 안씌운 벡터 계산값

벡터 방향

  • 벡터 = 길이 * 방향
    • 길이가 1이면 방향을 알 수 있다.
//벡터의 정규화
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이 계속 부딪혀서 벽에 붙어서 이동되는 경우가 생긴다.
    • 해결책
      1. 부딪힌 방향의 반대를 구해서 방향으로 설정한다.
      2. 충돌시 포지션을 벽에 딱 붙게 한 다음 방향을 설정하고 이동시키면 붙지 않게된다.

AABB 충돌

  • 충돌하는 박스를 서로 만든다.
    • 박스가 서로 닿는것을 확인한다.
  • GetGlobalBound 함수가 이걸 가능하게 한다. ⇒ GameObject에서 상속해서 사용하면 좋다. → 알아서 구현해봐라
    • 글로벌 좌표 기준으로 박스를 리턴하는 함수다.
    • 이걸 겹치는지 true false로 반환하는 함수도 있다.