C# XNA - Pong Kollisionsabfrage

locomarco

Commander
Registriert
Aug. 2009
Beiträge
2.446
Ich habe folgenden Code um den Ball am Schläger abprallen zu lassen:

Code:
public void BallCollisionUpdate()
        {
            Rectangle RectSchlaeger1, RectSchlaeger2, RectBall;

            RectSchlaeger1 = new Rectangle(Schlaeger1X, Schlaeger1Y, Schlaeger1.Width, Schlaeger1.Height);
            RectSchlaeger2 = new Rectangle(Schlaeger2X, Schlaeger2Y, Schlaeger2.Width, Schlaeger2.Height);
            RectBall = new Rectangle(BallX, BallY, Ball.Width, Ball.Height);
            
            
            if (RectBall.Left <= RectSchlaeger1.Right && BallY + Ball.Height / 2 >= RectSchlaeger1.Top && BallY + Ball.Height / 2 <= RectSchlaeger1.Bottom ||
                RectBall.Right >= RectSchlaeger2.Left && BallY + Ball.Height / 2 >= RectSchlaeger2.Top && BallY + Ball.Height / 2 <= RectSchlaeger2.Bottom)
            {
                BallSpeedX *= -1;
                BallSpeedY *= -1;
            }


            if (RectBall.Top <= 0 || RectBall.Bottom >= Height)
                BallSpeedY *= -1;
            
            if (RectBall.Left <= 0 || RectBall.Right >= Width)
                BallSpeedX *= -1;
        }

Das Problem ist das der Ball nicht immer abprallt.

Ball prallt rechts nicht ab -> prallt Links ab -> prallt rechts nicht ab -> prallt links nicht ab -> prallt rechts ab -> prallt links nicht ab -> prallt rechts nicht ab -> prallt links wieder ab und immer so weiter.


Vielleicht findet ja jemand den Fehler und hilft mir :)
Falls ihr den restlichen Code braucht, werd ich ihn Posten.


Grüße loco



EDIT: Habs selbst rausgefunden.
Hatte für die Controllersteuerung nicht int Schlaeger1Y sondern float Y1 benutzt und in dem Abschnitt nicht geändert.
 
Zuletzt bearbeitet:
Warum sollte man für einen Pixel auf einem Rasterdisplay float benutzen?
 
Weil GamePad.GetState(PlayerIndex.One).ThumbSticks.Left von -1 bis 1 geht und ich nicht weiter drüber nachgedacht habe?
 
Beim Programmieren nicht weiter nachdenken halte ich nicht für zielführend.
Solltest du in Zukunft anpassen.
 
Die Kollisionsabfrage musst du eh noch stark bearbeiten...

Bei einer Kollision kommt es sehr selten vor, dass der Ball exakt in die Richtung zurückfliegt, aus der er kommt... normal ändert sich lediglich die Geschwindigkeit in eine Richtung (also normalerweise muss man Einfallswinkel = Ausfallswinkel, aber hier ist das Winkelrechnen in dem Maße nicht nötig...)
 
asdfman schrieb:
Beim Programmieren nicht weiter nachdenken halte ich nicht für zielführend.
Solltest du in Zukunft anpassen.
Das mach ich normalerweise auch, war nur für einen ersten Test.

1668mib schrieb:
Bei einer Kollision kommt es sehr selten vor, dass der Ball exakt in die Richtung zurückfliegt, aus der er kommt... normal ändert sich lediglich die Geschwindigkeit in eine Richtung
Das ist mir vorhin auch aufgefallen, habs mittlerweile geändert :D
 
Scheinst ja nicht sonderlich viel Ahnung davon zu haben, wie wäre es mit ein par Tutorials?

Rectangle hat zum Beispiel eine Intersects(Rectangle)-Methode, mit der du dir die Boundsabfrage sparen kannst.
Und dann heißt es nur: Einfallswinkel=Ausfallswinkel

btw ich würde die Rechtecke nicht immer in der Methode neu deklarieren.

Wenn du unbedingt mit Nachkommastellengenauigkeit bewegen, evtl. sogar beschleunigen willst, solltest du für Ball und Schläger jeweils eine eigene Position als Vector2 haben. Solltest dann aber auch noch dt benutzen um dann auch genau zu bleiben bei der Positionsberechnung.
In der Kollisionsabfrage am Anfang der Methode die Positionen aus den Vectoren in die Rectangles casten.

Das Ganze kann man dann noch dementsprechend erweitern und optimieren.

Das wäre zumindest die beste Lösung.

EDIT:
Dazu fällt mir noch ein, dass du ja schief spielen solltest. So wie es scheint, hast du darüber noch gar nicht nachgedacht?
 
Zuletzt bearbeitet:
Wenn du unbedingt mit Nachkommastellengenauigkeit bewegen, evtl. sogar beschleunigen willst
Braucht man nicht. Es gibt Algorithmen, die das können und trotzdem nur mit diskreten Werten arbeiten.
Man nehme z.B. Bresenham's Line Algorithm und behält für die Änderung der Position Geschwindigkeit
und Beschleunigung "im Hinterkopf".
 
Die Benutzung des Vector2s hat den Vorteil, dass dieser bei dem Zeichnen der Textur anstelle des Rectangles übergeben werden kann.
Mir ist aufgefallen, dass dabei dann die Ränder entsprechend bearbeitet werden, wodurch
die Bewegung flüssiger erscheint. Bei der Übergabe eines Rectangles als Parameter "springt" die Textur jedoch von einem Pixel zum nächsten.
 
Dr. Greg House schrieb:
Scheinst ja nicht sonderlich viel Ahnung davon zu haben, wie wäre es mit ein par Tutorials?
Da hast du recht, ich hab nicht allzuviel Ahnung. Und normalerweise schau ich mir Tutorials an, wenn ich nicht weiß wie etwas funktioniert. Hier habe ich noch nicht viel gebraucht.

Rectangle hat zum Beispiel eine Intersects(Rectangle)-Methode, mit der du dir die Boundsabfrage sparen kannst.
Die hatte ich benutzt, hat vermutlich wegen dem Fehler oben nicht funktioniert.

Wenn du unbedingt mit Nachkommastellengenauigkeit bewegen, evtl. sogar beschleunigen willst, solltest du für Ball und Schläger jeweils eine eigene Position als Vector2 haben. Solltest dann aber auch noch dt benutzen um dann auch genau zu bleiben bei der Positionsberechnung.
In der Kollisionsabfrage am Anfang der Methode die Positionen aus den Vectoren in die Rectangles casten.
Ich hab zwar die Positionen als Vector2, aber ich weiß nicht was du mir da rätst, ich bin ein blutiger Anfänger :D


EDIT:
Dazu fällt mir noch ein, dass du ja schief spielen solltest. So wie es scheint, hast du darüber noch gar nicht nachgedacht?
Was meinst du mit schief? Falls du den Ball meinst, der bewegt sich diagonal in richtung einer Ecke.
 
Irgendwie muss der Ball doch ´ne Richtungsänderung bekommen. Sonst macht er immer nur ein und dieselbe Hin- und Herbewegung
 

Ähnliche Themen

Zurück
Oben