AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Vektoriales Rechnen

Ein Thema von Maurooon · begonnen am 12. Mai 2017 · letzter Beitrag vom 16. Mai 2017
Antwort Antwort
Seite 3 von 3     123   
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
721 Beiträge
 
Delphi 11 Alexandria
 
#21

AW: Vektoriales Rechnen

  Alt 16. Mai 2017, 07:52
Hallo Mauroon

die Funktion ZweiObjekte( ) überprüft, ob sich zwei Objekte a und b, welche sich mit gleichmässiger Geschwindigkeit je entlang einer Gerade bewegen jetzt gerade oder in der Zukunft treffen werden.

IN:
a1 : Momentaner Standort von a
a2 : a ist unterwegs von a1 in Richtung a2
ppsa: Geschwindigkeit von a in Pixel Pro Sekunden
radiusa : Zur Vereinfachung wird für die Form der Objekte ein Kreis mit Radius radiusa angenommen. [Man könnte hier natürlich auch ein Rechteck oder die wirkliche Form annehmen.]

OUT:
treffpunkt_a : Ortsvektor von a beim Zusammentreffen mit b.
kontakt: TRUE, wenn sich die beiden Objekte momentan überlappen.
zeit_bis_a2: Zeit, welche a von a1 nach a2 benötigt
Result: TRUE, wenn sich die beiden Objekte jetzt treffen oder sich in Zukunft treffen werden.
Falls Result=TRUE: sekundenbiszumteffen: Nach dieser Zeit treffen a und b aufeinander.



Delphi-Quellcode:
function ZweiObjekte( a1, a2 : TRPoint; radiusa : extended; ppsa : extended;
                      b1, b2 : TRPoint; radiusb : extended; ppsb : extended;
                      var treffpunkt_a, treffpunkt_b : TRPoint;
                      var zeit_bis_a2 : extended; var sekundenbiszumteffen : extended; var kontakt : boolean ):boolean;

var speeddelta, startdelta, speeda, speedb : TVektor;
    Radius : extended;
    quadres : TQuadResultat;
    res : boolean;

    function getVektor( a, b : TRPoint ): TVektor;
    begin
        Result.x := b.x - a.x;
        Result.y := b.y - a.y;
    end;

    function speedvektor( v : TVektor; pps : extended ) : TVektor;
    var len : extended;
    // IN v in Bewegungsrichtung pps=Speed des Objekts Pixel pro Sekunden
    // OUT Vektor - nach einer Sekunde hat sich das Objekt um diesen Vektor verschoben
    begin
        len := sqrt( sqr(v.x) + sqr(v.y) );
        if ( len > 0 ) then
        begin
          Result.x := v.x/len*pps;
          Result.y := v.y/len*pps;
        end
        else
        begin
          v.x := 0;
          v.y := 0;
        end;
    end;

    function OrtNachTSekunden( start, speedvektor : TVektor; sec : extended ) : TVektor;
    begin
        Result.x := start.x + sec*speedvektor.x;
        Result.y := start.y + sec*speedvektor.y;
    end;

    function hkontakt( pos1, pos2 : TRPoint; radius1, radius2 : extended ):boolean;
    begin
        Result := sqrt(sqr(pos2.x-pos1.x) + sqr(pos2.y-pos1.y)) < (radius1 + radius2);
    end;


begin
  Radius := radiusa + radiusb;
  res := false;
  kontakt := false;

  // Objekt a bewegt pro Sekunde "speeda" vorwärts - Objekt b bewegt pro Sekunde "speeda" vorwärts
  speeda := speedvektor( getVektor( a1, a2 ), ppsa );
  speedb := speedvektor( getVektor( b1, b2 ), ppsb );

  // Solange benötigt a von a1 nach a2:
  if abs(speeda.x) > abs(speeda.y) then
    zeit_bis_a2 := ( a2.x - a1.x )/speeda.x else
    zeit_bis_a2 := ( a2.y - a1.y )/speeda.y;

  // nach t Sekunden befindet sich Objekt a an der Stelle a1 + t*speeda,
  // nach t Sekunden befindet sich Objekt b an der Stelle b1 + t*speedb
  // Treffen die Objekte aufeinander? D.g. gibt es ein t: a1 + t*speeda = b1 + t*speedb?
  speeddelta := getVektor( speedb, speeda );
  startdelta := getVektor( b1, a1 );

  if ( speeddelta.x = 0 ) and ( speeddelta.y = 0 ) then
  begin // die relative geschwindigkeit zwischen a und b ist 0 =>
        // prüfen, ob sich a und b am momentanen ort berühren:
      res := hkontakt( a1, b1, radiusa, radiusb );
      treffpunkt_a := a1;
      treffpunkt_b := b1;
      kontakt := res;
      sekundenbiszumteffen := 0;
  end
  else
  begin
       // sonst muss für ein Zusammentreffen nach t gelten:
       // ¦a1+t*speeda - (b1+t*speedb)¦ < Radius =>
       // Dies führt auf eine quadratische Gleichung in t, welche wir lösen müssen:
      if Quadratische_Gleichung_Reell( (sqr(speeddelta.x) + sqr(speeddelta.y)),
        2*( speeddelta.x * startdelta.x + speeddelta.y * startdelta.y),
        sqr(startdelta.x) + sqr(startdelta.y)- sqr(Radius),
        quadres ) then
      begin
          // quadres.x2 ist immer <= quadres.x1 (da in dieser quadratischen Gleichung (at^2+bt+c=0) a immer positiv ist)
          if ( quadres.x1 <> quadres.x2 ) then // wir werden nur Überschneidungen der Kreise als Treffer
          begin
              kontakt := ( quadres.x2 < 0 ) and ( quadres.x1 > 0 );
              if kontakt then
              begin
                 // a und b haben momentan einen gemeinsamen Schnitt
                 treffpunkt_a := a1;
                 treffpunkt_b := b1;
                 res := true;
                 sekundenbiszumteffen := 0;
              end
              else
              begin
                 // a und b werden in quadres.x2 Sekunden einen gemeinsamen Schnitt haben
                 if ( quadres.x2 > 0 ) then
                 begin
                    treffpunkt_a := OrtNachTSekunden( a1, speeda, quadres.x2 );
                    treffpunkt_b := OrtNachTSekunden( b1, speedb, quadres.x2 );
                    res := true;
                    sekundenbiszumteffen := quadres.x2;
                 end;
              end;
          end;
      end;
  end;
  Result := res;
end;


Anwendungsbeispiel:
Dein Spielobjekt a befindet sich an Position a1, das Zielobjekt an Position a2. a (dein Projektil) bewegt sich mit ppsa in Richtung a2.
b ist ein Hindernis, welches sich auch bewegt oder auch still steht ( dann ppsb = 0 wählen ).
Die Funktion überprüft, ob und wann (var sekundenbiszumteffen) a auf b treffen wird.
Die Funktion berechnet ebenfalls, wie lange a von a1 nach a2 benötigt.


Code unten:
a bewegt sich entlang der x Achse von x=1000 nach -1000. speed 500
b bewegt sich entlang der y Achse von y=500 nach 0. speed 250

Die Funktion gibt TRUE zurück, weil sich die Objekte natürlich nach ca. 2 Sekunden in der Region (0,0) treffen werden.
a und b treffen nach treffer_in_sec=1.989266873708 aufeinander.
a benötigt von a1 nach a2 bisa=4 Sekunden.
=> a trifft aufs Hindernis b, bevor a beim Punkt a2 angekommen ist.

Delphi-Quellcode:
procedure TForm92.Button1Click(Sender: TObject);
var a1, a2, b1, b2, tpa, tpb : TRPoint;
    ppsa, ppsb, radiusa, radiusb, bisa2, treffer_in_sec : extended;
    kontakt : boolean;

begin
  a1 := RPoint( 0,1000);
  a2 := RPoint( 0,-1000 );
  b1 := RPoint( 500,0 );
  b2 := RPoint( 0,0 );

  radiusa := 3;
  radiusb := 3;
  ppsa := 500;
  ppsb := 250;

  if ZweiObjekte( a1, a2, radiusa, ppsa,
                  b1, b2, radiusb, ppsb, tpa, tpb, bisa2, treffer_in_sec, kontakt ) then
  begin
      showmessage( 'treffer' );
  end
  else showmessage( 'kein treffer' );
end;
Michael Gasser
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 3     123   


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:55 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