![]() |
Geschwindigkeit umkehren
Guten Abend alle miteinander.
Momentan arbeite ich an einem kleinen Spiel, in dem es darum geht, Kreise zu vernichten. Diese Kreise werden mit einem timer erzeugt (array of TKreis). Sie haben eine grundgeschwindigkeit von speedx=5 und speedy=5. Es gibt Objectives und Weapons, unter Objectives findet man unter anderem eine Kiste. Ich bewege sie in dem ich ihr einfach die mausposition zuweise. Das Problem ist das ich nicht weiß wie ich eine gute Kollision hinbekomme. Kollidieren die Kiste und ein kreis wird der kreis momentan in die selbe richtung aus der er kam zurückgeschleudert. ich will aber einfallswinkel gleich ausfallswinkel. Was ich bisher ausprobiert habe (ohne Erfolg):
Delphi-Quellcode:
und:
if InterSectRect(StubRect,Kreis[b].BoundsRect,Image3.BoundsRect) and Image3.Visible then
begin Kreis[b].speedx := -(Kreis[b].speedx); Kreis[b].speedy := -(Kreis[b].speedy); end; end;
Delphi-Quellcode:
if InterSectRect(StubRect,Kreis[b].BoundsRect,Image3.BoundsRect) and Image3.Visible then
begin Kreis[b].speedx := -Abs(Kreis[b].speedx); Kreis[b].speedy := -Abs(Kreis[b].speedy); end; |
AW: Geschwindigkeit umkehren
Wenn du nur die Speed-Werte umkehrst, ist es ja klar, dass der Kreis in exakt die selbe Richtung zurückfliegt, aus die er kam.
Was du noch brauchst ist eine Feststellung aus welcher Richtung die Kollision kommt und musst entsprechend darauf reagieren. Von oben und unten: Y = -Y Von links und rechts: X = -X PS: Ich würde empfehlen, dass du dir auch mal Andorra 2D anschaust. Die VCL (TImage, ...) als Sprites zu verwenden ist auf lange Frist keine effiziente Lösung. |
AW: Geschwindigkeit umkehren
ja ich weiß, das ist mir auch bewusst, nur ich wusste nicht wie es richtig geht.
Wieso soll ich kein Image verwenden? Ist schon etwas später, wie genau stellst du dir die Abfrage vor. ich hatte überlegt man könnte es mit dem Satz des Pythagoras machen, aber gibt es nicht noch was einfacheres? |
AW: Geschwindigkeit umkehren
Liste der Anhänge anzeigen (Anzahl: 1)
Im Prinzip ist es einfache Mathematik.
Du hast 2 Vektoren, der aufeinandertreffenden Objekte. Daraus kannst du eine Aufschlagebene berechnen, wie die Kräfte aufeinandertreffen. Und darüber berechnest du dann jeweils die Winkel, wie es weitergeht. Aber im Prinzip kommt dann noch mehr mit rein, wenn man es genau machen will. - die jeweilige Geschwindigkeit der Objekte - und die Größe/Masse (also ob z.B. Kraft von einem Objekt auf das Andere übertragen wird) - und teilweise auch die Form der Objekte, denn jenachdem wie und an welche Stelle der Aufschlag geschieht, kann sich das auch noch auswirken |
AW: Geschwindigkeit umkehren
Zitat:
Code:
Nur als grobes Beispiel.
Wenn Kollision Dann
Wenn Quellobjekt.Y + Quellobjekt.Höhe >= Zielobjekt.Y Dann Kollisionsrichtung = Von oben Wenn Quellobjekt.X + Quellobjekt.Breite >= Zielobjekt.X Dann Kollisionsrichtung = Von links ... |
AW: Geschwindigkeit umkehren
Nennt sich dann
![]() |
AW: Geschwindigkeit umkehren
Erinnert mich fast an
![]() |
AW: Geschwindigkeit umkehren
Zugegeben: Mathematische Wipkipedia Artikel tendieren teilweise stark zu unnötig komplexen Formeln und Symbolgeilheit (oftmals wirklich für das breite Publikum unangemessen verklausuliert). Hier finde ich es aber doch noch recht okay - sind ja wirklich nur Grundrechenarten :) Wenn man die Formeln ein wenig auseinanderklamüsert sieht man, dass das an sich ziemlich popelig ist. Schaut auf den ersten Blick nur gewaltig aus.
In diesem Fall nicht nötig: Aber wenn man sich einfach mal vor Augen hält, dass eine Summenformel nichts weiter ist, als eine for-Schleife mit der Formel dahinter im Rumpf, verlieren zumindest diese schon mal ihre abschreckende Wirkung =) Die Seite ist aber eine ziemlich herrliche Satire! Manchmal fühlt man sich echt so :) |
AW: Geschwindigkeit umkehren
Danke für die Lösung. Ich habe jetzt mal angefangen mit der Kollision
Delphi-Quellcode:
und das funktioniert auch alles soweit, aber als ich versucht habe die kollision von unten und den Seiten zu schreiben, kam ich nicht mehr so ganz weiter. mit diesem code ging es nicht:
if (Kreis[b].y+Kreis[b].Height)>Image3.Height then //Kreis kommt von oben
Kreis[b].speedy := -Abs(Kreis[b].speedy);
Delphi-Quellcode:
if Kreis[b].x+Kreis[b].Width>Image3.Width then //
begin Kreis[b].speedy := -Abs(Kreis[b].speedy); Kreis[b].speedx:= Abs(Kreis[b].speedx); end; |
AW: Geschwindigkeit umkehren
bei den Seitenprüfungen musst Du x invertieren // wahrscheinlich ein Flüchtigkeitsfehler.
Du kannst links rechts zusammen und oben unten ebenfalls zusammen behandeln. |
AW: Geschwindigkeit umkehren
Was genau ist denn mit "x invertieren" gemeint?
Soll ich die speedx invertieren? und wieso kann ich rechts und links und oben und unten als eins behandeln. Funktioniert zumindest nicht |
AW: Geschwindigkeit umkehren
ich meinte etwas in der Art ....
Delphi-Quellcode:
if ((Kreis[b].y+Kreis[b].Height)>Image3.Height) or (Kreis[b].y <=0 ) then
Kreis[b].speedy := - Kreis[b].speedy; if ((Kreis[b].x+Kreis[b].Width)>Image3.Width) or (Kreis[b].x <= 0) then Kreis[b].speedx := - Kreis[b].speedx; |
AW: Geschwindigkeit umkehren
Mit diesem Code passiert leider genau das, was ich vermeiden wollte:
Der Ball prallt wieder in die Richtung, aus der er kam und nicht "Einfallswinkel=Ausfallswinkel" |
AW: Geschwindigkeit umkehren
die Stelle mit der Positionszuweisung sieht schon so oder so ähnlich aus ?
Delphi-Quellcode:
ich hatte vor längerem mal ein Thema wo so etwas auch verwendet wurde ...
Kreis[b].x := Kreis[b].x + Kreis[b].speedy;
Kreis[b].y := Kreis[b].y + Kreis[b].speedx; ![]() |
AW: Geschwindigkeit umkehren
Nein so oder so ähnlich sah sie nicht aus, aber mit dieser Zuweisung bugt es komplett rum.
Die Kreise bleiben stehen wenn sie jetzt das Objekt berühren... |
AW: Geschwindigkeit umkehren
Zitat:
2) So schwer ist es nicht. Es ist einfach nur Logik und hat nichts mit Programmieren zu tun. Logikarbeit nehme ich dir aber nicht ab, weil's der Punkt ist, wo du am meisten lernen kannst. :mrgreen: |
AW: Geschwindigkeit umkehren
1.Mir wurde erklärt das "abs" die Richtung absolut umkehrt und irgendwie sinnvoller wäre.
2.ja das ist richtig, ich will es auch gerne alleine schaffen, aber so ganz peile ich es noch nicht. x und y zeigen die Position auf x und y Achsen an aber geht diese Position jetzt von der Mitte des Kreises aus oder wieso verrechnen wir diese Koordinaten mit der höhe? |
AW: Geschwindigkeit umkehren
Zitat:
Hier musst Du einfach die Grenzen Deinen Gegebenheiten anpassen und rechts Width/2 zu x addieren und links statt 0 Width/2 verwenden, entsprechend für die y Koordinaten ... |
AW: Geschwindigkeit umkehren
Zitat:
Wer auch immer dir das wie du schriebst erzählt hat, wollte dich entweder veräppeln, oder ist definitiv nicht die richtige Person für mathematische Fragen. (Zumal ich nichtmal wüsse, wie man "absolut umkehren" verstehen sollte.) |
AW: Geschwindigkeit umkehren
Das Problem war wohl, dass ich mit dem Programm vor Ewigkeiten angefangen habe und mir über x und y nicht mehr im klaren war.
Die beiden variablen werden beim erzeugen des kreises verwendet um einen beliebigen startpunkt zu wählen, das sieht dann so aus:
Delphi-Quellcode:
Kreis [a].x := Kreis [a].radius + random (1000 - 2*Kreis [a].radius);
Kreis [a].y := Kreis [a].radius + random (500 - 2*Kreis [a].radius); |
AW: Geschwindigkeit umkehren
:cyclops:
Random für x und für y ... ok, dann weißt Du ja wo Du hinfassen musst, wobei gegen eine zufällige Positionierung nichts spricht solange Du weißt worauf sich x und y beziehen ... (z.B. top/left, center ...) |
AW: Geschwindigkeit umkehren
Zitat:
Zeichne deine Kreise und deine Objekte, beschrifte sie, zeichne Pfeile, gepunktete Linien um Bewegungen darzustellen ... Zitat:
Wenn du also eine Kollision rechts vom Objekt feststellen willst, muss du X + Breite addieren und prüfen, ob sie >= dem X-Wert des Kollisionsobjekts sind. Wenn du auf eine Kollision links vom Objekt prüfen willst, musst du schauen, ob der X-Wert des Kollisionsobjekts + Breite des Kollisionsobjekts <= dem X-Wert deines Objekts sind. Denn einem normalen Sprite-Objekt liegt in der Regel immer ein Quadrat zu Grunde, mit dem man arbeitet, auch wenn es einen Kreis darstellt (der Kreis wird dann in das Quadrat gezeichnet). |
AW: Geschwindigkeit umkehren
So also da bin ich wieder und habe mich direkt mal an die Arbeit gemacht.
X und Y werden wie folgt beschrieben:
Delphi-Quellcode:
Nun zeigen die beiden ja die Position genau so an, wie es notwendig wäre. Wieso funktioniert es nun trotzdem nicht bzw. wieso prallt der Ball mit Bummis Sourcecode falsch ab und bugt rum
for b := 0 to high(Kreis) do
begin Kreis [b].x := Kreis [b].x + Kreis [b].speedx; //Geschwindigkeit X Kreis [b].y := Kreis [b].y + Kreis [b].speedy; //Geschwindigkeit Y With Kreis [b] do begin Left := Kreis [b].x; Top := Kreis [b].y; end; |
AW: Geschwindigkeit umkehren
pack das ganze doch mal in ein Zip, so stochern wir im Nebel rum ...
|
AW: Geschwindigkeit umkehren
Irgendwie hab ich das Gefühl, dass das Ganze bei dir 'n ziemliches Flickwerk ist. :mrgreen: Daher nochmal der Tipp: Geh dein Projekt und dein Vorhaben nochmal analytisch durch. Denn wenn du nicht weißt, warum und weshalb etwas geht oder nicht geht, dann weil dir selbst nicht klar ist, was da überhaupt passiert. Und da kommt man dahin, wo wir jetzt sind: Unklare Fragestellung durch unklare Problemformulierung, weil du scheinbar selbst den Überblick irgendwie über das Projekt verloren hast. Oder?
1)
Delphi-Quellcode:
Warum 0 to ... und nicht Low(Kreis) to ...?
for b := 0 to high(Kreis) do
2)
Delphi-Quellcode:
Wo wird Width und Height gesetzt?
With Kreis [b] do
begin Left := Kreis [b].x; Top := Kreis [b].y; end; |
AW: Geschwindigkeit umkehren
Liste der Anhänge anzeigen (Anzahl: 1)
Okay alles klar, ich habe den ganzen Kram mal angehängt
|
AW: Geschwindigkeit umkehren
Die Bitmapprobleme hat ja Sir Rufo bereits beantwortet.
Das Klebeproblem lässt sich hierdurch beseitigen, allerdings ist das noch nicht final, da durch die Bedingungen Kollisionen z.B. oben und rechts gleichzeitig gefunden werden, was zu einer optisch nicht nachzuvollziehenden Reflexion führt. Ich habe leider jetzt nicht mehr die Zeit mir eine brauchbare Bedingung zu suchen. Aber wir haben ja genügend Mitstreiter hier ...
Delphi-Quellcode:
if InterSectRect(Stubrect, Kreis[b].BoundsRect, Image3.BoundsRect) and Image3.Visible then // Box
begin if ((Kreis[b].y + Kreis[b].Height) > Image3.top) or (Kreis[b].y <= (Image3.top + Image3.Height)) then Kreis[b].speedy := -Kreis[b].speedy; if ((Kreis[b].x + Kreis[b].Width) > Image3.left) or (Kreis[b].x <= (Image3.Left + Image3.Width)) then Kreis[b].speedx := -Kreis[b].speedx; end; Kreis[b].x := Kreis[b].x + Kreis[b].speedx; Kreis[b].y := Kreis[b].y + Kreis[b].speedy; |
AW: Geschwindigkeit umkehren
Danke trotzdem für die ganze Mühe :-D
Mit diesem Code funktoniert die Kollision leider nicht wie gewollt (altes Problem, Einfallswinkel=Einfallswinkel) und manchmal bleibt ein Kreis hängen. Aber ich bin schon ein Stück weiter, danke dafür. Haben die Anderen den vielleicht noch Ideen, dass zu realisieren? Ist wichtig und sollte bis Montag fertig sein, wenn möglich |
AW: Geschwindigkeit umkehren
Den elastischen Stoß hab' ich hier mal gepostet:
![]() Gruß Thomas |
AW: Geschwindigkeit umkehren
@Bjoerk: So ganz blicke ich bei dem Code noch nicht durch. Mit Matrizen habe ich mich noch nicht beschäftigt
|
AW: Geschwindigkeit umkehren
Hat nicht noch Jemand eine Lösung.
Der Code von Bummi lässt die Kreise in die selbe Richtung zurückprallen aus der sie kamen, aber wie bereits gesagt, ich will eine Einfallswinkel=Ausfallswinkel Kollision und zudem müsste das Bug Problem behoben werden: Wenn man den Block zu schnell bewegt, bleiben die Kreise darin hängen :/ |
AW: Geschwindigkeit umkehren
Es wurden doch etliche Lösungsansätze geposted, und sogar ein gutes Stück Code verlinkt. Mach dich doch erstmal an die Umsetzung dieser Ideen (es sind die richtigen, sei versichert), und wenn dabei konkrete Probleme auftauchen, reden wir hier weiter.
|
AW: Geschwindigkeit umkehren
Liste der Anhänge anzeigen (Anzahl: 1)
Durch die Geschwindigkeit bekommst Du wie gesagt bei einem Treffer in der Auswertung für x und y Überschneidungen. Ein recht brauchbarer Weg könnte es sein statt der Region die Du jetzt verwendest 4 Regions je 1 Pixel hoch(horizontal) bzw. breit(vertikal) und Kantenlänge - Geschwindigkeit * 2 , zentriert auf den Kanten, in der anderen Dimension zu verwenden.
Dann sollte ein CombineRegion nacheinander über die 4 Seiten die richtige Auswertung zulassen. |
AW: Geschwindigkeit umkehren
Hmm das klingt schon sehr gut, aber wie soll ich das denn umsetzten. Ehrlich gesagt, fällt mir da jetzt so direkt keine konkrete Umsetzungsmöglichkeit in Delphi ein :?
Tut mir leid, dass ich nicht so der Profi bin, ich tue schon alles Mögliche, um mein Delphi Wissen zu steigern :oops: |
AW: Geschwindigkeit umkehren
Du kannst behelfsweise auch mit InterSectRect an der Stelle weiterabeiten, dann sind es halt 4 Rects statt 4 Regions ,der Kreis durch das umhüllende Rect etwas verfälscht abgefragt, bei kleineren Radien fällt das aber kaum auf.
Wenn Du Dir die Regions ansehen willst, kannst Du Dich dort ![]() |
AW: Geschwindigkeit umkehren
Ich hab mir deinen Code jetzt nicht näher angeschaut, aber bei solchen Kollusionen gibt es i.d.R. folgende Punkte zu beachten.
1.) Der Timer läuft auf, weil er sehr schnell eingestellt ist. Das kann man leicht beheben, indem man am Anfang der OnTimerRoutine den Timer disabled und am Schluß der Routine wieder auf enabled setzt. 2.) Die Bälle, Kugeln ect. laufen ineinander. Das ist schon etwas schwieriger. Hier kann man mit einer function IsFreePlace(X, Y) prüfen, bevor man die Kugel an eine bestimmte Stelle setzt. 3.) Die Kollusion wird nicht erkannt, weil der Timer sehr schnell eingestellt ist und auch hier laufen die Kugeln manchmal ineinander. Da kann man zum Beispiel einen Zug im Voraus denken und mit diesen Koordinaten auf Kollusion prüfen (in meinem Code die NextBalls). 4.) Wenn dir der elastische Stoß mit Berücksichtigung der Massen zu kompliziert ist bzw. wenn alle Kugeln die gleiche Masse haben, kannst du die Geschwindigkeiten der beiden Kugeln einfach austauschen. 5.) Bei Kollusion mit einer Wand wird die entsprechende Geschwindigkeit umgedreht. Gruß Thomas PS.: Etwas einfacher zu handhaben als InterSectRect ist: ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:51 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