Skip to navigation


Driving model: ApplyDrivingModel

Name: ApplyDrivingModel [Show more] Type: Subroutine Category: Driving model Summary: Apply the driving model to the player's car Deep dive: An overview of the driving model The core driving model
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * MainDrivingLoop (Part 2 of 5) calls ApplyDrivingModel
.ApplyDrivingModel LDA playerYawAngleHi \ Set (A X) = (playerYawAngleHi playerYawAngleLo) LDX playerYawAngleLo JSR GetRotationMatrix \ Calculate the rotation matrix for rotating the \ player's yaw angle into the global 3D coordinate \ system, as follows: \ \ [ cosYawAngle 0 -sinYawAngle ] \ [ 0 1 0 ] \ [ sinYawAngle 0 cosYawAngle ] JSR RotateCoordToCar \ Rotate the player's delta vector from the 3D world \ coordinate system to the frame of reference of the \ player's car, putting the result into: \ \ [ xVelocity ] \ [ - ] \ [ zVelocity ] \ \ We ignore the y-coordinate as the calculations are \ all done along the ground LDA xVelocityLo \ Set (xPrevVelocityHi xPrevVelocityLo) STA xPrevVelocityLo \ = (xVelocityHi xVelocityLo) LDA xVelocityHi STA xPrevVelocityHi LDA zVelocityLo \ Set (A T) = (zVelocityHi zVelocityLo) STA T LDA zVelocityHi JSR Absolute16Bit \ Set (A T) = |A T| \ = |zVelocity| STA playerSpeedHi \ Set (playerSpeedHi playerSpeedLo) = (A T) LDA T \ = |zVelocity| STA playerSpeedLo LDY playerSpeedHi \ Set Y to the high byte of (playerSpeedHi \ playerSpeedLo) BNE dmod1 \ If the high byte is non-zero, jump to dmod1 to skip \ the following AND #%11110000 \ A contains playerSpeedLo, so this sets Y to the high TAY \ nibble of the low byte of (playerSpeedHi \ playerSpeedLo) .dmod1 STY playerMoving \ Store Y in playerMoving, which is zero if the player \ is not moving, non-zero if they are, so this denotes \ the player as moving if (playerSpeedHi playerSpeedLo) \ is non-zero, ignoring the bottom nibble of the \ low byte JSR ApplySpinYaw \ Calculate the following: \ \ xVelocity = xVelocity - (spinYawAngle * 0.34) \ \ xSpinVelocity = spinYawAngle * 0.52 JSR ApplyGrassOrTrack \ Apply the effects of driving and braking, depending on \ the current driving surface (grass or track) JSR ApplyEngine \ Apply the effects of the engine LDX #1 \ Set X = 1, so the call to ApplyTyresAndSkids processes \ the rear tyres JSR ApplyTyresAndSkids \ Calculate the forces on the rear tyres and apply skid \ forces and sound effects where applicable LDA xPrevVelocityLo \ Set (xVelocityHi xVelocityLo) to the x-coordinate of STA xVelocityLo \ the velocity vector from the previous iteration of the LDA xPrevVelocityHi \ main loop, which we stored in (xPrevVelocityHi STA xVelocityHi \ xPrevVelocityLo) LDA xVelocityLo \ Set (xVelocityHi xVelocityLo) CLC \ += (xSpinVelocityHi xSpinVelocityLo) ADC xSpinVelocityLo \ STA xVelocityLo \ starting with the low bytes LDA xVelocityHi \ And then the high bytes ADC xSpinVelocityHi STA xVelocityHi JSR ApplySteeringSpeed \ Calculate the following in parallel: \ \ zVelocity = zVelocity + xVelocity * steering \ \ xVelocity = xVelocity - zVelocity * steering LDX #0 \ Set X = 0, so the call to ApplyTyresAndSkids processes \ the front tyres JSR ApplyTyresAndSkids \ Calculate the forces on the front tyres and apply skid \ forces and sound effects where applicable JSR ApplySteeringForce \ Calculate the following in parallel: \ \ xTyreForceNose = xTyreForceNose \ + zTyreForceNose * steering \ \ zTyreForceNose = zTyreForceNose \ - xTyreForceNose * steering JSR ScaleTyreForces \ Calculate the following: \ \ spinYawDelta = (xTyreForceNose - xTyreForceRear) \ * 0.3 \ \ xTyreForceNose = xTyreForceNose >> 2 \ \ xTyreForceRear = xTyreForceRear >> 2 \ \ zTyreForceNose = zTyreForceNose >> 2 \ \ zTyreForceRear = zTyreForceRear >> 2 \ \ xPlayerAccel = (xTyreForceRear * 1.5 \ + xTyreForceNose) * 1.6 \ \ zPlayerAccel = (zTyreForceRear * 1.5 \ + zTyreForceNose) * 1.6 \ \ zTyreForceBoth = zPlayerAccelHi LDA heightAboveTrack \ If heightAboveTrack < 2, jump to dmod3 CMP #2 BCC dmod3 \ If we get here then heightAboveTrack >= 2 LDX #2 \ We now zero the three 16-bit bytes at spinYawDelta, \ xPlayerAccel and zPlayerAccel, so set a counter in X \ for the three variables LDA #0 \ Set A = 0 to use as the zero value .dmod2 STA spinYawDeltaLo,X \ Zero the X-th byte of (spinYawDeltaHi spinYawDeltaLo) STA spinYawDeltaHi,X DEX \ Decrement the variable counter BPL dmod2 \ Loop back until we have zeroed all three 16-bit \ variables .dmod3 JSR ApplyWingBalance \ Calculate the following: \ \ xPlayerAccel = xPlayerAccel \ - scaledSpeed * xPrevVelocityHi \ \ zPlayerAccel = zPlayerAccel \ - scaledSpeed \ * (wingBalance * playerSpeedHi + 2048) \ * abs(zVelocity) JSR RotateCarToCoord \ Rotate this vector: \ \ [ xPlayerAccel ] \ [ - ] \ [ zPlayerAccel ] \ \ from the frame of reference of the player's car into \ the 3D world coordinate system, putting the result \ into: \ \ [ xAcceleration ] \ [ - ] \ [ zAcceleration ] \ \ We ignore the y-coordinate as the calculations are \ all done along the ground JSR UpdateVelocity \ Calculate the following: \ \ xPlayerSpeed = xPlayerSpeed + xAcceleration << 5 \ \ zPlayerSpeed = zPlayerSpeed + zAcceleration << 3 \ \ spinYawAngle = spinYawAngle + spinYawDelta << 3 JSR ApplyDeltas \ Calculate the following: \ \ xPlayerCoord = xPlayerCoord + xPlayerSpeed * 2 \ \ zPlayerCoord = zPlayerCoord + zPlayerSpeed * 2 \ \ playerYawAngle = playerYawAngle + spinYawAngle JSR ApplyElevation \ Calculate changes in the car's elevation RTS \ Return from the subroutine