AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Kollision mit Reflektion - Ich raffs net...
Thema durchsuchen
Ansicht
Themen-Optionen

Kollision mit Reflektion - Ich raffs net...

Ein Thema von Fussel9 · begonnen am 9. Feb 2011 · letzter Beitrag vom 13. Feb 2011
Thema geschlossen
Seite 1 von 3  1 23      
Benutzerbild von Fussel9
Fussel9

Registriert seit: 25. Mai 2009
322 Beiträge
 
Turbo Delphi für Win32
 
#1

Kollision mit Reflektion - Ich raffs net...

  Alt 9. Feb 2011, 21:30
Delphi-Version: 2006
hallo...

ich würde gerne nen BreakoutClone schreiben in Delphi mit nem Shape als Ball und Panels als Schläger und Bricks...

erst hatte ich diesen Quelltext selber geschrieben:

Delphi-Quellcode:
function TFormMain.collision(pCollisionObject: TPanel) : Boolean;
var
  I: Integer;
  J: Integer;
begin
result:=FALSE;
  for J := 0 to pCollisionObject.Height do
    begin
      if ((SBall.Left+SBall.Width)=(pCollisionObject.Top+J)) then
        begin
          result:=TRUE;
        end
      else
        begin
          if (SBall.Top=(pCollisionObject.Top+J)) then
            begin
              result:=TRUE;
            end
          else
            begin
              for I := 0 to pCollisionObject.Width do
                begin
                  if ((SBall.Top+SBall.Height)=(pCollisionObject.Left+I)) then
                    begin
                      result:=TRUE;
                    end
                  else
                    begin
                      if (SBall.Top=(pCollisionObject.Left+I)) then
                        begin
                          result:=TRUE;
                        end;
                    end;
                end;
            end;
        end;
    end;
end;
der funktioniert überhaupt nicht, dann hab ich von der Funktion IntersectRect gelesen,
die funktioniert zwar, aber ich weiß nicht wie ich damit das Reflektieren hinbekommen soll...

dann bin ich darauf gestoßen:
hi,

danke für die Hilfe. Der Ball reflektiert jetzt korrekt.

Delphi-Quellcode:

unit Uball;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, StdCtrls;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    Schlaeger: TShape;
    Pgrenze: TPanel;
    sball: TShape;
    BStart: TButton;
    procedure Timer1Timer(Sender: TObject);
    procedure BStartClick(Sender: TObject);
    procedure SchlaegerMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  bx: Integer;
  by: integer;
implementation

{$R *.DFM}

procedure TForm1.BStartClick(Sender: TObject);
begin
     bx:=5;
     by:=5;
     Timer1.enabled:=true;
end;


procedure TForm1.Timer1Timer(Sender: TObject);
begin

       sball.left:=sball.left+bx;
       if sball.left < 0 then
          begin
          sball.left := 1;
          bx := -bx;
          end;
          if sball.left > pgrenze.width - sball.width then
          begin
          sball.left := pgrenze.width - sball.width;
          bx := -bx;
          end;

       sball.top := sball.top+by;
       if sball.top < 0 then
          begin
          sball.Top := 1;
          by := -by;
          end;
       if sball.top > pgrenze.height - sball.height then
          begin
          sball.top := pgrenze.height - sball.height;
          by := -by;
          end;

end;


procedure TForm1.SchlaegerMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
Schlaeger.Left := X - Schlaeger.Width div 2;
end;

end.

Bei dem Mousemove procedure stimmt anscheinend auch etwas nicht. Meine Shape haftet sich sofort an die linke Wand und bewegt sich nur ab und zu mit meiner Maus. Aber auch nur um dann sofort wieder an die linke Wand zu hüpfen.

Wie kann ich einen Schläger programmieren?
den Quelltext kann ich nicht ganz nachvollziehen und ich weiß nicht was das mit dem Pannel PGrenze auf sich hat...

Vielleicht bin ich einfach zu doof


Grundsätzlich hab ich einfach nur vor den einfallswinkel je nach dem ob er > oder < 90,180 oder 270 bzw. 360 ist, in seiner differenz zu 180 zu behandeln.

(klingt komplizierter als es ist <siehe Anhang>)
__________________________________________________ __________________________________________________ __________

Jetz noch mal ganz bündig mein Problem: Mir fehlt bei IntersectRect der Einfallswinkel um den Ausfallswinkel zu berechnen und weiß nicht wie mans richtig machen muss....

Kann mir da bitte jemand helfen
Miniaturansicht angehängter Grafiken
winkel.jpg  
 
Delphi-Laie

Registriert seit: 25. Nov 2005
1.474 Beiträge
 
Delphi 10.1 Berlin Starter
 
#2

AW: Kollision mit Reflektion - Ich raffs net...

  Alt 9. Feb 2011, 22:22
Das "Raffen", wie Du es wohl zu verwenden scheinst, ist Jargon und bedeutet eigentlich - etwas gehoben, aber immer noch umgangssprachlich - gieriges Sammeln von Werten. Davon ausgehend, frage ich mich, was Du nicht "raffst".... oder begreifst Du etwas nicht - falls ja, was, und warum drückst Du Dich dann nicht so aus?

Wo ist denn in Deinen Quelltexten der Einfallswinkel parametriert (d.h., welche Variable verkörpert ihn)?

Geändert von Delphi-Laie ( 9. Feb 2011 um 22:41 Uhr)
 
Benutzerbild von Fussel9
Fussel9

Registriert seit: 25. Mai 2009
322 Beiträge
 
Turbo Delphi für Win32
 
#3

AW: Kollision mit Reflektion - Ich raffs net...

  Alt 9. Feb 2011, 22:35
Verzeihet, mir wart nicht geläufig das Dudenschreiben bei Hofe sind...

Ja ich verstehe den Quelltext nicht...

und zwar diese Stelle
Delphi-Quellcode:
       sball.left:=sball.left+bx;
       if sball.left < 0 then
          begin
          sball.left := 1;
          bx := -bx;
          end;
          if sball.left > pgrenze.width - sball.width then
          begin
          sball.left := pgrenze.width - sball.width;
          bx := -bx;
          end;

       sball.top := sball.top+by;
       if sball.top < 0 then
          begin
          sball.Top := 1;
          by := -by;
          end;
       if sball.top > pgrenze.height - sball.height then
          begin
          sball.top := pgrenze.height - sball.height;
          by := -by;
          end;
wieso: if sball.left > pgrenze.width - sball.width then
begin
sball.left := pgrenze.width - sball.width;

Und der Quelltext den ich geschrieben habe diente nur dazu festzustellen ob eine Kollision vorliegt evtl. auch noch wo..(oben unten rechts links) und nicht der reflektion ...


Ich hoffe das meine Ausführungen der deutschen Syntax genuge wurden...
 
Benutzerbild von BUG
BUG

Registriert seit: 4. Dez 2003
Ort: Cottbus
2.094 Beiträge
 
#4

AW: Kollision mit Reflektion - Ich raffs net...

  Alt 9. Feb 2011, 22:39
Davon ausgehend, frage ich mich, was Du nicht "raffst".... oder begreifst Du etwas nicht - falls ja, was, und warum drückst Du Dich dann nicht so aus?
Er versteht es nicht, das kann man ja aus dem Kontext folgern

Jetz noch mal ganz bündig mein Problem: Mir fehlt bei IntersectRect der Einfallswinkel um den Ausfallswinkel zu berechnen und weiß nicht wie mans richtig machen muss....
Du kannst den Winkel aus der aktuellen Verschiebung ermitteln.

Ich habe mal ein schönes häßliches Bild gemalt:
winkel.png
Intellekt ist das Verstehen von Wissen. Verstehen ist der wahre Pfad zu Einsicht. Einsicht ist der Schlüssel zu allem.
 
Benutzerbild von Fussel9
Fussel9

Registriert seit: 25. Mai 2009
322 Beiträge
 
Turbo Delphi für Win32
 
#5

AW: Kollision mit Reflektion - Ich raffs net...

  Alt 9. Feb 2011, 22:52
ein wunder fabuloses bild, nur hab ich cosinus,tangens und sinus schon im Matheunterricht aufs verrecken gehasst...

naja als ich weiß das man mit dem Tangens diese reflektion ausrechnet,
du hast geschrieben/gemalt tan=dy/dx
das ist z.B. was mir nix sagt... wenn ich ein dreieck habe mit den seitenlängen 3cm(dy),5cm(dx) und 2cm
und dan ist der Tangens von a 3/5 ... was hab ich davon?

in delphi ist der ursrung des koordinatensystems ja oben links statt unten links wie in einem normalen...
wirkt sich das irgendwie auf die berechnungen aus?

wenn ich jetzt meinen Ball hab und der läuft da gerade mit nem Winkel von ...ka... 30Grad übers feld und trifft auf den schläger, woher krieg ich dann dy und dx? (dx wahrscheinlich Schläger.Width ... aber dy?)

ach ich glaub das reicht an fragen für heute... hoffe das mir die jemand beantworten kann und dann gehts morgen weiter ^^ gute n8
 
QuickAndDirty

Registriert seit: 13. Jan 2004
Ort: Hamm(Westf)
1.883 Beiträge
 
Delphi 12 Athens
 
#6

AW: Kollision mit Reflektion - Ich raffs net...

  Alt 10. Feb 2011, 08:17
Du speicherst für deinen Ball einen Geschwindigkeitsvector.
Dieser Vector hat in einem 2 Dimensionalen System 2 Teilgeschwindigkeiten.
Die Vx und die Vy Geschwindigkeit.

Wenn du diese nicht schon wüsstest sondern erst ermitteln wolltest kämest du auf dx und dy.
Ball bei T1 hat die Koordinaten X1 und Y1
Ball bei T2 hat die Koordinaten X2 und Y2

Wenn für T2 -T1 = 1 gilt dann
ist Vxy
Vx = dx = X2-X1
Vy = dy = Y2-Y1

Daraus kannst du dann über den Tangens den Winkel ermitteln...

Wenn dein Ball nur an horizontalen und Vertikalen Flächen reflektiert ist es sogar noch einfacher...
...dann musst du nur das Vorzeichen einer der Teilgeschwindigkeiten umkehren.
Andreas
Monads? Wtf are Monads?
 
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#7

AW: Kollision mit Reflektion - Ich raffs net...

  Alt 10. Feb 2011, 10:28
Wenn dein Ball nur an horizontalen und Vertikalen Flächen reflektiert ist es sogar noch einfacher...
...dann musst du nur das Vorzeichen einer der Teilgeschwindigkeiten umkehren.
Mit ein bisschen Vektorzeugs geht das immer (und nicht nur an horizontalen/vertikalen Flächen) - dann braucht man den Tangens gar nicht mehr

Formel: v_neu = v_alt - 2 * (v_alt*n)*n
n ist der Normalenvektor der Fläche, v_neu und v_alt die vorher/nachher Geschwindigkeitsvektoren.

Zitat:
wieso:
Delphi-Quellcode:
if sball.left > pgrenze.width - sball.width then
begin
sball.left := pgrenze.width - sball.width; //(1)
bx := -bx;//(2)
Naja, wenn der Ball rechts rausfliegt, wird der Ball (1) zurückgesetzt an den Rand und (2) die x Geschwindigkeit negiert, damit er wieder in die andere Richtung fliegt. (1) ist nötig weil es sonst passieren könnte, dass der Ball etwas zu weit raus fliegt und im nächsten Schritt wieder eine Kollision erkannt wird. Das darf nicht sein weil der Ball dann am rechten Rand hängen bleiben würde.
 
Benutzerbild von Fussel9
Fussel9

Registriert seit: 25. Mai 2009
322 Beiträge
 
Turbo Delphi für Win32
 
#8

AW: Kollision mit Reflektion - Ich raffs net...

  Alt 10. Feb 2011, 21:41
Zitat:
Naja, wenn der Ball rechts rausfliegt, wird der Ball (1) zurückgesetzt an den Rand und (2) die x Geschwindigkeit negiert, damit er wieder in die andere Richtung fliegt. (1) ist nötig weil es sonst passieren könnte, dass der Ball etwas zu weit raus fliegt und im nächsten Schritt wieder eine Kollision erkannt wird. Das darf nicht sein weil der Ball dann am rechten Rand hängen bleiben würde.
ok das hab ich jetz verstanden, aber das mit dem ganzen vektorengedönz...#_#

Zitat:
Wenn für T2 -T1 = 1 gilt dann
ist Vxy
Vx = dx = X2-X1
Vy = dy = Y2-Y1
T2-T1=1
das ist nur der Fall wenn T2 zufällig T1*2 ist
angenommen T2 wäre (4|4) dann muss T1 (2|2) sein damit diese Kondition erfüllt ist... nicht unbedingt wahrscheinlich...

und wo bleibt der Richtungsvektor? Ich hab jetz ma ne Zeichnung gemacht und erkenne keine Zusammenhänge...


Zitat:
Formel: v_neu = v_alt - 2 * (v_alt*n)*n
n ist der Normalenvektor der Fläche, v_neu und v_alt die vorher/nachher Geschwindigkeitsvektoren.
venn VNeu darstellt wo sich der Ball jetzt befinden wird und VAlt wo der Ball vorher war, woher nehme ich dann den Normalenvektor der Fläche (ich denke mal das soll z.B. der Schläger oder der Brick sein)
Und worauf basiert die Formel? 2* den alten Vektor*Normalenvektor und dann nochmal * den Normalenvektor ...
...

und das sind so die punkte an denen ich dann wieder raus bin,,,

ich speicher übrigens nicht die xy sondern den winkel für den ball hilft mir das irgendwie weiter?
ich glaub das kann ich so gar nicht machen oder?
Delphi-Quellcode:
procedure TFormMain.MoveByAngle(pWinkel: Integer);
begin
  if (pWinkel<90) then
    begin
      SBall.Top:=SBall.Top+10;
      SBall.Left:=SBall.Left-pWinkel;
    end
  else
    begin
      if (pWinkel=90) then
        begin
          SBall.Left:=SBall.Left-pWinkel;
        end
      else
        begin
          if (pWinkel<=180) then
            begin
              SBall.Top:=SBall.Top-10;
              SBall.Left:=SBall.Left-pWinkel;
            end
          else
            begin
              if (pWinkel<270) then
                begin
                  SBall.Top:=SBall.Top-10;
                  SBall.Left:=SBall.Left+pWinkel;
                end
              else
                begin
                  if (pWinkel=270) then
                    begin
                      SBall.Left:=SBall.Left+pWinkel;
                    end
                  else
                    begin
                      if (pWinkel<=360) then
                        begin
                          SBall.Top:=SBall.Top+10;
                          SBall.Left:=SBall.Left+pWinkel;
                        end;
                    end;
                end;
            end;
        end;
    end;
end;
Miniaturansicht angehängter Grafiken
vektor_t1_t2.jpg  
 
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#9

AW: Kollision mit Reflektion - Ich raffs net...

  Alt 10. Feb 2011, 22:16
Du würdest dir mit Vektoren wesentlich einfacher tun.
Zitat:
ich speicher übrigens nicht die xy sondern den winkel für den ball hilft mir das irgendwie weiter?
ich glaub das kann ich so gar nicht machen oder?
Genau dafür sind die nämlich praktisch - anstatt des Winkels speicherst du ein deltaX und ein deltaY. Und jedesmal, wenn sich der Ball bewegen soll, veränderst du seine X Postition um deltaX udn seine Y Position um deltaY.

Die Prozedur sieht dann so aus:
Delphi-Quellcode:
procedure TFormMain.MoveByAngle(pWinkel: Integer);
begin
    SBall.Top := SBall.Top + deltaX;
    SBall.Left := SBall.Left + deltaY;
end;
Und über diese deltas steuerst du dann die Bewegungsrichtung.

P.S.: In diesem Zusammenhang ist ein "Vektor" auch nur etwas, um 2 Zahlen "zusammenzufassen". die kannst also deltaX und deltaY als einen Vektor interpretieren. Oder CBall.Left und SBall.Top als einen Vektor.
Zitat:
venn VNeu darstellt wo sich der Ball jetzt befinden wird und VAlt wo der Ball vorher war, woher nehme ich dann den Normalenvektor der Fläche (ich denke mal das soll z.B. der Schläger oder der Brick sein)
Und worauf basiert die Formel? 2* den alten Vektor*Normalenvektor und dann nochmal * den Normalenvektor ...
Und das v aus meinem Beitrag ist dann genau dieser Vektor deltaX/deltaY. Das v ist also nicht die Position, sondern die Geschwindigkeit des Balls!
Die Formel basiert auf Einfallswinkel=Ausfallswinkel. Habe ich vorhin selbst hergeleitet, aber ist sicher noch woanders zu finden.[1] [2] Den Normalenvektor der Fläche musst du wissen - wenn der Ball z.B. oben an den Rand gestoßen ist, dann ist der Normalenvektor (0|1) (Y Achse zeigt ja nach unten, daher +1)
Ach, und: Die Produkte sind Skalarprodukte, die musst du schon genau so rechnen. Assoziativgesetz gilt nicht, also die Klammern sind wichtig!

ich hoffe das hat mehr geholfen als verwirrt

Geändert von jfheins (10. Feb 2011 um 22:22 Uhr)
 
Benutzerbild von Fussel9
Fussel9

Registriert seit: 25. Mai 2009
322 Beiträge
 
Turbo Delphi für Win32
 
#10

AW: Kollision mit Reflektion - Ich raffs net...

  Alt 11. Feb 2011, 16:07
Zitat:
ich hoffe das hat mehr geholfen als verwirrt
Nope ^^

Ich versteh jetz nicht, woher ich zur laufzeit den Normalenvektor her nehmen soll.. hier ist meine Move methode ohne winkelberechnung... so wie ich sie in nem anderen threat gefunden hatte nur weiter ausgebaut.

Delphi-Quellcode:
procedure TFormMain.MoveBall(pCollisionObject: array of TPanel);
var tempObject,CollisionRect: TRect;
    I: Integer;
begin
  sball.left:=sball.left+XCor;
  Ball.Left:=SBall.Left;
  Ball.Right:=SBall.Left+SBall.Width;
    if sball.left < (PLinks.Left+PLinks.Width) then
      begin
      sball.left := (PLinks.Left+PLinks.Width);
      Xcor := -Xcor;
      end;
    if sball.left > PRechts.Left - sball.width then
      begin
      sball.left := (PRechts.Left - sball.width);
      XCor := -XCor;
      end;


  sball.top := sball.top+YCor;
  Ball.Top:=SBall.Top;
  Ball.Bottom:=SBall.Top+SBall.Height;
    if sball.top < (POben.Top+POben.Height) then
      begin
      sball.Top := (POben.Top+POben.Height);
      YCor := -YCor;
      end;
    if sball.top > (self.height - sball.height) then
      begin
      sball.top := (self.height - sball.height);
      YCor := -YCor;
      end;
    if IntersectRect(Collision,Ball,Stick) then
      begin
        sball.top := (PStick.top - sball.height);
        YCor:= -YCor;
      end;
    if Sball.Top > PStick.Top then
      begin
        SBall.Visible:=False;
        TMover.Enabled:=False;
        MessageDLG('Game Over!',mtWarning,[mbOk],0);
        SpawnBall;
      end;
    for I := 0 to High(pCollisionObject) - 1 do
      begin
        tempObject.Left:=pCollisionObject[I].Left;
        tempObject.Right:=pCollisionObject[I].Left+pCollisionObject[I].Width;
        tempObject.Top:=pCollisionObject[I].Top;
        tempObject.Bottom:=pCollisionObject[I].Top+pCollisionObject[I].Height;
        if IntersectRect(CollisionRect,Ball,tempObject) then
          begin
            YCor:= -YCor;
            XCor:= -XCor;
            pCollisionObject[I].Visible:=False;
            pCollisionObject[I].Left:=0-PCollisionObject[I].Width;
            pCollisionObject[I].Top:=0-PCollisionObject[I].Height;
          end;
      end;
end;
hier der Methodenaufruf:
Delphi-Quellcode:
procedure TFormMain.TMoverTimer(Sender: TObject);
begin
  MoveBall([Panel2,Panel3,Panel4,Panel5,Panel6,Panel7,Panel8,Panel9,Panel10,
           Panel11,Panel12,Panel13,Panel14,Panel15,Panel16,Panel17,Panel18,
           Panel19,Panel20,Panel21,Panel22,Panel23,Panel24,Panel25,Panel26,
           Panel27,Panel28,Panel29,Panel30,Panel31,Panel32,Panel33,Panel34,
           Panel35,Panel36,Panel37,Panel38,Panel39,Panel40,Panel41,Panel42,
           Panel43,Panel44,Panel45,Panel46,Panel47,Panel48,Panel49,Panel50,
           Panel51,Panel52,Panel53,Panel54,Panel55,Panel56,Panel57]);
end;
und im anhang mal die pas

Wenn mein Ball jetzt auf einen Stein trifft, woher nehme ich dann den Normalenvektor? Der Normalenvektor beschreibt doch eine im rechten winkel zur fläche stehende gerade, oder?


ich geb es einfach mal auf die formel nachzuvollziehen und sehe sie als gegeben...

Wenn mir jetzt jemand sagen kann woher ich den dusseligen Normalenvektor nehmen soll dann könnte ichs ja programmieren...

Zitat:
Den Normalenvektor der Fläche musst du wissen - wenn der Ball z.B. oben an den Rand gestoßen ist, dann ist der Normalenvektor (0|1) (Y Achse zeigt ja nach unten, daher +1)
... das hat mir irgendwie nicht weitergeholfen...
Angehängte Dateien
Dateityp: pas UMain.pas (5,9 KB, 2x aufgerufen)
 
Thema geschlossen
Seite 1 von 3  1 23      


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 04:38 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