Revs on the BBC Micro

# Driving model: ApplyElevation (Part 5 of 5)

```       Name: ApplyElevation (Part 5 of 5)                            [Show more]
Type: Subroutine
Category: Driving model
Summary: Calculate the player's 3D y-coordinate and progress speed
Deep dive: The core driving model
Jumps and drops
Context: See this subroutine in context in the source code
References: No direct references to this subroutine in this source file

Calculate the following:

* (yPlayerCoordTop yPlayerCoordHi) =   (ySegmentCoordIHi ySegmentCoordILo)
+ carProgress * yTrackSegmentI
+ heightAboveTrack * 4
+ 172

* carSpeedHi for the player's car = playerSpeedHi * 2.13

ASL A                  \ Set (W A) = (0 A) << 2
ROL W                  \           = (W A) << 2
ASL A                  \           = heightAboveTrack << 2
ROL W                  \           = heightAboveTrack * 4

STA V                  \ Set (W V) = (W A)
\           = heightAboveTrack * 4

LDX currentPlayer      \ Set X to the driver number of the current player

LDA carProgress,X      \ Set A to the lowest byte of the player's progress
\ through the current segment

JSR MultiplyHeight     \ Set:
\
\   A = A * yTrackSegmentI
\     = carProgress * yTrackSegmentI
\
\ flipping the sign if we are facing backwards
\
\ The value given in yTrackSegmentI is the y-coordinate
\ of the segment vector, i.e. the vector from this
\ segment to the next, which is the same as the change
\ in height as we move through the segment
\
\ The calculation above effectively works out the
\ difference in elevation of the car as it progresses
\ through the segment, and puts it in A

BPL elev19             \ If A is positive, jump to elev19 to skip the following
\ instruction

DEC W                  \ A is negative, so set W = W - 1

.elev19

LDY playerSegmentIndex \ Set Y to the index of the player's track segment from
\ the track segment buffer

CLC                    \ Set:
\   A = A + ySegmentCoordILo
\     = carProgress * yTrackSegmentI + ySegmentCoordILo
\
\ ySegmentCoordILo is the low byte of the 3D
\ y-coordinate for the player's track segment
\
\ So A now contains the segment's y-coordinate, plus the
\ elevation of the car due to the track's progress
\ through the segment

PHP                    \ Store the C flag on the stack, which will be set if

CLC                    \ Set A = A + 172

PHP                    \ Store the C flag on the stack, which will be set if

\ We now calculate the following for the y-coordinate of
\ the player's 3D coordinates:
\
\   (yPlayerCoordTop yPlayerCoordHi)
\
\     =   A
\       + (W V)
\       + (ySegmentCoordIHi 0)
\       + C flag from the first addition
\       + C flag from the second addition
\
\    =   carProgress * yTrackSegmentI + ySegmentCoordILo
\      + 172
\      + heightAboveTrack * 4
\      + (ySegmentCoordIHi 0)
\      + C flag from the first addition
\      + C flag from the second addition
\
\    =   carProgress * yTrackSegmentI
\      + 172
\      + heightAboveTrack * 4
\      + (ySegmentCoordIHi ySegmentCoordILo)
\
\ with all the correct carry bits included

STA yPlayerCoordHi

LDA ySegmentCoordIHi,Y \ And then the high bytes
PLP
PLP
STA yPlayerCoordTop

LDA playerSpeedHi      \ Set U = playerSpeedHi, which is the player's speed in
STA U                  \ mph

LDA #33                \ Set A = 33

JSR Multiply8x8        \ Set (A T) = A * U
\           = playerSpeedHi * 33
\
\ So A = playerSpeedHi * 33 / 256

ASL U                  \ Set A = A + U * 2
CLC                    \       = playerSpeedHi * 33 / 256 + playerSpeedHi * 2
ADC U                  \       = playerSpeedHi * 2.13

STA carSpeedHi,X       \ Set carSpeedHi for the player's car to playerSpeedHi *
\ 2.13
\
\ carSpeedHi is now the speed of the car in terms of
\ 1/256-ths of a segment, with 120 mph in playerSpeedHi
\ corresponding to a whole segment in carSpeedHi (as
\ 120 * 2.13 = 255)

RTS                    \ Return from the subroutine
```