AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Vektordistanz Fadenkreuz zu Spieler (2D) berechnen
Thema durchsuchen
Ansicht
Themen-Optionen

Vektordistanz Fadenkreuz zu Spieler (2D) berechnen

Ein Thema von Zacherl · begonnen am 12. Aug 2011 · letzter Beitrag vom 13. Aug 2011
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#1

Vektordistanz Fadenkreuz zu Spieler (2D) berechnen

  Alt 12. Aug 2011, 18:53
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
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#2

AW: Vektordistanz Fadenkreuz zu Spieler (2D) berechnen

  Alt 12. Aug 2011, 23:01
Ich muss gestehen, ich blicke gerade nicht wirklich durch deine Codefetzen, aber so prinzipiell: Dein Fadenkreuz hat 2D-Koordinaten? Dein Spieler 3D? Dann transformier doch die Spielerkoordinaten händisch in den Screenspace, und dann einfach den euklidschen Abstand. Vorausgesetzt, du willst den in Screenkoordinaten haben! Wenn nicht, wäre ggf. wichtig zu sagen, in welchem Kontext du den Abstand brauchst.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Bjoerk

Registriert seit: 28. Feb 2011
Ort: Mannheim
1.384 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: Vektordistanz Fadenkreuz zu Spieler (2D) berechnen

  Alt 12. Aug 2011, 23:19
Delphi-Quellcode:
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  e1, e2, x1, y1, x2, y2, xR, yR, R, S: double;
begin
  R:= 50; // Turm
  x1:= 100;
  y1:= 100;

  x2:= x; // "Monster"
  y2:= y;

  S:= Sqrt (Sqr(x2-x1) + Sqr(y2-y1));
  e1:= (x2 - x1) / S; // cos
  e2:= (y2 - y1) / S; // sin

  xR:= x1 + R*e1;
  yR:= y1 + R*e2;

  Canvas.MoveTo(Round(x1), Round(y1));
  Canvas.LineTo(Round(xR), Round(yR));

  Caption:= IntToStr(Round(xR))+' '+IntToStr(Round(yR));
end;
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#4

AW: Vektordistanz Fadenkreuz zu Spieler (2D) berechnen

  Alt 13. Aug 2011, 02:51
Ich muss gestehen, ich blicke gerade nicht wirklich durch deine Codefetzen, aber so prinzipiell: Dein Fadenkreuz hat 2D-Koordinaten? Dein Spieler 3D? Dann transformier doch die Spielerkoordinaten händisch in den Screenspace, und dann einfach den euklidschen Abstand. Vorausgesetzt, du willst den in Screenkoordinaten haben! Wenn nicht, wäre ggf. wichtig zu sagen, in welchem Kontext du den Abstand brauchst.
Das Fadenkreuz selbst befindet sich ja in der Mitte des Bildschirms. Aber davon mal unabhängig habe ich die Position meines eigenen Spielers im World Space (3D) und seine Rotation (Pitch und Yaw). Ebenfalls habe ich die Position des gegnerischen Spielers im World Space (3D).
Nun möchte ich den Spieler ermitteln, welcher den nähesten Abstand zum Fadenkreuz besitzt.

Meine geposteten Funktionen haben einfach gesagt erstmal die X, Y Koordinaten des Fadenkreuzes ermittelt (Mitte des Bildschirms) und danach die 3D World Space Koordinaten des gengerischen Spielers in die Screen Koordinaten (2D) umgerechnet. Dann konnte ich über Phytagoras ganz einfach den Abstand ermitteln.

Das Problem ist jetzt einfach, dass wenn ich einen Winkel von 90° zum gegnerischen Spieler überschreite, meine Berechnung von 3D in 2D logischerweise fehlschlägt. Der Grund ist ganz einfach, dass der Spieler nicht mehr sichtbar ist und somit seine 2D Koordinaten nicht mehr auf den Bildschirm passen würden.

Konkret suche ich jetzt eine Methode, welche zuverlässig auch dann den nähesten am Fadenkreuz befindlichen Spieler ermittelt, wenn dieser sich in einem Winkel > 90° befindet, also theoretisch nicht mehr sichtbar ist.

@Bjoerk:
Deinen Codeschnipsel verstehe ich jetzt nicht ganz. So wie ich das sehe werden dort nur 2D Koordinaten verwendet.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#5

AW: Vektordistanz Fadenkreuz zu Spieler (2D) berechnen

  Alt 13. Aug 2011, 03:17
Ahaaa! Es geht also um einen Winkelabstand, nicht um eine Räumliche Distanz! In dem Fall wäre es ggf. hilfreich, sich mal Bei Google suchenKugelkoordinaten anzuschauen, welche eben aus 2 Winkeln bestehen. Projeziert man nun die kartesischen Koordinaten der Gegner, und den Strahl in Blickrichtung des Spielers auf eine Einheitskugel (damit man "r" ausser Acht lassen kann, und das quasi zu einem 2D-Fall degeneriert), kann man wieder mit dem 2D euklidschen Abstand da dran gehen, und du hast quasi den horizontalen und vertikalen Winkel zwischen Blickrichtung und Gegner im Screenspace (sozusagen, die Wortwahl ist vermutlich formal nicht ganz korrekt).
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#6

AW: Vektordistanz Fadenkreuz zu Spieler (2D) berechnen

  Alt 13. Aug 2011, 03:23
Du sprichst chinesisch Aber ich werde die Begriffe mal googlen und schauen, ob ich damit was anfangen kann. Ob Winkelabstand in diesem Falle korrekt ist, weiß ich nicht. Es geht mir ja schon um eine räumliche Distanz. Aber eben nur im 2D Raum.

Ein Ansatz, den ich im Moment probiere, ist das Berechnen von Delta Yaw und Delta Pitch zwischen meiner Blickrichtung und der Blickrichtung, die ich hätte, wenn ich auf den gegnerischen Spieler schaue. Das scheint sogar schon teilweise zu funktionieren. Momentan beachte ich nur Yaw und lasse Pitch mal außen vor.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#7

AW: Vektordistanz Fadenkreuz zu Spieler (2D) berechnen

  Alt 13. Aug 2011, 03:38
Das ist effektiv das selbe wie mein Vorschlag Nur, dass man mit den Kugelkoordinaten vermutlich billiger davon kommt, da man pro Gegner nur zwei trigonometrische Funktionen und 4 einfache Fallunterscheidungen machen muss*, und schon hast du "delta yaw + pitch". Wichtig ist dabei eben, dass die Distanz weg fällt, da so ein Projektil ja mit unendlicher Geschwindigkeit recht gut angenähert ist

Wenn man die beiden Winkel hat, kann man wieder recht einfach mittels "sqrt(yaw²+pitch²)" den gesamten Abstand berechnen, da die Projektion auf die Kugel im Grunde wieder ein 2D-Raum ist. Allerdings kein euklidscher, man müsste diesen Abstand dann für ein paar Fälle anpassen, da man zwischen -180° und 180° so eine doofe Stelle hat - es beschreibt ja beides die selbe Richtung, ist aber in Zahlen gesprochen recht weit weg voneinander. Man müsste also hier und da mal ein Pi addieren bzw. abziehen, aber für wann und wo genau ist mir das jetzt auch zu spät

*) Und natürlich insgesamt ein Mal (pro Frame / Testdurchgang) für einen Punkt in Blickrichtung mit etwas Abstand zum Spieler.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)

Geändert von Medium (13. Aug 2011 um 03:51 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#8

AW: Vektordistanz Fadenkreuz zu Spieler (2D) berechnen

  Alt 13. Aug 2011, 04:28
Ich bedanke mich schonmal recht herzlich für deine Hilfe. Werde mich wohl morgen nochmal melden Ich probiere jetzt erstmal die Sache mit sqrt() anhand von meinen wohl umständlich berechneten Delta Pitch und Delta Yaw Werten aus und schaue, inwiefern ich da noch ein Paar Anpassen vornehmen muss.

Wenn das soweit funktioniert bin ich sehr gespannt, ob ich mit den Kugelkoordinaten noch eine Optimierung erreichen kann

Hier mal meine momentane Funktion zur Berechnung der Zielwinkel (absoluter Winkel / kein Delta):
Delphi-Quellcode:
procedure CalculateAimAngle(const Device: IDirect3DDevice9;
  Player: TPlayerListItem; var Pitch, Yaw: Single);
var
  Z, P, D, A: TD3DXVector3;
  T: Integer;
begin
  Z := CallNodeTransform(Device, Player, BONE_HEAD, false);
  P := Camera.Position;
  // Pitch berechnen
  D3DXVec3Subtract(D, Z, P);
  A.x := 0;
  A.y := 1;
  A.z := 0;
  D3DXVec3Normalize(D, D);
  Pitch := ArcSin(Abs(D.x * A.x + D.y * A.y + D.z * A.z));
  if ((Z.y - P.y) > 0) then Pitch := -Pitch;
  // Yaw berechnen
  D.x := Z.x - P.x;
  D.y := 0;
  D.z := Z.z - P.z;
  A.x := 0;
  A.y := 0;
  A.z := 1;
  D3DXVec3Normalize(D, D);
  Yaw := ArcCos(D.x * A.x + D.y * A.y + D.z * A.z);
  if ((Z.x - P.x) < 0) then Yaw := (2 * PI) - Yaw;
  // In Normalform umrechnen (Manchmal sind die Winkel Vielfache von 2*PI)
  T := Round(Yaw / (PI));
  if (T = 1) then
  begin
    Yaw := Yaw - (2 * PI);
  end else
  begin
    Yaw := Yaw - (PI * T);
  end;
end;
Denke mal, hier kann man noch einiges an Optimierungen durchführen
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#9

AW: Vektordistanz Fadenkreuz zu Spieler (2D) berechnen

  Alt 13. Aug 2011, 17:54
Das haut schonmal absolut nicht hin. Ich berechne erst den Winkel mit der oben geposteten Funktion und passe ihn dann an das aktuelle Vielfache von 2*PI an. Wenn man die Spielfigur paar Mal im Kreis bewegt, wird der Yaw Winkel nicht resettet, sondern erhöht sich einfach um eine komplette Umdrehung.

Zum anpassen des berechneten Winkels habe ich mir folgendes geschrieben:
Delphi-Quellcode:
procedure NormalizeAimAngle(var Pitch, Yaw: Single);
var
  T: Integer;
begin
  T := Round(Camera.Yaw / (PI));
  Yaw := Yaw + (PI * T);
  if (T mod 2) <> 0 then
  begin
    Yaw := Yaw + PI;
  end;
end;
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#10

AW: Vektordistanz Fadenkreuz zu Spieler (2D) berechnen

  Alt 13. Aug 2011, 18:00
Meine Idee wäre, das Fadenkreuz als dreidimensionalen Strahl aufzufassen, der von der Kameraposition aus in die Blickrichtung verläuft. Der Abstand eines Spieler wäre dann der Abstand zu diesem Strahl. Ich wüsste jetzt aber auf die Schnelle nicht, wie man den Abstand eines Punktes von einem Strahl am einfachsten berechnet.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:43 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz