Skip to navigation

Revs on the BBC Micro

3D objects: BuildVisibleCar

Name: BuildVisibleCar [Show more] Type: Subroutine Category: 3D objects Summary: Check the distance to the specified car and build the car object if it is close enough Deep dive: Tactics of the non-player drivers
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * MoveAndDrawCars calls BuildVisibleCar

Arguments: X The position of the driver whose distance we want to check
.BuildVisibleCar LDA driversInOrder,X \ Set A to the number of the driver in position X STA thisDriver \ Store the driver number in thisDriver so we can \ retrieve it later STA objectNumber \ Store the driver number in objectNumber, in case we \ need to hide this driver's car below TAX \ Set X to the driver number LDY #23 \ Set Y to 23, the object number we use to store the \ front segment of the track segment buffer SEC \ Set the C flag for a 16-bit calculation in the call \ to CompareSegments JSR CompareSegments \ Set A and T to the distance between driver X and \ the front segment in the track segment buffer in \ object Y BCS bvis1 \ If the C flag is set then the two cars are far apart, \ i.e. |T| < 128, so jump to bvis1 to hide the car EOR directionFacing \ This tests whether bit 7 of directionFacing and bit 7 BMI bvis1 \ of the distance in A are different, which will happen \ if either of the following is true: \ \ * We are facing forwards (0) and driver X is ahead \ of the front segment in the track segment buffer \ (1) \ \ * We are facing backwards (1) and driver X is not \ ahead of the front segment in the track segment \ buffer (0) \ \ In both cases driver X is too far away from us to be \ seen, and bit 7 of the result of the EOR will be set, \ so jump to bvis1 to hide the car LDA T \ Set T = |T| JSR Absolute8Bit \ STA T \ so A and T contain the absolute value of the distance \ between the car and the front segment in the track \ segment buffer CMP #40 \ If |A| < 40, jump to bvis2 to skip the following BCC bvis2 \ instruction and continue creating the car object \ If we get here then the car and the front segment in \ the track segment buffer are far apart, so we hide the \ car .bvis1 JMP HideObject \ Hide the object in objectNumber, which this hides the \ car object for driver X, and return from the \ subroutine using a tail call .bvis2 \ If we get here, A and T contain the absolute value of \ the distance between the car and the front segment in \ the track segment buffer ASL A \ Set A = A * 2 \ = distance * 2 CLC \ Set A = ~(A + T) ADC T \ = ~(distance * 2 + distance) EOR #&FF \ = ~(distance * 3) SEC \ Set A = A + 1 + frontSegmentIndex ADC frontSegmentIndex \ = ~(distance * 3) + 1 + frontSegmentIndex \ = -(distance * 3) + frontSegmentIndex \ = frontSegmentIndex - distance * 3 \ \ frontSegmentIndex contains the index * 3 of the front \ segment in the track segment buffer, so this is the \ same as: \ \ (front segment index - distance) * 3 BPL bvis3 \ If the result was positive, i.e. track segment index \ > distance, jump to bvis3 to skip the following CLC \ Otherwise set A = A + 120 ADC #120 .bvis3 TAY \ Copy the result from A into Y, so Y now contains the \ track segment index * 3 of the track segment for the \ car object LDA carStatus,X \ If bit 4 of driver X's carStatus is set, then tactics AND #%00010000 \ are not enabled for this car, so jump to BNE BuildCarObjects \ BuildCarObjects to skip setting the car's steering LDA carSpeedHi,X \ If the high byte of driver X's speed is less than 50, CMP #50 \ jump to BuildCarObjects BCC BuildCarObjects LDA segmentSteering,Y \ Set the driver's carSteering to the segmentSteering STA carSteering,X \ value for this track segment, so the car follows the \ curve of the track