# Driving on grass

## What happens when you spill off the track into the lush green grass

This article details the extra calculations that the driving model performs when any part of the car is driving on grass. It is designed to be read alongside the core driving model calculations.

Note that the game knows if the car is on grass by checking the colour of two specific screen pixel bytes, one just to the left of the dashboard, and the other just to the right. If one of these pixel bytes is fully green, then we know that side of the car is on grass. The screen memory addresses for these two bytes are defined by the leftSurface and rightSurface configuration variables.

## Calculation 5: Calculate height of bumpy grass -----------------------------------------------

See code: ApplyGrassOrTrack

This is an explanation of calculation 5 in the driving model. It might help to see calculation 5 in context.

First, we check whether we have just hit the track verge, and if so, we set some variables so the car jumps and spins, as follows:

• If all the following are true:
• There is grass under at least one side of the car
• bumpyGrassHeight = 0
• heightAboveTrack = 0
• Bit 7 of playerDrift is set
then this means all of the following are also true:
• We have at least one wheel off the track
• We haven't already hit the grass, as the grass height is zero
• We aren't already jumping, as we are on the ground
• We are moving sideways pretty fast
In other words, we only just hit the verge, so we calculate the following to make the car jump and spin, with the jump being higher with higher speeds:
```  yGravityDelta = playerSpeedHi / 2

yJumpHeight = playerSpeedHi / 4

heightAboveTrack = heightAboveTrack + 1

spinYawAngleHi = spinYawAngleHi >> 1 with bit 7 set
```
We also make the crash/contact sound to indicate that we have hit the verge.

Second, if any part of the car is on the grass, then we set the height of the grass in bumpyGrassHeight to a random figure in the range 1 to 7 (with a higher number more likely at higher speeds). We do this on each iteration of the main driving loop, so while we are driving on grass, our height bumps up and down, with higher bumps the faster we are going. Specifically, we do this:

• If there is grass under at least one side of the car, then:
```  bumpyGrassHeight = random number in the range 1 to 7
that is higher with higher speeds
```
otherwise:
```  bumpyGrassHeight = 0
```

These variables are used in the jumps and drops calculation in the last step of the driving model.

## Calculation 6: Calculate wing and brake downward forces -------------------------------------------------------

See code: ApplyGrassOrTrack

This is an explanation of calculation 6 in the driving model. It might help to see calculation 6 in context.

If we are driving on grass on both sides of the car, then instead of the normal calculation, we set:

```  wingForce = wingForceGrass + brakeForce
```

where wingForceGrass is defined as 25 for the front wing and 26 for the rear wing. This cancels out the downward force that we normally get from the wings, and reduces the base downward force from wingForceTrack (53) to wingForceGrass (25 or 26). The result is a serious loss of grip.

## Calculation 17: Apply drag --------------------------

See code: ApplyWingBalance

This is an explanation of calculation 17 in the driving model. It might help to see calculation 17 in context.

If bumpyGrassHeight > 0, then we are already driving across grass, so we change the calculation so the acceleration reduces by twice the amount, as follows:

```  xPlayerAccel = xPlayerAccel - 2 * playerSpeedHi * xPrevVelocityHi
```
```  zPlayerAccel = zPlayerAccel - 2 * playerSpeedHi
* (wingBalance * playerSpeedHi + 2048)
* abs(zVelocity)
```

The effect is that driving on grass doubles the drag on the car, which leads to a noticeable loss of acceleration.