AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi [Andorra] Kollisionserkennung verbessern
Thema durchsuchen
Ansicht
Themen-Optionen

[Andorra] Kollisionserkennung verbessern

Offene Frage von "Diamondback2007"
Ein Thema von Diamondback2007 · begonnen am 17. Jul 2008 · letzter Beitrag vom 21. Jul 2008
 
Benutzerbild von Diamondback2007
Diamondback2007

Registriert seit: 2. Feb 2007
260 Beiträge
 
Delphi 2007 Professional
 
#6

Re: [Andorra] Kollisionserkennung verbessern

  Alt 17. Jul 2008, 19:31
Ach das ist doch alles blöd
Ich bekomm das nicht hin mit dem "Seperating Axis Theorem"...
Ich poste mal meinen Code:
Die Polygonklasse:
Delphi-Quellcode:
unit uPolygon;

interface

uses
  AdPhysics,
  Vectors,
  Math;

type
  // Array mit den Vertices des Polygons
  TV2fArray = array of TVector2f;
  // Polygon Klasse
  TPolygon = class(TPhysicalBoxSprite)
  private
    fposition: TVector2f; // Position
    fvertices: TV2fArray; // Vertices (Objektkoordinaten)
    function GetVertex(n: integer): TVector2f; // Liefert die Objektkoordinaten
    function GetVertexAbs(n: integer): TVector2f; // Liefert die absoluten Koordinaten
    procedure SetVertex(n: integer; Value: TVector2f); // Setzt die Objektkoordinaten
    function GetCount: integer; // Liefert length(fvertices)
  public
    procedure AddVertex(v: TVector2f); // Fügt ein Vertex hinzu
    procedure AddVertexAbs(v: TVector2f); // Fügt ein Vertex mit Weltkoordinaten hinzu
    procedure RemoveVertex(n: integer); // Entfernt ein Vertex
    property position: TVector2f read fposition write fposition; // Position
    property vertices[n: integer]: TVector2f read GetVertex write SetVertex; // Vertex Koordinaten
    property vertices_abs[n: integer]: TVector2f read GetVertexAbs; // Vertex Weltkoordinaten
    property Count: integer read GetCount; // siehe GetCount
  end;
  TPolygonArray = array of TPolygon;

function BrickBallIntersect(A, B: TPolygon; var MTD: TVector2f): boolean;

implementation

function CreateAxis(P: TPolygon): TV2fArray;
var
  i, l : integer;
  tmp : TVector2f;
begin
  for i := 0 to (P.count - 1) do
    begin
      l := i + 1;
      if l > (P.count - 1) then
        l := 0;
      // Berechnung der Seitenfläche
      tmp := v2f_sub(P.vertices[l], P.vertices[i]);
      // Berechnet die Normale der Seitenfläche
      setlength(result, length(result) + 1);
      result[high(result)] := v2f_normalize(to_v2f(-tmp.y, tmp.x));
    end;
end;

procedure ProjectOntoAxis(P: TPolygon; proj: TVector2f; var pmin, pmax: extended);
var
  i : integer;
  dp : extended;
begin // Projeziert den ersten Wert
  pmin := v2f_dotproduct(P.vertices[0], proj);
  pmax := pmin;
  // Findet den kleinsten und größten projezierten Wert für die Gerade für P
  for i := 1 to (P.count - 1) do
    begin
      // projezieren
      dp := v2f_dotproduct(P.vertices[i], proj);
      if dp < pmin then
        pmin := dp;
      if dp > pmax then
        pmax := dp;
    end;
end;

function CollisionCheck(A, B: TPolygon; var axis: TVector2f; voffset: TVector2f): boolean;
var
  foffset,
    amin, amax,
    bmin, bmax,
    d1, d2, depth : extended;
begin
  ProjectOntoAxis(A, axis, amin, amax);
  ProjectOntoAxis(B, axis, bmin, bmax);
  foffset := v2f_dotproduct(voffset, axis);
  amin := amin + foffset;
  amax := amax + foffset;
  d1 := amin - bmax;
  d2 := bmin - amax;
  // Wenn es keine Überschneidung gibt, abbrechen -> keine Kollision
  if (d1 > 0) or (d2 > 0) then
    begin
      result := false;
      exit;
    end;
  // Ansonsten den Verschiebungsvektor bestimmen
  depth := max(d1, d2);
  axis := v2f_scale(axis, abs(depth));
  result := true;
end;

function BrickBallIntersect(A, B: TPolygon; var MTD: TVector2f): boolean;
var
  axis : TV2fArray;
  voffset : TVector2f;
  i : integer;
begin
  MTD := to_v2f(0, 0);
  // Offset berechnen
  voffset := v2f_sub(A.position, B.position);
  // Alle Achsen für A
  axis := CreateAxis(A);
  // Alle Achsen für B
  axis := CreateAxis(B);
  // Projezieren der Polygone
  for i := 0 to high(axis) do
    if not CollisionCheck(A, B, axis[i], voffset) then
      begin
        result := false;
        exit;
      end;
  // MTD bestimmen
  MTD := axis[0];
  for i := 1 to high(axis) do
    if v2f_length(axis[i]) < v2f_length(MTD) then
      MTD := axis[i];
  if v2f_dotproduct(voffset, MTD) < 0 then
    MTD := v2f_scale(MTD, -1);
  // Kollision
  result := true;
end;

{ TPolygon }

procedure TPolygon.AddVertex(v: TVector2f);
begin
  setlength(fvertices, length(fvertices) + 1);
  fvertices[high(fvertices)] := v2f_sub(v, position);
end;

procedure TPolygon.AddVertexAbs(v: TVector2f);
begin
  setlength(fvertices, length(fvertices) + 1);
  fvertices[high(fvertices)] := v;
end;

function TPolygon.GetCount: integer;
begin
  result := length(fvertices);
end;

function TPolygon.GetVertex(n: integer): TVector2f;
var
  acos, asin : extended;
begin
  sincos(degtorad(angle), asin, acos);
  result.x := fvertices[n].x * acos + fvertices[n].y * -asin;
  result.y := fvertices[n].x * asin + fvertices[n].y * acos;
end;

function TPolygon.GetVertexAbs(n: integer): TVector2f;
begin
  result := v2f_add(fvertices[n], fposition);
end;

procedure TPolygon.RemoveVertex(n: integer);
var
  i : integer;
begin
  for i := n to high(fvertices) - 1 do
    fvertices[i] := fvertices[i + 1];
  setlength(fvertices, length(fvertices) - 1);
end;

procedure TPolygon.SetVertex(n: integer; Value: TVector2f);
begin
  fvertices[n] := Value;
end;

end.
Die ist nur abkopiert, sollte also soweit richtig sein.

Dann noch die Erstellung meiner Objekte:
Delphi-Quellcode:
procedure TGameForm.AddBrick(aX, aY: Double; aColor: Integer);
begin
  with TBrick.Create(AdSpriteEngine) do
    begin
      Image := AdImgLst.Find('brick');
      X := 1 + aX;
      Y := 1 + aY;
      Width := 90;
      Height := 20;
      Position := to_v2f(X, Y);
      AddVertex(to_v2f(90, -20));
      AddVertex(to_v2f(90, 0));
      AddVertex(to_v2f(0, 0));
      AddVertex(to_v2f(0, -20));
     { AddVertex(to_v2f(BoundsRect.Right, BoundsRect.Bottom));
      AddVertex(to_v2f(BoundsRect.Right, BoundsRect.Top));
      AddVertex(to_v2f(BoundsRect.Left, BoundsRect.Top));
      AddVertex(to_v2f(BoundsRect.Left, BoundsRect.Bottom));}

      Color := aColor;
      Typ := ptStatic;
      InitializeShape;
    end;
end;
und
Delphi-Quellcode:
procedure TGameForm.NewBall;
begin
  with TBall.Create(AdSpriteEngine) do
    begin
      Image := AdImgLst.Find('ball');
      X := Bat.X + Bat.Width / 2;
      Y := Bat.Y;
      Width := 10;
      Height := 10;
      Position := to_v2f(X, Y);
      AddVertex(to_v2f(10, -10));
      AddVertex(to_v2f(10, 0));
      AddVertex(to_v2f(0, 0));
      AddVertex(to_v2f(0, -10));
      {AddVertex(to_v2f(BoundsRect.Right, BoundsRect.Bottom));
      AddVertex(to_v2f(BoundsRect.Right, BoundsRect.Top));
      AddVertex(to_v2f(BoundsRect.Left, BoundsRect.Top));
      AddVertex(to_v2f(BoundsRect.Left, BoundsRect.Bottom));  }

    end;
  Bat.IsBallOnbat := true;
end;
Die Überprüfung findet hier statt:
Delphi-Quellcode:
for i := 0 to GameForm.AdSpriteEngine.Items.Count - 1 do
    begin
      if GameForm.AdSpriteEngine.Items[i] is TBrick then
        begin
          if BrickBallIntersect(GameForm.AdSpriteEngine.Items[i] as TBrick, self, MTD) then
            DoBrickCollision(GameForm.AdSpriteEngine.Items[i]);
        end;
    end;
Wenn ich das ganze starte, dann werden alle Bricks gleichzeitig "berührt" und verschwinden dann. Die Kollisionsabfrage klappt also nicht richtig...
Fabian E.
  Mit Zitat antworten Zitat
 


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 22:56 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz