Hallo,
ich stehe vor einem mehr oder weniger mathematischen Problem. Ich versuche die Distanz zwischen Fadenkreuz und einer gegnerischen Spielfigur zu ermitteln. Momentan gehe ich hierfür wie folgt vor:
Delphi-Quellcode:
function GetCrosshairDistance2D(const Device: IDirect3DDevice9;
Player: TPlayerListItem): Integer;
var
ViewPort: TD3DViewport9;
BoneVector,
Crosshair: TD3DXVECTOR3;
begin
Result := $FFFFFFF;
try
BoneVector := CallNodeTransform(Device, Player, BONE_HEAD, true);
Device.GetViewport(ViewPort);
Crosshair.x := Viewport.Width / 2;
Crosshair.y := Viewport.Height / 2;
Result := GetVectorDistance(Crosshair, BoneVector, 1);
except
end;
end;
function GetVectorDistance(V1, V2: TD3DXVECTOR3; Units: Integer): Integer;
var
Difference: TD3DXVECTOR3;
begin
Difference.x := V2.x - V1.x;
Difference.y := V2.y - V1.y;
Difference.z := V2.z - V1.z;
Result := Round(sqrt(Difference.x * Difference.x +
Difference.y * Difference.y + Difference.z * Difference.z) / Units);
end;
Dieser Code funktioniert auch soweit wunderbar, allerdings nur solange zwischen meiner Blickrichtung und dem Gegner ein maximaler Winkel von +/-90° eingehalten wird. Das Problem konnte ich auf die WorldToScreen() Funktion eingrenzen, welche indirekt von CallNodeTransform aufgerufen wird. Ihr Zweck ist es, die World Space Koordinaten in die 2D Bildschirm Koordinaten umzurechnen.
Delphi-Quellcode:
function WorldToScreen(
const Device: IDirect3DDevice9; X, Y, Z: Single;
var Pos: TD3DXVECTOR3): Boolean;
var
VectorWorld: TD3DXVector3;
ViewPort: D3DVIEWPORT9;
Projection,
View,
World: TD3DXMATRIX;
begin
Result := false;
try
VectorWorld := D3DXVECTOR3(X, Y, Z);
FillChar(ViewPort, SizeOf(D3DVIEWPORT9), #0);
FillChar(Pos, SizeOf(TD3DXVECTOR3), #0);
if (
not Device.GetTransform(D3DTS_VIEW, View) = D3D_OK)
then Exit;
if (
not Device.GetTransform(D3DTS_PROJECTION, Projection) = D3D_OK)
then
Exit;
if (
not Device.GetTransform(D3DTS_WORLD, World) = D3D_OK)
then Exit;
if (
not Device.GetViewport(ViewPort) = D3D_OK)
then Exit;
D3DXVec3Project(Pos, VectorWorld, ViewPort, Projection, View, World);
if (Pos.Z < 1)
then
begin
Result := true;
end;
except
raise Exception.Create('
WorldToScreen failed');
end;
end;
Vom Prinzip her erscheint es auch logisch, dass die Funktion fehlschlägt, da die berechneten Koordinaten bei einem Winkel von über +/-90° ja nicht mehr in den 2D Space des Bildschirms passen.
Gibt es hier eine geschicktere Möglichkeit den rein 2-dimensionalen Abstand meines eigenen Fadenkreuzes zum Spieler zu berechnen? Eventuell über meine eigene Position und Rotation?
Viele Grüße
Zacherl