mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-23 07:29:02 -08:00
65 lines
2.5 KiB
C#
65 lines
2.5 KiB
C#
using System;
|
|
using SuperStarTrek.Space;
|
|
|
|
namespace SuperStarTrek.Utils
|
|
{
|
|
internal class DirectionAndDistance
|
|
{
|
|
private readonly float _fromX;
|
|
private readonly float _fromY;
|
|
|
|
private DirectionAndDistance(float fromX, float fromY)
|
|
{
|
|
_fromX = fromX;
|
|
_fromY = fromY;
|
|
}
|
|
|
|
internal static DirectionAndDistance From(Coordinates coordinates) => From(coordinates.X, coordinates.Y);
|
|
|
|
internal static DirectionAndDistance From(float x, float y) => new DirectionAndDistance(x, y);
|
|
|
|
internal (float Direction, float Distance) To(Coordinates coordinates) => To(coordinates.X, coordinates.Y);
|
|
|
|
internal (float Direction, float Distance) To(float x, float y)
|
|
{
|
|
var deltaX = x - _fromX;
|
|
var deltaY = y - _fromY;
|
|
|
|
return (GetDirection(deltaX, deltaY), GetDistance(deltaX, deltaY));
|
|
}
|
|
|
|
// The algorithm here is mathematically equivalent to the following code in the original,
|
|
// where X is deltaY and A is deltaX
|
|
// 8220 X=X-A:A=C1-W1:IFX<0THEN8350
|
|
// 8250 IFA<0THEN8410
|
|
// 8260 IFX>0THEN8280
|
|
// 8270 IFA=0THENC1=5:GOTO8290
|
|
// 8280 C1=1
|
|
// 8290 IFABS(A)<=ABS(X)THEN8330
|
|
// 8310 PRINT"DIRECTION =";C1+(((ABS(A)-ABS(X))+ABS(A))/ABS(A)):GOTO8460
|
|
// 8330 PRINT"DIRECTION =";C1+(ABS(A)/ABS(X)):GOTO8460
|
|
// 8350 IFA>0THENC1=3:GOTO8420
|
|
// 8360 IFX<>0THENC1=5:GOTO8290
|
|
// 8410 C1=7
|
|
// 8420 IFABS(A)>=ABS(X)THEN8450
|
|
// 8430 PRINT"DIRECTION =";C1+(((ABS(X)-ABS(A))+ABS(X))/ABS(X)):GOTO8460
|
|
// 8450 PRINT"DIRECTION =";C1+(ABS(X)/ABS(A))
|
|
// 8460 PRINT"DISTANCE =";SQR(X^2+A^2):IFH8=1THEN1990
|
|
private static float GetDirection(float deltaX, float deltaY)
|
|
{
|
|
var deltaXDominant = Math.Abs(deltaX) > Math.Abs(deltaY);
|
|
var fractionalPart = deltaXDominant ? deltaY / deltaX : -deltaX / deltaY;
|
|
var nearestCardinal = deltaXDominant switch
|
|
{
|
|
true => deltaX > 0 ? 7 : 3,
|
|
false => deltaY > 0 ? 1 : 5
|
|
};
|
|
|
|
var direction = nearestCardinal + fractionalPart;
|
|
return direction < 1 ? direction + 8 : direction;
|
|
}
|
|
|
|
private static float GetDistance(float deltaX, float deltaY) =>
|
|
(float)Math.Sqrt(Math.Pow(deltaX, 2) + Math.Pow(deltaY, 2));
|
|
}
|
|
} |