Skip to navigation

Revs on the BBC Micro

Car geometry: MovePlayerSegment

Name: MovePlayerSegment [Show more] Type: Subroutine Category: Car geometry Summary: Move the player's car in the correct direction Deep dive: Placing cars on the track
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * MainDrivingLoop (Part 2 of 5) calls MovePlayerSegment

This routine checks whether the player has turned enough to be in a different direction (i.e. pointing forwards to pointing backwards or vice versa), and if so, it turns the player around by updating the track segment buffer for the new direction, resetting the track section list, and updating all the direction-related variables. Otherwise it works out whether the player has moved into a new segment, and if so, it updates the car's segment and section numbers accordingly.
.MovePlayerSegment LDA playerHeading \ Set A = playerHeading - spinYawAngleTop SEC \ SBC spinYawAngleTop \ So A contains the new heading of the player's car, \ once the current spin is added (i.e. it's the new \ heading of the car) \ A is an angle that represents the new direction in \ which our car will be facing, after applying spin, \ with respect to the track, like this: \ \ 0 \ -32 | +32 Overhead view of car \ \ | / \ \ | / 0 = looking straight ahead \ \|/ +64 = looking sharp right \ -64 -----+----- +64 -64 = looking sharp left \ /|\ \ / | \ \ / | \ \ -96 | +96 \ 128 \ \ An angle of 0 means our car is facing forwards along \ the track, while an angle of +32 means we are facing \ 45 degrees to the right of straight on, and an angle \ of 128 means we are facing backwards along the track BPL mpla1 \ If A is positive, jump to mpla1 to skip the following EOR #&FF \ Invert A, so this effectively reflects the angle into \ the right half of the above diagram: \ \ 0 \ | 32 \ | / \ | / \ |/ \ +----- 64 \ |\ \ | \ \ | \ \ | 96 \ 127 .mpla1 ASL A \ Set A = A << 1, so we now have: \ \ 0 \ | 64 \ | / \ | / \ |/ \ +----- 128 \ |\ \ | \ \ | \ \ | 192 \ 254 CMP #128 \ Clear the C flag if A < 128 (i.e. top-right quadrant) \ is set the C flag if A >= 128 (i.e. bottom-right \ quadrant) \ Note that bit 7 is similar, so we have: \ \ 0 \ | 64 \ | / <-- C flag and bit 7 clear \ | / \ |/ \ +----- 128 \ |\ \ | \ \ | \ <-- C flag and bit 7 set \ | 192 \ 254 EOR directionFacing \ If we are facing forwards, leave A alone, but if we \ are currently facing backwards, flip bit 7 of A BPL mpla3 \ If we are facing forwards and we are in the top-right \ quadrant, or we are facing backwards and we are in the \ bottom-right quadrant, then the direction we are \ facing is still correct, so jump to mpla3 to get on \ with moving the car \ \ Otherwise we may now be facing in a different \ direction to before, and bit 7 of A is set BCC mpla2 \ If bit 7 of A was clear before the above EOR, then we \ are in the top-right quadrant but are currently facing \ backwards, so jump to mpla2 to skip the following \ instruction EOR #%01111111 \ Bit 7 of A was set before the above EOR, so we are in \ the bottom-right quadrant, but are currently facing \ forwards, so flip bits 0-6 of A, changing the range of \ the bottom-right quadrant from 128 to 254 to \ 255 to 129 .mpla2 \ By this point, we are pointing in the opposite \ direction to the setting of directionFacing, and the \ angles are as follows: \ \ 0 \ | 64 \ | / <-- C flag and bit 7 clear \ | / \ |/_.- 127 \ +----- 255 \ |\-._ 252 \ | \ \ | \ <-- C flag and bit 7 set \ | 192 \ 129 \ \ So 0 to 127 is in the top-right quadrant, while 255 to \ 129 is the bottom-right quadrant CMP #252 \ If A >= 252, then the new angle we are facing is in BCS mpla3 \ the top sliver of the bottom-right quadrant, so jump \ to mpla3 to get on with moving the car \ If we get here then A < 252, which means we are either \ now in the top-right quadrant, or we are in the bottom \ part of the bottom-right quadrant, and we are facing \ in a different direction to directionFacing \ \ So we have now officially turned in the opposite \ direction, and need to update all the various buffers \ and variables JSR ChangeDirection \ Turn the player around by updating the track segment \ buffer for the new direction, resetting the track \ section list, and updating all the direction-related \ variables RTS \ Return from the subroutine .mpla3 \ The GetSegmentAngles routine, which has already been \ called by this point, sets up the track segment list \ and sets edgeSegmentNumber to the entry number within \ the track segment list that is closest to the player's \ car \ \ Entry 13 in the track segment list corresponds to the \ segment that's 32 behind the front segment of the \ track segment buffer, which is the position of the \ player's car, so if edgeSegmentNumber does not equal \ 13, then it means that the car has moved into a new \ segment \ \ Specifically, the values of edgeSegmentNumber mean \ the following: \ \ * 11 = player has moved forward two segments \ * 12 = player has moved forward one segment \ * 13 = player is still in the same segment \ * 14 = player has moved back one segment \ * 15 = player has moved back two segments \ \ The player can't travel more than two segments in one \ iteration of the main driving loop LDA edgeSegmentNumber \ If edgeSegmentNumber = 12, jump to mpla4 to move the CMP #12 \ player forward by one segment BEQ mpla4 BCS mpla5 \ If edgeSegmentNumber > 12, then the player is either \ in the same segment, or has moved backwards, so jump \ to mpla5 \ If we get here then edgeSegmentNumber < 12, so \ edgeSegmentNumber must be 11, so we move the player \ forwards by two segments JSR MovePlayerForward \ Move the player forwards by one segment .mpla4 BIT playerPastSegment \ If bit 0 of playerPastSegment is clear, then the BPL mpla7 \ player has not yet gone past the closest segment, so \ jump to mpla7 to return from the subroutine without \ moving forward by this segment JSR MovePlayerForward \ Move the player forwards by one segment RTS \ Return from the subroutine .mpla5 \ If we get here then edgeSegmentNumber > 12 CMP #14 \ If edgeSegmentNumber < 14, i.e. edgeSegmentNumber is BCC mpla7 \ 13, then the player has not changed segment, so jump \ to mpla7 to return from the subroutine BEQ mpla6 \ If edgeSegmentNumber = 14, jump to mpla6 to move the \ player backwards by one segment \ If we get here then edgeSegmentNumber > 14, so \ edgeSegmentNumber must be 15, so we move the player \ backward by two segments JSR MovePlayerBack \ Move the player backwards by one segment .mpla6 JSR MovePlayerBack \ Move the player backwards by one segment .mpla7 RTS \ Return from the subroutine