Revs on the BBC Micro

# 3D objects: GetObjectDistance

```       Name: GetObjectDistance                                       [Show more]
Type: Subroutine
Category: 3D objects
Summary: Calculate the distance between an object and the player's car, for
collision purposes
Context: See this subroutine in context in the source code
References: This subroutine is called as follows:
* CheckForContact calls GetObjectDistance
* GetSectionYawAngle calls GetObjectDistance

This routine is called with the smaller yaw angle of the object, where 0 to
255 represents 0 to 45 degrees, so 103 = 18.2 degrees. The smaller viewing
angle is taken from the arctan calculation for the yaw angle calculation in
GetObjYawAngle, so that's the triangle whose hypotenuse is the line between
the player and the object, and whose other sides are parallel to the x-axis
and z-axis.

If the smaller yaw angle is < 18.2 degrees, the routine does this:

* Set (L K) = (J I) + (H G) / 8
= max + min / 8

If the smaller yaw angle is >= 18.2 degrees, the routine does this:

* Set (L K) = (J I) * 7/8 + (H G) / 2
= max * 7/8 + min / 2

This appears to set the distance between the object and the player's car, for
the purposes of determining whether contact has been made.

I suspect the calculation is an approximation of Pythagoras that is much
faster to calculate, split into small yaw angles (when the objects are
close to being orthogonal to each other) and larger yaw angles (when their
relative positions are closer to the diagonal). This is a guess, though.

Arguments:

(J I)                max(|x-delta|, |z-delta|)

(H G)                min(|x-delta|, |z-delta|)

M                    The smaller yaw angle of the object, where 0 to 255
represents 0 to 45 degrees, so 103 = 18.2 degrees

Returns:

(L K)                The distance between the object and the player's car

A                    Contains the high byte of (L K)

.GetObjectDistance

CMP #103
BCS odis1

LDA G                  \ Set A = G

LSR H                  \ Set (H A) = (H A) >> 3
ROR A                  \           = (H G) >> 3
LSR H
ROR A
LSR H
ROR A

CLC                    \ Set (L K) = (J I) + (H A)
ADC I                  \           = (J I) + (H G) >> 3
STA K                  \           = (J I) + (H G) / 8
LDA H
STA L

RTS                    \ Return from the subroutine

.odis1

LSR H                  \ Set (H G) = (H G) >> 1
ROR G

LDA J                  \ Set (T A) = (J I)
STA T
LDA I

LSR T                  \ Set (T U) = (T A) >> 3
ROR A                  \           = (J I) >> 3
LSR T
ROR A
LSR T
ROR A
STA U

LDA G                  \ Set (L K) = (J I) + (H G)
CLC                    \           = (J I) + (H G) >> 1
STA K
LDA H
STA L

LDA K                  \ Set (L K) = (L K) - (T U)
SEC                    \           = (J I) + (H G) >> 1 - (J I) >> 3
SBC U                  \           = (J I) * 7/8 + (H G) / 2
STA K
LDA L
SBC T
STA L

RTS                    \ Return from the subroutine

EQUB &F1, &0C          \ These bytes appear to be unused
EQUB &E5, &74
EQUB &8D, &F6
EQUB &0C, &60
EQUB &00, &00
EQUB &00, &00
EQUB &00, &00
EQUB &40
```