Ich versuche mein Hauptaugenmerk auf dieses Hallo-Welt-Problem in der Spieleentwicklung zu legen. Ich habe ein TicTacToe-Spiel in XNA erstellt, also würde der nächste Schritt wohl ein Breakout- Klon sein.
Denken Sie daran, dass ich keine Kenntnisse über Spieleprogrammierung habe oder auch nicht, auf welche Mathematik ich wo anwenden sollte. Deshalb stelle ich diese Frage.
Zur Frage: Wie kann ich bestimmen, wo der Ball springen soll, wenn er auf das Paddel am unteren Bildschirmrand trifft?
Ich würde mir vorstellen, dass es so etwas wie:
- Erfassen Sie die Geschwindigkeit und den Winkel des ankommenden Balls.
- Erkennen Sie, wo es den Balken berührt hat (ganz links, ganz rechts, in der Mitte) und geben Sie ihm dementsprechend eine höhere Geschwindigkeit, wenn es die äußeren Bereiche berührt.
- Hier stecke ich fest. Hehe
Irgendwelche Einsichten? Mir ist klar, dass dies keine einfache Frage ist, aber ich bin sicher, es ist eine, der sich irgendwann jeder stellen muss.
Ich lese das Buch Lineare Algebra , das auf dieser Website empfohlen wurde, aber ich habe noch keine Ahnung, ob ich es hier anwenden soll.
Antworten:
Hier ist die relevante Logik, die ich für das Pong auf meiner Homepage verwendet habe : (Bitte spiele sie vor dem Lesen, damit du weißt, welchen Effekt ich mit dem folgenden Code erreiche.)
Wenn der Ball mit dem Paddel kollidiert, wird seine Richtung im Wesentlichen völlig ignoriert. Es erhält eine neue Richtung, je nachdem, wie weit von der Mitte des Paddels entfernt es kollidiert ist. Wenn der Ball genau in der Mitte auf das Paddel trifft, wird er genau horizontal weggeschickt. Wenn es direkt auf die Kante trifft, fliegt es in einem extremen Winkel (75 Grad) davon. Und es fährt immer mit konstanter Geschwindigkeit.
Nehmen Sie den mittleren Y-Wert des Paddels und subtrahieren Sie den Y-Schnittpunkt des Balls. Wenn das Paddel 10 Pixel hoch ist, liegt diese Zahl zwischen -5 und 5. Ich nenne dies den "relativen Schnitt", da es sich jetzt im "Paddelraum" befindet, dem Schnittpunkt des Balls relativ zur Mitte des Paddels.
Nehmen Sie den relativen Schnittpunkt und teilen Sie ihn durch die halbe Paddelhöhe. Jetzt ist unsere Zahl von -5 bis 5 eine Dezimalzahl von -1 bis 1; es ist normalisiert . Dann multiplizieren Sie es mit dem maximalen Winkel, um den der Ball springen soll. Ich habe es auf 5 * Pi / 12 Radiant (75 Grad) eingestellt.
Berechnen Sie abschließend mit Hilfe der einfachen Trigonometrie neue Kugelgeschwindigkeiten.
Dies ist möglicherweise nicht der Effekt, den Sie anstreben, oder Sie möchten möglicherweise auch eine Geschwindigkeit ermitteln, indem Sie den normalisierten relativen Schnittpunkt mit einer maximalen Geschwindigkeit multiplizieren. Dies würde den Ball schneller machen, wenn er in der Nähe der Kante eines Paddels schlägt, oder langsamer, wenn er in der Nähe der Mitte schlägt.
Ein Vektor enthält implizit sowohl Geschwindigkeit als auch Richtung. Ich speichere meinen Vektor als "vx" und "vy"; das heißt, die Geschwindigkeit in der x-Richtung und die Geschwindigkeit in der y-Richtung. Wenn Sie keinen Einführungskurs in Physik belegt haben, scheint Ihnen das etwas fremd zu sein.
Der Grund, warum ich das tue, ist, dass es die erforderlichen Einzelbildberechnungen reduziert. Jedes Bild, das Sie gerade machen,
x += vx * time;
undy += vy * time;
wo die Zeit die Zeit seit dem letzten Bild ist, in Millisekunden (daher sind die Geschwindigkeiten in Pixel pro Millisekunde).In Bezug auf die Implementierung der Fähigkeit, den Ball zu krümmen:
Zunächst müssen Sie die Geschwindigkeit des Paddels zum Zeitpunkt des Ballschlags kennen. Dies bedeutet, dass Sie den Verlauf des Paddels nachverfolgen müssen, damit Sie eine oder mehrere frühere Positionen des Paddels kennen und mit der aktuellen Position vergleichen können, um festzustellen, ob es sich bewegt hat. (Änderung der Position / Änderung der Zeit = Geschwindigkeit; Sie benötigen also 2 oder mehr Positionen und die Zeiten dieser Positionen)
Sie müssen jetzt auch eine Winkelgeschwindigkeit des Balls verfolgen , die praktisch die Kurve darstellt, entlang der er sich bewegt , aber dem tatsächlichen Spin des Balls entspricht. Ähnlich wie Sie den Sprungwinkel aus der relativen Position des Balls bei Kollision mit dem Paddel interpolieren würden, müssten Sie auch diese Winkelgeschwindigkeit (oder Drehung) aus der Geschwindigkeit des Paddels bei Kollision interpolieren. Anstatt die Drehung einfach so einzustellen, wie Sie es mit dem Abprallwinkel tun, möchten Sie möglicherweise die vorhandene Drehung des Balls addieren oder subtrahieren, da dies in Spielen gut funktioniert (der Spieler kann feststellen, dass sich der Ball dreht, und veranlassen, dass er sich dreht noch wilder, oder kontern Sie die Drehung in einem Versuch, es geradeaus zu bewegen).
Beachten Sie jedoch, dass dies zwar der gängigste und wahrscheinlich einfachste Weg ist, die tatsächliche Physik eines Sprunges jedoch nicht nur von der Geschwindigkeit des Objekts abhängt, auf das er auftrifft. Einem Objekt ohne Winkelgeschwindigkeit (kein Spin), das unter einem Winkel auf eine Oberfläche trifft, wird ein Spin verliehen. Dies könnte zu einer besseren Spielmechanik führen, daher möchten Sie vielleicht einen Blick darauf werfen, aber ich bin nicht sicher, welche Physik dahinter steckt, also werde ich nicht versuchen, es zu erklären.
quelle
Es ist schon eine Weile her, seit ich das getan habe, aber ich denke, ich habe das richtig verstanden.
Bei einer perfekten Kollision ist der Reflexionswinkel gleich dem Einfallswinkel.
Sie kennen die Normalen Ihres Paddels (unter der Annahme einer flachen Oberfläche): N Sie kennen Ihre ursprüngliche Position Ihres Balls (am Anfang Ihres Zeitschritts): P Sie kennen Ihre neue Position des Balls (am Ende des Zeitschritts): P 'Sie kennen Ihren Kollisionspunkt: C Angenommen, Sie haben berechnet, dass das Segment P -> P' durch Ihr Paddel verläuft, wäre Ihre neu reflektierte Position (P ''):
P '+ 2 * (N * (P' Punkt -N))
Der Unterausdruck N * (P 'Punkt-N) berechnet die Tiefe entlang der Kollisionsnormalen, die der Ball zurückgelegt hat. Das Minuszeichen korrigiert die Tatsache, dass die Tiefe entgegen der Normalenrichtung geprüft wird.
Das P '+ 2 * der Teil des Teilausdrucks bewegt den Ball um das Zweifache der Kollisionstiefe über die Kollisionsebene zurück.
Wenn Sie eine weniger als perfekte Kollision wünschen, ändern Sie den Faktor 2 auf (1 + (1-k)), wobei k Ihr Reibungskoeffizient ist. Eine perfekte Kollision hat einen k-Wert von 0, wodurch der Reflexionswinkel genau dem eingehenden Winkel entspricht. Ein k-Wert von 1 verursacht eine Kollision, bei der der Ball auf der Oberfläche der Kollisionsebene verbleibt.
Ihr neuer Geschwindigkeitsvektor, V '', wäre P '' - C. Normalisieren Sie ihn und multiplizieren Sie ihn mit Ihrer ankommenden Geschwindigkeit, und Ihre resultierende Geschwindigkeitsgröße wäre dieselbe, jedoch in der neuen Richtung. Sie können mit dieser Geschwindigkeit affen, indem Sie sie mit einem Koeffizienten multiplizieren, der entweder die resultierende Geschwindigkeit erhöht (l> 1) oder verringert (l <1).
Zusammenfassen:
P '' = P '+ (1 - k) * (N * (P Punkt - N)) V' '= 1 * V * ((P' '- C) / | P' '- C |)
Wobei k und l Koeffizienten Ihrer Wahl sind.
quelle
Die Reflexion kann entweder "richtig" oder "einfach" erfolgen.
Der "richtige" Weg besteht darin, Vektoren senkrecht zu den Wänden zu berechnen. In 2D ist das ziemlich einfach und man könnte sie wahrscheinlich nur hart codieren. Dann lässt der Reflexionsschritt im Wesentlichen die "parallele" Komponente der Bewegung intakt und kehrt die "senkrechte" Komponente um. Es gibt wahrscheinlich detaillierte Informationen im Web, vielleicht sogar bei MathWorld.
Die "einfache" Möglichkeit besteht darin, die X- oder Y-Bewegung einfach zu negieren, wenn Sie gegen eine Wand stoßen. Wenn Sie die Seitenwände treffen, negieren Sie X. Wenn Sie die Oberseite treffen, negieren Sie Y. Wenn Sie den Ball beschleunigen möchten, erhöhen Sie einfach, was Sie wollen; Sie können es in der aktuellen Richtung beschleunigen, indem Sie die X- und Y-Geschwindigkeit multiplizieren, oder Sie können nur auf einer Achse beschleunigen.
quelle
Ich mache auch selbst ein Arkanoid-Spiel und ich denke, die Lösung, wie sich der Ball beim Schlagen des Paddels verhalten soll, ist einfacher und schneller als der Einstieg in den Sin / Cos-Ansatz Spiel wie dieses. Folgendes mache ich:
Natürlich interpoliere ich, da die Ballgeschwindigkeit mit der Zeit zunimmt, die vorher / nachher x, y-Schritte, um eine genaue Kollisionserfassung aufrechtzuerhalten, wobei alle "stepX" und "stepY" durchlaufen werden, die berechnet werden, indem jede Geschwindigkeitskomponente durch den Modul des gebildeten Vektors geteilt wird durch die aktuellen und zukünftigen Ballpositionen.
Wenn eine Kollision mit dem Paddel auftritt, dividiere ich die Y-Geschwindigkeit durch 20. Diese "20" ist der bequemste Wert, den ich gefunden habe, um meinen resultierenden maximalen Winkel zu erhalten, wenn der Ball auf die Seiten des Paddels schlägt, aber Sie können ihn in einen beliebigen Wert ändern Ihre Bedürfnisse sind, spielen Sie einfach mit einigen Werten und wählen Sie das Bessere für Sie. Nehmen wir an, wir teilen die Geschwindigkeit durch 5, was meine anfängliche Spielgeschwindigkeit durch diese Zahl (20) ist. Dadurch erhalte ich einen "Rückprallfaktor" von 0,25. Diese Berechnung hält meine Winkel ziemlich proportional, wenn die Geschwindigkeit mit der Zeit bis zu meinem maximalen Geschwindigkeitswert ansteigt, der beispielsweise 15 betragen könnte (in diesem Fall: 15/20 = 0,75). In Anbetracht der Tatsache, dass meine Paddel-Koordinaten x, y in der Mitte liegen (x und y stellen die Mitte des Paddels dar), multipliziere ich dieses Ergebnis mit der Differenz zwischen der Ballposition und der Paddelposition. Je größer der Unterschied, das große Jahr der resultierende Winkel. Außerdem erhalten Sie mit einem mittelharten Schläger das richtige Vorzeichen für das x-Inkrement, abhängig von der Seite, auf die der Ball schlägt, ohne sich um die Berechnung des Mittelpunkts kümmern zu müssen. Im Pseudocode:
Für n = 0 zum Modul ...
wenn collision_detected dann ist speedX = - (speedY / 20) * (paddleX - ballX); speedY = -speedY;
Ausfahrt; ende wenn
...
x = x + stepX; y = y + stepY;
Ende für
Denken Sie daran, immer zu versuchen, die Dinge einfach zu halten. Ich hoffe, es hilft!
quelle
Das Paddel in Breakout wird in der Regel als gekrümmte Oberfläche modelliert, wenn es dem von Ihnen beschriebenen Stil folgt. Der Einfallswinkel ändert sich abhängig von der Position des Paddels, auf das er trifft. Im Totpunkt ist die Tangente zur Kurve absolut horizontal und der Ball reflektiert wie erwartet. Wenn Sie sich von der Mitte wegbewegen, wird die Tangente zur Kurve zunehmend abgewinkelt und der Ball wird dadurch anders reflektiert.
Entscheidend ist, dass sich der Reflexionswinkel und nicht die Ballgeschwindigkeit ändert. Die Ballgeschwindigkeit steigt im Allgemeinen mit der Zeit nur langsam an.
quelle
angle = 1 - 2 * (ball.x - paddle.left) / paddle.width
gibt Ihnen eine Zahl zwischen 1 und -1; Dies (mal ein für Ihre Spielmechanik optimierter Wert) ist die Steigung der Tangentenlinie an dem Punkt, an dem der Ball kollidierte. Reflektiere eher von dieser Linie als von der streng horizontalen.Nolan Bushnell hielt am vergangenen Wochenende eine Keynote bei SIEGE und sprach über ein ähnliches Problem mit dem Original-Pong. Sie müssen nicht viele komplizierte Berechnungen durchführen. Wenn Sie in Richtung des linken Teils des Feldes schlagen, senden Sie den Ball nach links. Machen Sie dasselbe für die rechte Seite.
Zunächst können Sie den Winkel für die linke und rechte Seite auf 45 Grad einstellen. Sobald Sie das Spiel beendet haben, können Sie, wenn Sie möchten, zurückgehen und dies komplizierter machen, aber machen Sie dies zunächst so einfach wie möglich.
quelle
Breakout ist eine klassische Anfängerarbeit, um in die Welt der physikbasierten Spielprogrammierung einzutauchen. Grundsätzlich hat der Ball eine Sprungbewegung, wenn er gegen die Wand schlägt. Wie oben angedeutet, ist der Einfallswinkel gleich dem Reflexionswinkel. Aber wenn Sie den Ball betrachten, der das Paddel schlägt. Die Logik ist in 3 Abschnitte unterteilt. 1.) Der Ball trifft auf den Mittelteil des Paddels. 2.) Der Ball trifft den linken Teil des Paddels. 3.) Der Ball trifft die rechte Position des Paddels.
Wenn Sie den Mittelteil betrachten: Sie müssen den Abpralleffekt nicht von dem unterscheiden, der beim Schlagen des Balls angewendet wird. Der Ball wird einfach normal abgelenkt. Wenn jedoch eine Richtung getroffen wird, ist der Fall anders.
Wenn der Ball auf der linken Seite getroffen wird, betrachten Sie den Ball also von der linken Seite des Bildschirms und Sie kommen mit dem Paddel von der rechten Seite. Wenn Sie dann den Ball mit dem linken Teil treffen, sollte der Ball in die Richtung reflektieren, aus der er kam. Gleiches gilt umgekehrt. Im rechten Teil gilt auch das Gleiche.
Diese Bewegung des Balls nach links oder rechts beim Schlagen macht ihn glaubwürdiger.
Hoffe, Sie haben die Idee, zumindest logisch. Vielen Dank
quelle
Stellen Sie sich vor, Sie berechnen den Abstand zwischen der Mitte des Paddels und dem Punkt, an dem der Ball Y aufschlägt, und nennen ihn
d
. Nehmen wir an,d
der Wert ist positiv, wenn der Ball über der Mitte des Paddels aufschlägt. Sie können nund * -0.1
die Y-Geschwindigkeit Ihres Balls erhöhen und die Richtung ändern. Hier ist ein Beispiel in Javascript, das leicht in c # übersetzt werden kann!quelle
Dies wird dazu beitragen , http://www-classes.usc.edu/engr/ee-s/477p/s00/pong.html Sie einfach Invertzucker x und y je nachdem , wo es auf den Bildschirm trifft. Wenn es nach oben geht und oben anschlägt, wird die y-Geschwindigkeit invertiert, während die x-Geschwindigkeit beibehalten wird
quelle
Hallo, ich habe kürzlich versucht, ein Ballspiel zu machen und eine Lösung dafür gefunden. Also, was ich getan habe: Das Paddel bewegt sich, während wir das Spiel spielen. Mein Koordinatensystem bleibt wie es ist, der obere linke Punkt der Zeichenfläche ist 0,0. Das Paddel bewegt sich in diesem Koordinatensystem. Die x-Achse zeigt von 0 bis zur Leinwandbreite, und die y-Achse zeigt auf 0 bis zur Leinwandhöhe. Ich habe ein Paddel mit fixer Größe 100 Breite und 20 Höhe erstellt. Und dann zeichne ich einen imaginären Kreis darum. Wenn der Ball das Paddel trifft, berechne ich den Mittelpunkt des Paddels
Dann subtrahiere ich die Mitte von der aktuellen Position des Balls, so dass sich das Koordinatensystem in der Mitte des Paddels befindet. BallCenter ist der Punkt, an dem der Ball auf das Paddel auftrifft (- (Paddelbreite + r) .. 0 .. (Paddelbreite + r) )) Dies ist nichts anderes als die Neuskalierung des Schlagpunktes auf dem Paddel
Berechnen Sie den Schnittpunkt des Kreises mit Hilfe des Schlagpunktes des Balls (x0). Dies ist eine Neuberechnung. Wir fragen nach der y-Koordinate auf dem Kreis mit der bereits bekannten x0-Koordinate und es wurde ein Flip für die y-Achse benötigt
Berechnen Sie das Derivat der Normalgleichung des Kreises, der um das Paddel definiert ist, mit radis paddleRadius f (x, y) = x ^ 2 + y ^ 2-r ^ 2
normalisiere den N-Vektor, um einen Einheitsvektor für die Oberflächennormale zu erhalten
Jetzt haben wir die normalisierten (Einheits-) Flächennormalen für das Paddel. Berechnen Sie die neue Richtung mit diesen Flächennormalen. Dies wird mit Hilfe der Reflexionsvektorformel berechnet: new_direction = old_direction-2 * dot (N, old_direction) * N, aber stattdessen mit der Flächennormalen, die immer nach oben zeigt, wird die Normale berechnet wechselt von Punkt zu Punkt, an dem der Ball auf das Paddel trifft
Ich habe meine Lösung für dieses Problem veröffentlicht. Für mehr Details und für das komplette Spiel siehst du mein Github-Repository:
https://github.com/zoli333/BricksGame
geschrieben in Java mit Eclipse. Es gibt eine andere Lösung für dieses Problem, die in Ball.java auskommentiert wurde. Dort, wo die Neuskalierung nicht erfolgt, verschiebe ich das Koordinatensystem nicht zum Mittelpunkt des Paddels, sondern berechne alle oben genannten Werte aus dem oberen linken 0,0-Koordinatensystem relativ zu der Mittelpunkt des Paddels. Das funktioniert auch.
quelle