hero projektu Alfa romeo game
Strona główna/Blog/Alfa Romeo 3d Demo

Alfa Romeo 3d Demo

Arkadiusz Wawrzyniak

Arkadiusz Wawrzyniak

29 marca 2026 - 54 wyświetlenia - 3 min czytania

Udostępnij

Jak z prostego demo zrobiła się… gra

Zawsze zaczyna się niewinnie. „Zrobię szybkie demo modelu 3D auta. Nic wielkiego.”

No i potem wjeżdża mój perfekcjonizm i mówi:

„a co jeśli to jednak może być lepsze?”

I tak demo zaczyna rosnąć. Najpierw był model. Potem pomysł:

skoro już jest model… to czemu nie dodać free roam?

A skoro jest free roam:

  • scena
  • niebo
  • podłoże

HDRI, własny asfalt, pierwsze ruchy auta…
I w tym momencie już wiadomo — to nie będzie mały projekt.

Kliknij, aby powiększyć


Gdzie zaczęła się prawdziwa zabawa

Auto się ruszało. Super.

Ale:

  • koła nie mogą wyglądać sztucznie
  • kamera musi „czuć” auto
  • skręt nie może być binarny

No i wtedy wjeżdża fizyka.

Nie chciałem zrobić czegoś płaskiego.
Chciałem, żeby auto:

  • miało masę
  • reagowało na gaz i hamulec

pozwalało na kontrolowany poślizg

Fizyka — czyli gdzie zaczyna się magia

Zamiast prostego modelu ruchu zrobiłem system oparty o kilka kluczowych elementów:

  • slip angle (kąt poślizgu opony)
  • rozdzielenie przodu i tyłu
  • przeniesienie masy
  • ograniczenia przyczepności (traction circle)

Slip angle (czyli dlaczego auto w ogóle skręca)

text
const vLatFront = physics.lateralSpeed + physics.yawRate * halfWB
const vLatRear = physics.lateralSpeed - physics.yawRate * halfWB

let targetFrontSlip = 0
let targetRearSlip = 0

if (absForward > 0.1) {
  targetFrontSlip =
    Math.atan2(vLatFront, absForward) -
    physics.steeringAngle * Math.sign(physics.forwardSpeed)

  targetRearSlip = Math.atan2(vLatRear, absForward)
}


Tutaj dzieje się kluczowa rzecz:

  • przód i tył auta mają inne kąty poślizgu
  • to właśnie różnica między nimi decyduje, czy auto skręca stabilnie czy zaczyna uciekać tyłem

To jest fundament całego prowadzenia.



Płynne zachowanie opon (bez szarpania)

text
const slipRelaxationAlpha = 1 - Math.exp(-8 * dt)

physics.frontSlipAngle +=
  (targetFrontSlip - physics.frontSlipAngle) * slipRelaxationAlpha

physics.rearSlipAngle +=
  (targetRearSlip - physics.rearSlipAngle) * slipRelaxationAlpha

Bez tego:

  • wszystko byłoby natychmiastowe i nienaturalne

Dzięki temu:

  • opony „dochodziły” do swojego zachowania
  • auto jest przewidywalne i płynne

Zakres przyczepności

text
const frontLatAvailable = Math.sqrt(
  Math.max(0, 1.0 - Math.pow(frontLongUsage * 0.95, 2))
)

const rearLatAvailable = Math.sqrt(
  Math.max(0, 1.0 - Math.pow(rearLongUsage * 0.95, 2))
)

To ogranicza sytuacje typu:

  • pełne hamowanie + maksymalny skręt = zero konsekwencji

Tutaj:

  • im więcej hamujesz lub przyspieszasz
  • tym mniej masz przyczepności

Mamy podsterowność

Przeniesienie masy

text
const weightTransferLong =
  (longitudinalAccel * config.cgHeight) / config.wheelbase

physics.weightTransfer = THREE.MathUtils.lerp(
  physics.weightTransfer,
  weightTransferLong * 0.015,
  Math.min(1, 2 * dt)
)

Efekt:

  • przy hamowaniu przód „siada”
  • przy przyspieszaniu tył dostaje więcej przyczepności

Wizualnie bardzo tego nie widać ale wpływa mocno na prowadzenie.

Trik dla lepszego prowadzenia przy małych prędkościach

text
const lowSpeedBoost = speedPercent < 0.5
  ? THREE.MathUtils.lerp(
      config.lowSpeedGripBoost,
      1.0,
      speedPercent / 0.5
    )
  : 1.0

Problemem realistycznych parametrów fizyki przy nie realistycznej skali pojazdu była zerowa skrętność przy małych prędkościach.
Nie mogłem się tego pozbyć zmieniając wartości samego modelu opon.

Zatem przy niższych prędkościach zastosowałem trik aby zwiększyć sterowność.


Trail braking

text
const isTrailBraking =
  brakeUsage > 0.3 && steeringAmount > rotationThreshold

const brakingRearReduction = THREE.MathUtils.lerp(
  1.0,
  config.brakingRearGripReduction,
  rotationIntensity
)

To jedna z ważniejszych rzeczy pod klawiaturę.

Efekt:

  • hamujesz + skręcasz → tył zaczyna lekko rotować (albo mocno)
  • możesz „ustawić” auto do zakrętu

Geometryczna korekcja skrętu

text
const geometricYawRate =
  absForward > 0.1
    ? (physics.forwardSpeed * Math.tan(physics.steeringAngle)) /
      config.wheelbase
    : 0

const yawError = geometricYawRate - physics.yawRate
const desiredCorrAccel = yawError * config.geometricSpringRate

const clampedCorrAccel = THREE.MathUtils.clamp(
  desiredCorrAccel,
  -maxCorrAccel,
  maxCorrAccel
)

physics.yawRate += clampedCorrAccel * geometricBlend * dt

Dzięki temu auto skręca płynnie a nie gwałtownie jak w grach arcade.
Choć na klawiaturze i tak ciężko o ten efekt, to jazda jest zdecydowanie przyjemniejsza.

Adaptive damping

text
const effectiveLateralDamp = THREE.MathUtils.lerp(
  gripDamp,
  slideDamp,
  smoothstep(maxSaturation, 0.3, 1.0)
)

physics.lateralSpeed *= Math.max(
  0,
  1 - effectiveLateralDamp * dt
)

Efekt:

  • w normalnej jeździe auto jest stabilne
  • w poślizgu pozwala się „rozwinąć” driftowi i go kontrolować

Kliknij, aby powiększyć



Niech nastanie światłość

Model 3d jest dość ograniczony, również przez fakt formatu .glb
W związku z tym mój pomysł na włączanie świateł był niemożliwy do osiągnięcia tylko przy użyciu meshy odbijających światło.

Zamiast z nim walczyć, użyłem sprytnych rozwiązań:

  • emissive mesh’e do bloom
  • spotlighty do realnego oświetlenia
  • dodatkowe światła „spill” dla miękkiego efektu


Umieszczone idealnie w przestrzeni 3d względem modelu auta.

text
<mesh position={[-0.78, 0.72, 2.28]}>
  <sphereGeometry args={[0.03, 8, 8]} />
  <meshStandardMaterial
    emissive="#e8f4ff"
    emissiveIntensity={0}
    transparent
  />
</mesh>

Efekt:

  • światła wyglądają naturalnie
  • oświetlają scenę
  • mają głębię i intensywność

Wszystko razem

Do tego doszło:

  • drift
  • dym
  • dźwięk na bazie prawdziwych sampli Alfa Romeo
  • dynamiczna kamera
  • przechyły nadwozia
  • dopracowane detale

Z czegoś co miało być tylko eksperymentem z modelem 3d, zrobiła się prawie gra.

Kliknij, aby powiększyć


Dlaczego tak?

Bo nie uznaję półśrodków. Nie podpiszę się pod czymś, co jest „okej”.
Albo coś robię dobrze, albo wcale. I z każdym projektem ta poprzeczka idzie wyżej.

Dla klientów to oznacza jedno:
dostają rzeczy dopracowane w najmniejszych detalach.

Dla mnie…
no cóż — powiedzmy, że czasem moje życie poza projektami cierpi 😅

Możecie poupalać to dzieło sztuki tutaj:
https://alfaromeodemo.netlify.app/