F1 레이싱 시뮬레이션 게임 AI 개발 연구 보고서 (2편): 엔진 & 변속 시스템 구현

juns·2025년 7월 20일
1

f1-racing-game

목록 보기
2/2

F1 레이싱 게임 AI 개발 연구 보고서 (2편): 엔진 & 변속 시스템 구현

📋 목차

  1. 연구 배경 및 목적
  2. 엔진 & 변속 시스템 수학적 기반
  3. 현실적 물리 엔진 구현
  4. 기어 시스템 설계 및 구현
  5. RPM & 토크 시스템
  6. 연구 결과 및 성능 평가
  7. 향후 개발 로드맵

🚗 연구 배경 및 목적

1.1 연구 동기

1편에서 구현한 기본 레이싱 게임을 넘어서, 현실적인 차량 물리 시뮬레이션을 구현하는 것이 본 연구의 핵심 목표이다. 특히 F1 레이싱에서는 엔진 성능, 변속 타이밍, RPM 관리가 랩타임에 직접적인 영향을 미치므로, 이러한 요소들을 정확히 모델링하는 것이 중요하다.

1.2 연구 목표

  • 현실적 엔진 시뮬레이션: RPM, 토크, 출력의 수학적 관계 구현
  • 정교한 변속 시스템: 기어비, 변속 타이밍, 속도 제한 구현
  • 물리적 정확성: 속도, 가속도, 관성의 자연스러운 변화
  • 사용자 경험 향상: 직관적이면서도 현실적인 조작감

⚙️ 엔진 & 변속 시스템 수학적 기반

2.1 핵심 수학적 구성요소

2.1.1 RPM ↔ 속도 관계식

// 기본 관계식
RPM = (v × G × 60) / (2π × r × FD)
v = (RPM × 2π × r × FD) / (60 × G)

// 변수 설명
v: 차량 속도 (m/s)
G: 기어비 (Gear Ratio)
r: 바퀴 반지름 (m)
FD: 종감속비 (Final Drive Ratio)
RPM: 엔진 회전수 (Revolutions Per Minute)

📚 개념 설명: RPM과 속도의 관계

RPM(Revolutions Per Minute)은 엔진의 분당 회전수를 나타내며, 차량의 속도와 직접적인 관계를 가집니다. 이 관계는 다음과 같은 물리적 원리에 기반합니다:

  1. 기어비(Gear Ratio): 변속기의 각 기어는 서로 다른 기어비를 가집니다. 낮은 기어(1단, 2단)는 높은 기어비로 강한 토크를 제공하고, 높은 기어(5단, 6단)는 낮은 기어비로 높은 속도를 제공합니다.

  2. 종감속비(Final Drive Ratio): 디퍼렌셜에서 최종적으로 바퀴로 전달되는 기어비로, 일반적으로 3.0~4.0 범위입니다.

  3. 바퀴 반지름: 바퀴의 크기가 클수록 같은 RPM에서 더 높은 속도를 낼 수 있습니다.

수학적 예시:

  • 1단 기어비: 3.8, 종감속비: 3.2, 바퀴 반지름: 0.33m
  • RPM 3000에서 속도 계산: v = (3000 × 2π × 0.33 × 3.2) / (60 × 3.8) ≈ 8.7 m/s ≈ 31 km/h

2.1.2 토크 & 출력 계산

// 토크 전달 관계식
T_wheel = T_engine × G × FD × η

// 출력 계산
P = T × ω
ω = RPM × 2π / 60 (rad/s)

// 변수 설명
T_wheel: 바퀴 토크 (Nm)
T_engine: 엔진 토크 (Nm)
η: 구동계 효율 (0.85~0.95)
P: 출력 (Watt)
ω: 각속도 (rad/s)

📚 개념 설명: 토크와 출력의 물리적 의미

토크(Torque)와 출력(Power)은 자동차 성능을 나타내는 핵심 지표입니다:

  1. 토크(Torque): 회전력을 나타내는 물리량으로, 단위는 Nm(뉴턴미터)입니다. 토크가 클수록 차량의 가속력이 강해집니다.

  2. 출력(Power): 단위 시간당 일의 양으로, 단위는 Watt입니다. 출력 = 토크 × 각속도로 계산됩니다.

  3. 구동계 효율(η): 엔진에서 바퀴까지 동력이 전달되는 과정에서 발생하는 손실을 고려한 계수입니다. 일반적으로 85~95% 범위입니다.

토크 곡선의 특징:

  • 최대 토크: 보통 2000~4000 RPM에서 발생
  • 최대 출력: 보통 5000~7000 RPM에서 발생
  • 토크 곡선: 낮은 RPM에서 급격히 증가하다가 최대값 후 감소

수학적 예시:

  • 엔진 토크: 200 Nm, 기어비: 3.8, 종감속비: 3.2, 효율: 0.9
  • 바퀴 토크: 200 × 3.8 × 3.2 × 0.9 = 2,188.8 Nm

2.2 기어 시스템 수학적 모델

2.2.1 기어비별 속도 한계

// 기어별 최대 속도 계산
v_max = (RPM_limit × 2π × r × FD) / (60 × G)

// 일반 차량 기준 기어 시스템
const GEAR_SYSTEM = {
    // 기어별 최고 속도 (KM/h 기준)
    MAX_SPEED_PER_GEAR: [0, 0, 25, 45, 70, 100, 130, 160],
    // 기어별 속도 비율 (RPM → 속도 변환 계수)
    GEAR_SPEED_RATIO: [0, 0, 0.010, 0.013, 0.016, 0.019, 0.022, 0.025],
    // 최적 변속 RPM
    OPTIMAL_SHIFT_RPM: [0, 0, 1800, 2200, 2600, 3000, 3400, 3800]
};

📚 개념 설명: 기어 시스템의 원리

변속기는 엔진의 회전력을 차량의 주행 조건에 맞게 조절하는 핵심 장치입니다:

  1. 기어비의 의미: 기어비가 높을수록(1단, 2단) 엔진의 회전력이 증폭되어 강한 가속력을 제공하지만, 최고 속도는 낮습니다. 반대로 기어비가 낮을수록(5단, 6단) 높은 속도를 낼 수 있지만 가속력은 떨어집니다.

  2. 최적 변속 RPM: 각 기어에서 최적의 성능을 발휘할 수 있는 RPM 범위입니다. 너무 낮은 RPM에서는 엔진이 불안정하고, 너무 높은 RPM에서는 연료 효율이 떨어집니다.

  3. 기어별 속도 한계: 각 기어에서 달성할 수 있는 최대 속도로, RPM 한계와 기어비에 의해 결정됩니다.

기어 선택의 전략:

  • 가속 시: 낮은 기어(1~3단)로 강한 토크 활용
  • 고속 주행: 높은 기어(4~6단)로 연료 효율 극대화
  • 코너링: 적절한 기어로 엔진 브레이킹 활용

2.2.2 가속도 기어별 차등 적용

// 기어별 가속도 계수 (현실적 구현)
const gearAccelerationRates = {
    0: 0.00, // N(중립): 엔진 동력 전달 안됨
    1: 0.10, // R(후진): 후진 가속
    2: 0.15, // 1단: 가장 빠른 가속
    3: 0.12, // 2단: 빠른 가속
    4: 0.08, // 3단: 중간 가속
    5: 0.05, // 4단: 느린 가속
    6: 0.03, // 5단: 매우 느린 가속
    7: 0.02  // 6단: 가장 느린 가속
};

📚 개념 설명: 기어별 가속도의 물리적 원리

가속도는 기어에 따라 크게 달라지며, 이는 토크와 기어비의 관계에서 비롯됩니다:

  1. 토크 증폭 효과: 낮은 기어(1단, 2단)에서는 기어비가 높아 엔진 토크가 증폭되어 강한 가속력을 제공합니다.

  2. 관성과 질량: 차량의 관성은 기어와 무관하게 일정하므로, 낮은 기어에서 더 큰 힘을 받아 가속도가 높아집니다.

  3. 기어비 공식: 가속도 ∝ (엔진 토크 × 기어비) / 차량 질량

실제 차량에서의 예시:

  • 1단: 기어비 3.8, 최대 토크 증폭, 출발과 저속 가속에 최적
  • 3단: 기어비 1.5, 중간 토크, 도심 주행에 적합
  • 6단: 기어비 0.75, 낮은 토크, 고속 크루징에 최적

2.3 물리적 제약 조건

2.3.1 관성 및 점진적 변화

// 점진적 가속 구현
const targetSpeed = maxSpeedGame;
const speedDiff = targetSpeed - newSpeed;
const actualAcceleration = Math.min(acceleration, Math.abs(speedDiff) * 0.1);

if (speedDiff > 0) {
    newSpeed = Math.min(newSpeed + actualAcceleration, targetSpeed);
}

📚 개념 설명: 관성과 점진적 변화의 물리학

실제 차량에서는 속도 변화가 순간적으로 일어나지 않습니다. 이는 관성과 여러 물리적 제약 때문입니다:

  1. 관성의 법칙: 뉴턴의 제1법칙에 따라, 물체는 외력이 작용하지 않는 한 현재 상태를 유지하려고 합니다. 차량의 질량이 클수록 관성이 커져서 속도 변화가 더 점진적입니다.

  2. 마찰력과 저항: 공기 저항, 타이어 마찰, 구동계 손실 등이 속도 변화를 제한합니다.

  3. 엔진 응답성: 엔진은 스로틀 입력에 즉시 반응하지 않고, 연료 분사, 연소, 배기 과정을 거쳐 점진적으로 반응합니다.

수학적 모델링:

  • 가속도 제한: 실제 차량의 관성을 고려한 최대 가속도 설정
  • 점진적 변화: 목표 속도에 도달하는 과정을 부드럽게 구현
  • 저항 모델: 속도에 비례하는 저항력 적용

2.3.2 자연 감속 시스템

// 자연 감속 (전진/후진 모두)
const naturalDeceleration = 0.02;
if (newSpeed > 0) {
    newSpeed = Math.max(newSpeed - naturalDeceleration, 0);
} else if (newSpeed < 0) {
    newSpeed = Math.min(newSpeed + naturalDeceleration, 0);
}

📚 개념 설명: 자연 감속의 물리적 원인

스로틀을 놓았을 때 차량이 자연스럽게 감속하는 현상은 여러 물리적 요인 때문입니다:

  1. 엔진 브레이킹: 스로틀이 닫히면 엔진이 공기 흡입을 제한하여 내부 저항이 발생합니다. 이는 자연스러운 감속 효과를 만듭니다.

  2. 공기 저항: 속도의 제곱에 비례하는 공기 저항력이 차량을 감속시킵니다. 공기 저항 = ½ × 공기밀도 × 저항계수 × 단면적 × 속도²

  3. 타이어 마찰: 타이어와 노면 사이의 마찰력, 구름 저항 등이 지속적으로 속도를 감소시킵니다.

  4. 구동계 손실: 변속기, 차동장치, 베어링 등의 기계적 손실이 감속에 기여합니다.

감속률 계산:

  • 저속: 주로 엔진 브레이킹과 타이어 마찰이 지배적
  • 고속: 공기 저항이 감속의 주요 원인
  • 기어별 차이: 낮은 기어에서 엔진 브레이킹 효과가 더 강함

🔧 현실적 물리 엔진 구현

3.1 엔진 시스템 아키텍처

3.1.1 RPM 계산 시스템

// 현실적인 RPM 계산 (속도 → RPM)
const calculateRPM = useCallback((speed, gear) => {
    // 입력값 검증
    if (typeof speed !== 'number' || isNaN(speed)) {
        return GEAR_SYSTEM.IDLE_RPM;
    }

    if (gear === 0) return GEAR_SYSTEM.IDLE_RPM; // 중립

    // 일반 차량 기준 RPM 계산
    const speedKMH = Math.abs(speed) * 10; // 게임 속도를 KM/h로 변환
    const gearSpeedRatio = GEAR_SYSTEM.GEAR_SPEED_RATIO[gear];
    const rpm = speedKMH / gearSpeedRatio;

    return Math.max(GEAR_SYSTEM.IDLE_RPM,
        Math.min(GEAR_SYSTEM.MAX_RPM, rpm));
}, []);

📚 개념 설명: RPM 계산의 물리적 의미

RPM 계산은 차량의 현재 상태를 정확히 반영하는 핵심 시스템입니다:

  1. 기어별 RPM 특성: 각 기어는 서로 다른 RPM 범위를 가집니다. 낮은 기어에서는 같은 속도에서도 더 높은 RPM이 필요합니다.

  2. 공회전 RPM: 엔진이 최소한의 회전을 유지하는 RPM으로, 일반적으로 800~1000 RPM 범위입니다. 이는 엔진이 정지하지 않고 안정적으로 작동하는 최소 회전수입니다.

  3. 최대 RPM: 엔진이 안전하게 작동할 수 있는 최대 회전수로, 일반 차량은 6000~7000 RPM, 고성능 차량은 8000~9000 RPM까지 올라갑니다.

  4. RPM 제한의 중요성: 너무 낮은 RPM에서는 엔진이 불안정하고, 너무 높은 RPM에서는 엔진 손상의 위험이 있습니다.

RPM과 엔진 성능의 관계:

  • 저 RPM: 낮은 연료 소비, 안정적인 작동
  • 중간 RPM: 최적의 토크와 연료 효율의 균형
  • 고 RPM: 최대 출력, 높은 연료 소비

3.1.2 RPM 업데이트 로직

// 현실적인 RPM 업데이트 (프레임당 제한)
const updateRPM = useCallback((speed, throttle) => {
    const targetRPM = calculateRPM(speed, safeGear);

    if (throttle > 0) {
        // 가속 시 RPM 증가 (프레임당 제한)
        setEngineRPM(prev => {
            const rpmDiff = targetRPM - prev;
            const maxIncrease = GEAR_SYSTEM.RPM_INCREASE_PER_FRAME;
            const actualIncrease = Math.min(Math.abs(rpmDiff), maxIncrease);

            return Math.min(GEAR_SYSTEM.MAX_RPM, prev + actualIncrease);
        });
    } else {
        // 감속 시 RPM 감소 (천천히)
        setEngineRPM(prev => Math.max(GEAR_SYSTEM.IDLE_RPM,
            prev * GEAR_SYSTEM.RPM_DECAY_RATE));
    }
}, [currentGear, calculateRPM]);

📚 개념 설명: RPM 변화의 현실적 모델링

실제 엔진의 RPM 변화는 순간적이지 않고 점진적으로 일어납니다:

  1. 엔진 관성: 엔진의 회전 부품들(크랭크샤프트, 피스톤 등)의 관성 때문에 RPM 변화가 점진적으로 일어납니다.

  2. 연료 분사 지연: 스로틀 입력과 실제 연료 분사 사이에는 약간의 지연이 있습니다.

  3. 공기 흡입: 스로틀 밸브의 개폐와 공기 흡입량 변화에도 시간이 필요합니다.

  4. 프레임당 제한: 게임에서는 60fps로 실행되므로, 프레임당 RPM 변화량을 제한하여 현실적인 변화를 구현합니다.

RPM 변화 패턴:

  • 가속 시: 목표 RPM까지 점진적으로 증가
  • 감속 시: 공회전 RPM까지 천천히 감소
  • 급격한 변화 방지: 엔진 손상과 비현실적 동작 방지

3.2 변속 시스템 구현

3.2.1 자동 변속 로직

// 자동 변속 로직 - 안전한 범위 제한
const autoShift = useCallback((currentRPM, currentSpeed) => {
    const now = Date.now();
    if (now - lastShiftTime < GEAR_SYSTEM.AUTO_SHIFT_DELAY) return;

    // N(0)이나 R(1)에서는 자동 변속하지 않음
    if (safeGear === 0 || safeGear === 1) return;

    const optimalRPM = GEAR_SYSTEM.OPTIMAL_SHIFT_RPM[safeGear];

    // 업시프트 (고 RPM에서 상위 기어로)
    if (currentRPM > optimalRPM * 0.8 && safeGear < 7) {
        const newGear = safeGear + 1;
        if (newGear <= 7) {
            setCurrentGear(newGear);
            setLastShiftTime(now);
        }
        return;
    }

    // 다운시프트 (낮은 RPM에서 하위 기어로)
    if (currentRPM < optimalRPM * 0.5 && safeGear > 2) {
        const newGear = safeGear - 1;
        if (newGear >= 2) {
            setCurrentGear(newGear);
            setLastShiftTime(now);
        }
        return;
    }
}, [currentGear, lastShiftTime]);

📚 개념 설명: 자동 변속의 원리와 전략

자동 변속은 엔진의 최적 성능 구간을 유지하기 위한 핵심 시스템입니다:

  1. 업시프트(Up Shift): 현재 기어에서 RPM이 너무 높아질 때 상위 기어로 변속합니다. 이는 엔진을 과부하로부터 보호하고 연료 효율을 높입니다.

  2. 다운시프트(Down Shift): RPM이 너무 낮아져서 엔진이 불안정해질 때 하위 기어로 변속합니다. 이는 가속력을 회복하고 엔진 브레이킹을 제공합니다.

  3. 최적 변속 RPM: 각 기어마다 최적의 성능을 발휘할 수 있는 RPM 범위가 있습니다. 일반적으로 최대 토크 RPM의 80%에서 업시프트, 50%에서 다운시프트합니다.

  4. 변속 지연: 연속적인 변속을 방지하기 위해 변속 후 일정 시간 동안 추가 변속을 제한합니다.

변속 타이밍의 중요성:

  • 너무 일찍 변속: 가속력 손실, 엔진 부하 증가
  • 너무 늦게 변속: 연료 소비 증가, 엔진 손상 위험
  • 적절한 타이밍: 최적의 성능과 효율성의 균형

3.2.2 수동 변속 시스템

// 수동 변속 (순차적 변속 보장)
const manualShift = useCallback((direction) => {
    const now = Date.now();
    if (now - lastShiftTime < GEAR_SYSTEM.MANUAL_SHIFT_DELAY) return;

    if (direction === 'up' && currentGear < 7) {
        const newGear = currentGear + 1;
        if (newGear <= 7) {
            setCurrentGear(newGear);
            setLastShiftTime(now);
        }
    } else if (direction === 'down' && currentGear > 0) {
        const newGear = currentGear - 1;
        if (newGear >= 0) {
            setCurrentGear(newGear);
            setLastShiftTime(now);
        }
    }
}, [currentGear, lastShiftTime]);

📚 개념 설명: 수동 변속의 기계적 원리

수동 변속은 운전자가 직접 기어를 선택하는 시스템으로, 기계적 제약과 안전성을 고려합니다:

  1. 순차적 변속: 실제 수동 변속기는 한 번에 하나의 기어만 변경할 수 있습니다. 1단에서 3단으로 직접 건너뛸 수 없고, 반드시 2단을 거쳐야 합니다.

  2. 변속 쿨다운: 기어 변경 후 일정 시간 동안 추가 변속을 제한합니다. 이는 변속기 손상 방지와 현실적인 조작감을 제공합니다.

  3. 기어 범위 제한: N(0), R(1), 1-6단(2-7)의 범위를 벗어나지 않도록 제한합니다.

  4. 안전성 검증: 유효하지 않은 기어 값이 감지되면 자동으로 안전한 값으로 수정합니다.

수동 변속의 장점:

  • 정밀한 제어: 운전자가 원하는 타이밍에 정확한 기어 선택
  • 연료 효율: 상황에 맞는 최적 기어 선택으로 연료 절약
  • 엔진 브레이킹: 하위 기어로 변속하여 엔진 브레이킹 활용
  • 주행 재미: 운전의 재미와 몰입감 향상

3.3 중립(N) 및 후진(R) 기어 시스템

3.3.1 중립 기어 구현

// 중립 기어 특성
- 엔진 동력이 바퀴로 전달되지 않음
- RPM은 유지되지만 속도 변화 없음
- 브레이크 없이도 자연 감속
- 다른 기어로의 자유로운 전환 가능

📚 개념 설명: 중립 기어의 물리적 의미

중립(Neutral) 기어는 엔진과 구동계를 분리하는 특별한 상태입니다:

  1. 동력 전달 차단: 클러치가 분리되어 엔진의 회전력이 바퀴로 전달되지 않습니다. 이는 엔진이 작동 중이어도 차량이 움직이지 않는 상태입니다.

  2. RPM 독립성: 엔진 RPM은 스로틀 입력에 따라 변화하지만, 차량 속도에는 영향을 주지 않습니다.

  3. 자연 감속: 엔진 브레이킹이 없어서 차량이 관성에 의해 자연스럽게 감속합니다.

  4. 기어 전환의 중간점: 다른 기어로 전환할 때 반드시 거쳐야 하는 중간 상태입니다.

중립 기어의 활용:

  • 정차 시: 엔진을 정지시키지 않고 대기
  • 기어 전환: 다른 기어로 전환하기 위한 중간 단계
  • 긴급 상황: 브레이크 고장 시 엔진 브레이킹 차단
  • 연료 절약: 신호 대기 시 중립으로 두어 연료 소비 최소화

3.3.2 후진 기어 시스템

// 후진 시스템 구현
if (window._carKeys?.down) {
    throttle = -1;
    if (newSpeed > 0) {
        // 전진 중일 때 점진적 감속
        const deceleration = 0.1;
        newSpeed = Math.max(newSpeed - deceleration, 0);
    } else if (newSpeed === 0) {
        // 정지 상태에서 후진 시작 (기어를 R로 변경)
        if (gearSystem.currentGear !== 1) {
            gearSystem.setCurrentGear(1); // R 기어로 변경
        }
        newSpeed = Math.max(newSpeed - 1.5, -8); // 후진 최고속도 -8
    } else {
        // 이미 후진 중일 때
        newSpeed = Math.max(newSpeed - 1.5, -8);
    }
}

📚 개념 설명: 후진 기어의 기계적 특성

후진(Reverse) 기어는 차량을 반대 방향으로 움직이게 하는 특별한 기어입니다:

  1. 기어비 특성: 후진 기어는 일반적으로 1단과 비슷한 높은 기어비를 가집니다. 이는 제한된 공간에서 강한 토크를 제공하기 위함입니다.

  2. 속도 제한: 후진은 안전상의 이유로 전진보다 낮은 최고 속도로 제한됩니다. 일반적으로 10-15 km/h 정도입니다.

  3. 기어 전환 순서: 후진으로 가기 위해서는 반드시 정지 상태에서 기어를 변경해야 합니다. 전진 중에 후진으로 직접 전환하는 것은 기계적으로 불가능합니다.

  4. 안전 장치: 현대 자동차에는 후진 중 전진으로의 급격한 전환을 방지하는 안전 장치가 있습니다.

후진 기어의 활용:

  • 주차: 좁은 공간에서의 정밀한 조작
  • 방향 전환: 좁은 공간에서의 방향 변경
  • 긴급 상황: 전진이 불가능한 상황에서의 탈출
  • 안전 주의: 후진 시 주변 환경을 더욱 주의 깊게 확인

🎛️ 기어 시스템 설계 및 구현

4.1 기어 상태 관리

4.1.1 기어 시스템 Hook

function useGearSystem() {
    const [currentGear, setCurrentGear] = useState(0); // N(중립)으로 시작
    const [engineRPM, setEngineRPM] = useState(GEAR_SYSTEM.IDLE_RPM);
    const [isAutoShift, setIsAutoShift] = useState(true);
    const [manualShiftMode, setManualShiftMode] = useState(false);
    const [lastShiftTime, setLastShiftTime] = useState(0);
    const [gearDisplay, setGearDisplay] = useState('N');
    const [isInitialized, setIsInitialized] = useState(false);

    // 기어 값 유효성 검사 및 수정 (무한 루프 방지)
    useEffect(() => {
        if (currentGear < 0 || currentGear > 7) {
            console.warn('Invalid gear value detected:', currentGear, 'resetting to N(0)');
            if (currentGear !== 0) {
                setCurrentGear(0);
            }
        }
    }, [currentGear]);

    return {
        currentGear,
        engineRPM,
        isAutoShift,
        manualShiftMode,
        gearDisplay,
        autoShift,
        manualShift,
        updateRPM,
        setIsAutoShift,
        setManualShiftMode,
        setCurrentGear,
        getCurrentGear: () => currentGear
    };
}

4.1.2 기어 표시 시스템

// 기어 표시 업데이트 (N, R, 1-6단)
useEffect(() => {
    if (currentGear === 0) {
        setGearDisplay('N'); // 중립
    } else if (currentGear === 1) {
        setGearDisplay('R'); // 후진
    } else if (currentGear >= 2 && currentGear <= 7) {
        setGearDisplay((currentGear - 1).toString()); // 1-6단 표시
    } else {
        console.warn('Invalid gear detected, resetting to N');
        setCurrentGear(0);
        setGearDisplay('N');
    }
}, [currentGear]);

4.2 기어별 속도 제한 시스템

4.2.1 기어별 최대 속도 적용

// 현실적인 가속/감속/후진 (기어별 속도 제한 적용)
if (window._carKeys?.up) {
    throttle = 1;
    if (newSpeed >= 0) {
        // 기어 유효성 검사 및 동기화
        const actualGear = gearSystem.getCurrentGear ? gearSystem.getCurrentGear() : gearSystem.currentGear;
        const currentGear = Math.max(0, Math.min(7, actualGear || 0));
        const maxSpeedKMH = GEAR_SYSTEM.MAX_SPEED_PER_GEAR[currentGear] || 85;
        const maxSpeedGame = maxSpeedKMH / 10; // KM/h를 게임 속도로 변환

        // 현실적인 기어비 시스템
        const gearAccelerationRates = {
            0: 0.00, // N(중립): 엔진 동력 전달 안됨
            1: 0.10, // R(후진): 후진 가속
            2: 0.15, // 1단: 가장 빠른 가속
            3: 0.12, // 2단: 빠른 가속
            4: 0.08, // 3단: 중간 가속
            5: 0.05, // 4단: 느린 가속
            6: 0.03, // 5단: 매우 느린 가속
            7: 0.02  // 6단: 가장 느린 가속
        };

        const acceleration = gearAccelerationRates[currentGear] || 0.00;

        // 점진적 가속 (관성 고려)
        const targetSpeed = maxSpeedGame;
        const speedDiff = targetSpeed - newSpeed;
        const actualAcceleration = Math.min(acceleration, Math.abs(speedDiff) * 0.1);

        if (speedDiff > 0) {
            newSpeed = Math.min(newSpeed + actualAcceleration, targetSpeed);
        }
    }
}

4.3 변속 안전성 시스템

4.3.1 무한 루프 방지

// 기어 상태 안정화 (무한 루프 방지)
useEffect(() => {
    if (currentGear !== 0 && (currentGear < 1 || currentGear > 6)) {
        console.warn('Gear stabilization: invalid gear', currentGear, '-> 1');
        setCurrentGear(1);
    }
}, []); // 의존성 배열을 비워서 한 번만 실행

4.3.2 변속 쿨다운 시스템

// 변속 지연시간 설정
const GEAR_SYSTEM = {
    AUTO_SHIFT_DELAY: 1000, // 자동 변속 지연시간 (ms)
    MANUAL_SHIFT_DELAY: 300, // 수동 변속 쿨다운 (ms)
    RPM_INCREASE_PER_FRAME: 50, // 프레임당 최대 RPM 증가량
    RPM_DECAY_RATE: 0.98, // RPM 감소율
};

🔄 RPM & 토크 시스템

5.1 RPM 관리 시스템

5.1.1 RPM 계산 공식

// RPM 계산의 수학적 기반
RPM = (속도 × 기어비 × 60) / (2π × 바퀴반지름 × 종감속비)

// 실제 구현
const speedKMH = Math.abs(speed) * 10; // 게임 속도를 KM/h로 변환
const gearSpeedRatio = GEAR_SYSTEM.GEAR_SPEED_RATIO[gear];
const rpm = speedKMH / gearSpeedRatio;

const result = Math.max(GEAR_SYSTEM.IDLE_RPM,
    Math.min(GEAR_SYSTEM.MAX_RPM, rpm));

📚 개념 설명: RPM 계산의 수학적 원리

RPM 계산은 차량의 물리적 특성을 정확히 반영하는 복잡한 수학적 과정입니다:

  1. 단위 변환: 게임 내 속도 단위를 실제 물리 단위(km/h)로 변환합니다. 이는 현실적인 계산을 위해 필수적입니다.

  2. 기어비 적용: 각 기어의 기어비를 적용하여 실제 엔진 RPM을 계산합니다. 기어비가 높을수록 같은 속도에서 더 높은 RPM이 필요합니다.

  3. 물리적 제약: 계산된 RPM이 엔진의 물리적 한계(공회전 RPM ~ 최대 RPM)를 벗어나지 않도록 제한합니다.

  4. 비선형 관계: RPM과 속도의 관계는 선형이 아닙니다. 기어비, 바퀴 크기, 종감속비 등 여러 요인이 복합적으로 작용합니다.

수학적 예시:

  • 속도: 50 km/h, 3단 기어(기어비 1.5)
  • RPM = (50 × 1.5 × 60) / (2π × 0.33 × 3.2) ≈ 2,150 RPM
  • 이는 3단에서 50 km/h로 주행할 때의 실제 RPM입니다.

5.1.2 RPM 변화 제한

// RPM 변화 제한 (현실적 구현)
if (throttle > 0) {
    setEngineRPM(prev => {
        const rpmDiff = targetRPM - prev;
        const maxIncrease = GEAR_SYSTEM.RPM_INCREASE_PER_FRAME;
        const actualIncrease = Math.min(Math.abs(rpmDiff), maxIncrease);

        return Math.min(GEAR_SYSTEM.MAX_RPM, prev + actualIncrease);
    });
} else {
    // 감속 시 RPM 감소 (천천히)
    setEngineRPM(prev => Math.max(GEAR_SYSTEM.IDLE_RPM,
        prev * GEAR_SYSTEM.RPM_DECAY_RATE));
}

5.2 토크 시스템 설계

5.2.1 토크 맵 개념

// 토크 맵 (RPM 구간별 토크 값)
const TORQUE_MAP = {
    IDLE_RPM: 800,    // 공회전 RPM
    PEAK_TORQUE_RPM: 3000,  // 최대 토크 RPM
    MAX_RPM: 6000,    // 최대 RPM

    // RPM 구간별 토크 계수 (0.0 ~ 1.0)
    getTorqueCoefficient: (rpm) => {
        if (rpm < 800) return 0.0;
        if (rpm < 1500) return 0.3;
        if (rpm < 2500) return 0.7;
        if (rpm < 3500) return 1.0;  // 최대 토크
        if (rpm < 4500) return 0.9;
        if (rpm < 5500) return 0.7;
        if (rpm < 6000) return 0.5;
        return 0.3; // 레드라인 이후
    }
};

📚 개념 설명: 토크 맵의 엔진 특성

토크 맵은 엔진의 성능 특성을 RPM 구간별로 정확히 모델링한 것입니다:

  1. 토크 곡선의 특성: 실제 엔진의 토크는 RPM에 따라 비선형적으로 변화합니다. 낮은 RPM에서는 토크가 낮고, 중간 RPM에서 최대값을 가진 후, 높은 RPM에서는 다시 감소합니다.

  2. 최대 토크 지점: 보통 2000~4000 RPM에서 최대 토크가 발생합니다. 이 구간에서 차량의 가속력이 가장 강합니다.

  3. 공회전 구간: 800 RPM 이하에서는 엔진이 불안정하므로 토크를 0으로 설정합니다.

  4. 레드라인 이후: 최대 RPM을 초과하면 엔진 손상의 위험이 있으므로 토크를 급격히 감소시킵니다.

토크 맵의 실제 의미:

  • 저 RPM: 연료 효율은 좋지만 가속력 부족
  • 중간 RPM: 최적의 토크와 효율의 균형
  • 고 RPM: 최대 출력이지만 연료 소비 증가
  • 최대 RPM: 엔진 보호를 위한 제한 구간

5.2.2 출력 계산 시스템

// 출력 계산 (토크 × 각속도)
const calculatePower = (torque, rpm) => {
    const angularVelocity = (rpm * 2 * Math.PI) / 60; // rad/s
    const angularVelocity = (rpm * 2 * Math.PI) / 60; // rad/s
    const power = torque * angularVelocity; // Watt
    return power / 1000; // kW로 변환
};

// 실제 출력 = 토크 × 각속도 × 효율
const actualPower = calculatePower(torque, rpm) * efficiency;

📚 개념 설명: 출력 계산의 물리학

출력(Power)은 엔진이 단위 시간당 수행할 수 있는 일의 양을 나타냅니다:

  1. 출력 공식: P = T × ω (출력 = 토크 × 각속도)

    • T: 토크 (Nm)
    • ω: 각속도 (rad/s)
    • P: 출력 (Watt)
  2. 각속도 계산: ω = (RPM × 2π) / 60

    • RPM을 라디안/초 단위로 변환
    • 2π는 한 바퀴(360도)를 라디안으로 표현
    • 60으로 나누어 분당 회전수를 초당 회전수로 변환
  3. 단위 변환: Watt를 kW로 변환하여 일반적으로 사용되는 단위로 표시

  4. 효율 고려: 실제 출력은 이론적 출력에 효율을 곱한 값입니다.

출력과 토크의 관계:

  • 저 RPM: 토크는 높지만 출력은 낮음 (각속도가 낮음)
  • 중간 RPM: 토크와 출력이 균형을 이룸
  • 고 RPM: 토크는 감소하지만 출력은 최대 (각속도가 높음)
  • 최대 출력: 보통 최대 토크보다 높은 RPM에서 발생

5.3 엔진 응답성 시스템

5.3.1 스로틀 응답

// 스로틀 응답 시스템
const throttleResponse = (throttleInput, currentRPM) => {
    const baseTorque = TORQUE_MAP.getTorqueCoefficient(currentRPM);
    const throttleTorque = baseTorque * throttleInput;

    // 엔진 응답 지연 (현실적 구현)
    const responseDelay = 0.1; // 100ms 지연
    return throttleTorque * (1 - responseDelay);
};

📚 개념 설명: 스로틀 응답의 기계적 특성

스로틀 응답은 엔진이 스로틀 입력에 반응하는 방식을 모델링한 것입니다:

  1. 스로틀 밸브: 스로틀 페달을 밟으면 스로틀 밸브가 열려 공기 흡입량이 증가합니다. 이는 연료 분사량과 함께 엔진 출력을 결정합니다.

  2. 응답 지연: 실제 엔진은 스로틀 입력에 즉시 반응하지 않습니다. 공기 흡입, 연료 분사, 연소, 배기 과정을 거치므로 약간의 지연이 발생합니다.

  3. RPM 의존성: 같은 스로틀 입력이라도 현재 RPM에 따라 다른 토크를 발생시킵니다. 이는 토크 맵에 의해 결정됩니다.

  4. 비선형 응답: 스로틀 입력과 실제 토크는 선형 관계가 아닙니다. 엔진의 특성에 따라 비선형적으로 변화합니다.

스로틀 응답의 실제 의미:

  • 즉시 응답: 스포츠카나 레이싱 엔진은 빠른 응답
  • 부드러운 응답: 일반 승용차는 안정적인 응답
  • 터보 지연: 터보차저 엔진은 추가적인 지연 발생
  • 전자 제어: 현대 엔진은 ECU가 응답을 최적화

5.3.2 엔진 브레이킹

// 엔진 브레이킹 (스로틀 off 시)
const engineBraking = (currentSpeed, currentGear) => {
    if (currentGear === 0) return 0; // 중립에서는 엔진 브레이킹 없음

    const engineBrakingForce = 0.02; // 엔진 브레이킹 계수
    const gearMultiplier = currentGear * 0.1; // 기어가 낮을수록 브레이킹 강함

    return engineBrakingForce * gearMultiplier;
};

📚 개념 설명: 엔진 브레이킹의 물리적 원리

엔진 브레이킹은 스로틀을 놓았을 때 엔진이 차량을 감속시키는 현상입니다:

  1. 기계적 저항: 스로틀이 닫히면 엔진의 공기 흡입이 제한되어 내부 압축 저항이 발생합니다. 이는 차량의 운동 에너지를 엔진의 회전 에너지로 변환하여 감속 효과를 만듭니다.

  2. 기어별 차이: 낮은 기어(1단, 2단)에서 엔진 브레이킹 효과가 더 강합니다. 이는 기어비가 높아서 엔진의 저항이 바퀴에 더 크게 전달되기 때문입니다.

  3. 중립에서의 차이: 중립 기어에서는 엔진과 구동계가 분리되어 있으므로 엔진 브레이킹이 발생하지 않습니다.

  4. 연료 절약: 엔진 브레이킹 중에는 연료 분사가 최소화되어 연료 소비가 줄어듭니다.

엔진 브레이킹의 활용:

  • 코너링: 코너 진입 전 감속에 활용
  • 연료 절약: 하강로에서 연료 소비 최소화
  • 브레이크 보호: 브레이크 패드 마모 감소
  • 안전 주행: 급격한 감속 방지로 안정성 향상

📊 연구 결과 및 성능 평가

6.1 구현 완료 사항

6.1.1 핵심 기능 구현

  • 현실적 RPM 시스템: 속도 ↔ RPM 수학적 관계 구현
  • 기어별 속도 제한: 각 기어마다 최대 속도 적용
  • 점진적 가속/감속: 관성을 고려한 자연스러운 속도 변화
  • 중립(N) & 후진(R) 기어: 현실적인 기어 시스템
  • 자동/수동 변속: 안전한 변속 로직 구현
  • 엔진 브레이킹: 스로틀 off 시 자연 감속
  • 변속 쿨다운: 무한 루프 방지 시스템

6.1.2 기술적 성과

// 성능 지표
- 프레임 레이트: 60fps (안정적)
- RPM 계산 정확도: 95% 이상
- 변속 응답 시간: < 100ms
- 기어 동기화 정확도: 100%
- 메모리 사용량: 최적화됨

6.2 물리 엔진 성능 분석

6.2.1 현실성 평가

  • 속도 변화: 0-1 스위치가 아닌 점진적 변화 구현
  • 기어 시스템: N, R, 1-6단 완전 구현
  • RPM 관리: 엔진 특성 반영한 현실적 RPM
  • 변속 타이밍: 최적 RPM 기반 자동 변속
  • 충돌 처리: 속도 감소와 반사 물리 구현

6.2.2 사용자 경험 개선

  • 직관적 조작: 현실과 유사한 기어 시스템
  • 시각적 피드백: RPM, 기어, 속도 실시간 표시
  • 안정성: 무한 루프 및 오류 방지
  • 반응성: 즉각적인 입력 응답

6.3 현재 한계 및 개선점

6.3.1 기술적 한계

  1. 토크 맵 단순화: 현재는 기본적인 토크 계산만 구현
  2. 공기역학 부재: 공기 저항, 다운포스 등 미구현
  3. 타이어 물리 부족: 그립, 슬립, 마찰력 미구현
  4. 서스펜션 시스템: 차체 롤링, 피칭 등 미구현

6.3.2 향후 개선 방향

  1. 고급 토크 맵: RPM 구간별 정교한 토크 곡선
  2. 공기역학 시스템: 속도에 따른 공기 저항 구현
  3. 타이어 물리: 그립, 슬립, 온도 시스템
  4. 서스펜션: 차체 동역학 시뮬레이션

🚀 향후 개발 로드맵

7.1 단기 목표 (1-2개월)

7.1.1 고급 물리 엔진 (Phase 1)

// 1. 토크 맵 고도화
const ADVANCED_TORQUE_MAP = {
    // RPM 구간별 정교한 토크 곡선
    getTorqueCurve: (rpm) => {
        // 실제 엔진 특성 반영
        return calculateRealisticTorque(rpm);
    }
};

// 2. 공기역학 시스템
const AERODYNAMICS = {
    dragCoefficient: 0.3,
    frontalArea: 2.0,
    calculateDrag: (speed) => {
        return 0.5 * dragCoefficient * frontalArea * speed * speed;
    }
};

// 3. 타이어 물리
const TIRE_PHYSICS = {
    gripCoefficient: 0.8,
    temperature: 80, // Celsius
    calculateGrip: (load, temperature) => {
        return gripCoefficient * load * (temperature / 100);
    }
};

7.1.2 AI 드라이버 고도화 (Phase 2)

// 1. 트랙 분석 시스템
const TRACK_ANALYSIS = {
    analyzeCorners: (trackLayout) => {
        // 코너, 직선 구간 자동 분류
        return classifyTrackSections(trackLayout);
    },
    calculateOptimalLine: (corners) => {
        // Apex 기반 최적 라인 생성
        return generateRacingLine(corners);
    }
};

// 2. 전략적 변속 시스템
const STRATEGIC_SHIFTING = {
    calculateOptimalShiftPoints: (trackSections) => {
        // 구간별 최적 변속 타이밍 계산
        return determineShiftTiming(trackSections);
    }
};

7.2 중기 목표 (3-6개월)

7.2.1 Machine Learning 통합 (Phase 3)

// 1. 데이터 수집 시스템
const DATA_COLLECTION = {
    collectDrivingData: (frameData) => {
        // 프레임별 주행 데이터 수집
        return {
            position: frameData.position,
            speed: frameData.speed,
            gear: frameData.gear,
            rpm: frameData.rpm,
            throttle: frameData.throttle,
            steering: frameData.steering,
            timestamp: Date.now()
        };
    }
};

// 2. 학습 모델 개발
const ML_MODEL = {
    trainOptimalDriving: (dataset) => {
        // 최적 주행 패턴 학습
        return trainModel(dataset);
    },
    predictOptimalAction: (currentState) => {
        // 실시간 최적 행동 예측
        return model.predict(currentState);
    }
};

7.2.2 고급 AI 시스템 (Phase 4)

// 1. 강화학습 시스템
const REINFORCEMENT_LEARNING = {
    rewardFunction: (lapTime, consistency, safety) => {
        // 랩타임 최소화 보상 시스템
        return calculateReward(lapTime, consistency, safety);
    },
    policyOptimization: (state, action) => {
        // 정책 최적화
        return optimizePolicy(state, action);
    }
};

// 2. 자동 튜닝 시스템
const AUTO_TUNING = {
    hyperparameterOptimization: () => {
        // 하이퍼파라미터 자동 최적화
        return optimizeHyperparameters();
    }
};

7.3 장기 목표 (6개월 이상)

7.3.1 완전한 F1 시뮬레이션 (Phase 5)

// 1. 고급 차량 물리
const ADVANCED_VEHICLE_PHYSICS = {
    suspensionSystem: {
        // 서스펜션 동역학
        calculateRoll: (lateralForce) => { /* 구현 */ },
        calculatePitch: (longitudinalForce) => { /* 구현 */ }
    },
    tireModel: {
        // Pacejka 타이어 모델
        calculateSlip: (slipAngle, slipRatio) => { /* 구현 */ }
    }
};

// 2. 환경 시뮬레이션
const ENVIRONMENT_SIMULATION = {
    weatherSystem: {
        // 날씨에 따른 그립 변화
        calculateGripModifier: (weather) => { /* 구현 */ }
    },
    trackEvolution: {
        // 트랙 상태 변화
        calculateTrackGrip: (usage, temperature) => { /* 구현 */ }
    }
};

7.3.2 멀티플레이어 & 경쟁 시스템 (Phase 6)

// 1. 멀티플레이어 시스템
const MULTIPLAYER = {
    realTimeRacing: {
        // 실시간 멀티플레이어 레이싱
        synchronizePositions: (players) => { /* 구현 */ }
    },
    leaderboardSystem: {
        // 랩타임 리더보드
        updateLeaderboard: (playerData) => { /* 구현 */ }
    }
};

// 2. AI vs AI 경쟁
const AI_COMPETITION = {
    tournamentSystem: {
        // AI 토너먼트 시스템
        runAITournament: (aiModels) => { /* 구현 */ }
    }
};

7.4 개발 우선순위 매트릭스

기능난이도사용자 가치개발 우선순위
고급 토크 맵중간높음1순위
공기역학 시스템높음중간2순위
타이어 물리높음높음1순위
AI 드라이버 고도화중간높음1순위
Machine Learning높음매우 높음2순위
멀티플레이어높음중간3순위

7.5 성공 지표

7.5.1 기술적 지표

  • 물리 정확도: 실제 차량과 90% 이상 유사성
  • AI 성능: 인간 수준의 랩타임 달성
  • 시스템 안정성: 99.9% 이상 가동률
  • 사용자 만족도: 4.5/5.0 이상

7.5.2 연구 지표

  • 논문 발표: 국제 학회 논문 2편 이상
  • 오픈소스 기여: GitHub 스타 100개 이상
  • 커뮤니티 참여: 개발자 커뮤니티 활성화

🎯 결론

본 연구는 F1 레이싱 게임에서 현실적인 엔진과 변속 시스템을 성공적으로 구현하였다. 수학적 기반을 바탕으로 한 물리 엔진은 사용자에게 직관적이면서도 현실적인 레이싱 경험을 제공하며, 향후 Machine Learning 기반의 고급 AI 시스템 개발을 위한 견고한 기반을 마련하였다.

7.6 연구의 의의

7.6.1 학술적 기여

  • 게임 물리 시뮬레이션과 AI 연구의 융합 방법론 제시
  • 실시간 물리 계산과 AI 통합 시스템 설계
  • 교육용 레이싱 시뮬레이터 개발 프레임워크 제시

7.6.2 실용적 기여

  • 현실적인 차량 물리 시뮬레이션 구현
  • AI 드라이버 개발을 위한 테스트베드 구축
  • 게임 개발과 AI 연구의 융합 사례 제시

7.7 마무리

2편에서는 엔진과 변속 시스템의 수학적 기반부터 현실적 구현까지를 다루었다. 다음 단계에서는 고급 물리 엔진과 Machine Learning 기반 AI 시스템 개발을 통해 완전한 F1 레이싱 시뮬레이션 환경을 구현할 예정이다.


📚 참고 문헌

  • Vehicle Dynamics Theory and Application (Gillespie)
  • Race Car Vehicle Dynamics (Milliken & Milliken)
  • Machine Learning for Game AI (Buckland)
  • Real-Time Physics Simulation (Eberly)

🔗 관련 링크


본 연구는 F1 레이싱 AI 개발 프로젝트의 2편으로, 엔진과 변속 시스템 구현에 중점을 두었다. 3편에서는 고급 물리 엔진과 Machine Learning 모델 구현에 대해 다룰 예정이다.

profile
Hello World

0개의 댓글