개발일지/TIL(Today I Learned)

2025-03-03 <최종프로젝트 D-11> 레이턴시, 추측항법 구현과 사소한 버그 리포트

프린스 알리 2025. 3. 3.

 

레이턴시 구하기

  // 레이턴시
  ping() {
    const now = Date.now();
    this.socket.write(makePingPacket(now));
  }

  handlePong(milliseconds) {
    const now = Date.now();
    this.lastPong = now;
    this.latency = (now - milliseconds) / 2; // 왕복이니까
  }

 

핑퐁함수(setInterval)을 구현해서 레이턴시를 주기적으로 저장한다.

 

추측항법

function predictPosition(socket, player, transform, latency) {
  // 직전 좌표와 transform의 좌표를 빼서 방향벡터를 구하고 노말라이즈
  const prevPosition = player.getPosition();
  const velocity = {
    posX: transform.posX - prevPosition.x,
    posY: transform.posY - prevPosition.y,
    posZ: transform.posZ - prevPosition.z,
  };

  // 속도 벡터 크기(속력) 계산 및 검증
  let magnitude = Math.sqrt(
    velocity.posX ** 2 + velocity.posY ** 2 + velocity.posZ ** 2,
  );
  if (magnitude > 7) {
    magnitude = 10;
    return socket.emit(
      'error',
      new CustomError(
        ErrorCodes.INVALID_SPEED,
        '플레이어의 이동 속도가 올바르지 않습니다.',
      ),
    );
  }

  // 초당 속도 벡터 구하기(노말라이즈)
  const normalizedVelocity =
    magnitude > 0
      ? {
          posX: velocity.posX / magnitude,
          posY: velocity.posY / magnitude,
          posZ: velocity.posZ / magnitude,
        }
      : { posX: 0, posY: 0, posZ: 0 };

  // 예측한 위치 = 현재 transform 위치 + (속도 벡터 * 레이턴시)
  const predictedPosition = {
    posX: transform.posX + normalizedVelocity.posX * latency,
    posY: transform.posY + normalizedVelocity.posY * latency,
    posZ: transform.posZ + normalizedVelocity.posZ * latency,
    rot: transform.rot,
  };

  return predictedPosition;
}

 

버그리포트

int 64 프로토버프에 Date.now()를 저장했더니 이렇게 나왔다.

 

 

이유를 gpt에 물어봤더니, 아래와 같이 답을 줬다.

 

JavaScript는 number 타입이 53비트 정밀도를 가지므로, 64비트 정수를 다룰 때 보통 low(하위 32비트)와 high(상위 32비트)로 분리해 저장하는 방식을 사용한다. Date.now()처럼 밀리초 단위의 타임스탬프로 변환하려면, 다음과 같이 lowhigh 값을 조합하면 된다:

function timestampToMillis(timestamp) {
    return (timestamp.high * 2 ** 32) + timestamp.low;
}

 

 

댓글