Revs on the BBC Micro

# Car geometry: ProcessContact

```       Name: ProcessContact                                          [Show more]
Type: Subroutine
Category: Car geometry
Summary: Process collisions between the player and the other cars
Context: See this subroutine in context in the source code
References: This subroutine is called as follows:
* MainDrivingLoop (Part 2 of 5) calls ProcessContact

Returns:

V                    Bit 7 is set if there is a collision

.ProcessContact

LDA processContact     \ If processContact is zero then there no other cars
BEQ DrawObjectEdge-1   \ close enough to the player's car for there to be any
\ contact, so return from the subroutine (as
\ DrawObjectEdge-1 contains an RTS)

LDA #0                 \ Set processContact = 0 to reset the flag, so we only
STA processContact     \ check for contact when a car is flagged as being close

SEC                    \ Set bit 7 of V
ROR V

LDA #37                \ Set A = 37 - objectDistanceLo
SEC                    \
SBC objectDistanceLo   \ The value of (objectDistanceHi objectDistanceLo) is
\ left over from the last call to CheckForContact, which
\ was last called for the nearest car in front of us
\ when building object for the five cars in front of us,
\ from furthest to nearest, as part of this chain of
\ routines:
\
\   MoveAndDrawCars > BuildVisibleCar > BuildCarObjects
\                   > GetObjectAngles > CheckForContact
\
\ Note that BuildVisibleCar does get called once more at
\ the end of MoveAndDrawCars, for the car behind us, but
\ as that car is not visible, it doesn't set the object
\ distance
\
\ So, in short, objectDistanceLo is the low byte of the
\ distance between the player and the nearest car, which
\ is the car we want to process for a collision
\
\ This means that a higher value of A means a closer
\ collision, so this is effectively a measure of how
\ dangerous this collision is, in the range 0 to 37

BCS cont1              \ If the above subtraction didn't underflow then the
\ other car is at a distance of 37 or less, so jump to
\ cont1 to skip the following instruction

LDA #5                 \ The subtraction underflowed, so the other car is a bit
\ of a distance away, so set A = 5 so have a minor
\ collision

.cont1

ASL A                  \ Set A = A * 2
\
\ so the damage measure is now in the range 0 to 74

STA U                  \ Set U = A, so U now contains the damage measure in the
\ range 0 to 74

LDX collisionDriver    \ Set X to the driver number of the car being hit (the
\ "other car")

LDY currentPlayer      \ Set Y to the driver number of the current player

CMP #40                \ If A < 40, then the collision is not bad enough to
BCC cont2              \ push the other car off the track, so jump to cont2

LDA raceStarted        \ If bit 7 of raceStarted is clear then this is either
BPL cont2              \ a practice or qualifying lap, so jump to cont2 to skip
\ the following instruction

JSR PushCarOffTrack    \ If we get here then the collision is close enough to
\ push the other car off the track, and this is a race,
\ so we push the other car off the track and out of the
\ race

.cont2

LDA objYawAngleHi,X    \ Set A to the yaw angle for the other car minus the yaw
SEC                    \ angle for the player, which we will call dYawAngle
SBC playerYawAngleHi

ASL A                  \ Set A = A * 4
ASL A                  \       = dYawAngle * 4

PHP                    \ Push the N flag onto the stack, which contains the
\ sign of dYawAngle

LDA carSpeedHi,Y       \ Set A to the high byte of the player's speed

CPX #20                \ If the driver number of the other car is >= 20, then
BCS cont4              \ jump to cont4 as this is not a computer-controlled
\ driver, so we do not adjust its speed

CMP carSpeedHi,X       \ If the high byte of the player's speed is >= the high
BCS cont3              \ byte of the other driver's speed, jump to cont3 with
\ A containing the higher of the two speeds, so the
\ other car gets bumped to a slightly higher speed than
\ the faster car (by adding 12, as the C flag is set)

LDA carSpeedHi,X       \ Set A to the high byte of the other driver's speed, so
\ A now contains the higher of the two speeds

BNE cont4              \ Jump to cont4 to leave the speed of the other car
\ alone, as it is going faster than the player (this BNE
\ is effectively a JMP, as we know from the above that
\ carSpeedHi,Y < carSpeedHi,X, which implies that the
\ value of carSpeedHi,X must be non-zero)

.cont3

\ If we get here, it's because the player is going
\ faster than the other car, and we jumped here via a
\ BCS, so the C flag is set, which means the following
\ adds 12 to the other car's speed

ADC #11                \ Increase the high byte of the other driver's speed by
STA carSpeedHi,X       \ 12, to speed it up after being hit by the faster
\ player's car

.cont4

\ By this point, A contains the speed of the faster car
\ following the collision, as the high byte of the speed

JSR Multiply8x8        \ Set (A T) = A * U
\           = carSpeedHi * damage measurement (0 to 74)
\
\ So (A T) is higher with closer and faster collisions

CMP #16                \ If A < 16, jump to cont5 to skip the following
BCC cont5

LDA #16                \ A >= 16, so set A to 16 as the maximum value of A

.cont5

\ By this point, (A T) is a measurement of how dangerous
\ the collision was, on a scale of 0 to 16, so now we
\ convert that into the amount of spin to apply to our
\ car

PLP                    \ Restore the sign of dYawAngle, which we stored on the
\ stack above, so the N flag is positive if the other
\ car's yaw angle is larger (i.e. the other car is to
\ the right of the player's car), or negative if the
\ other car's yaw angle is smaller (i.e. the other car
\ is to the left of the player's car)

JSR Absolute16Bit      \ Set the sign of (A T) to match the result of the
\ subtraction above, so A is now in the range -16 to
\ +16, with the sign reflecting the position of the
\ other car:
\
\   * -16 to 0 if the other car is to the left
\
\   * 0 to +16 if the other car is to the right
\
\ So we can use this to apply spin to our car, so we
\ spin in the correct direction and with an amount
\ that's proportional to the severity of the collision

\ Fall through into SquealTyres to set spinYawAngleTop
\ to the amount of yaw spin in A and make the sound of
\ squealing tyres
```