Skip to navigation

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