Skip to navigation

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. This looks like an implementation of the "alpha max plus beta min" algorithm, which approximates the Pythagoran distance as follows: |z| = SQRT(a^2 + b^2) =~ alpha * max(a, b) + beta * min(a, b) where alpha and beta are carefully chosen constants that produce optimal approximations. You can read all about this algorithm and the choice of constants in this Wikipedia article: https://en.wikipedia.org/wiki/Alpha_max_plus_beta_min_algorithm When the smaller yaw angle is < 18.2 degrees, the constants are: * alpha = 1 * beta = 1/8 When the smaller yaw angle is >= 18.2 degrees, the constants are: * alpha = 7/8 * beta = 1/2 This algorithm is a lot faster than a full Pythagoras calculation, especially in 8-bit 6502 assembly code.
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 LDA M \ If M >= 103, jump to odis1 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 ADC J 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 ADC I STA K LDA H ADC J 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