Entwickler-Ecke
WinForms - Kollision von zwei Rechtecken
YK18415 - Do 05.01.17 15:53
Titel: Kollision von zwei Rechtecken
Hallo,
ich bin dabei ein Asteroids-Spiel zu entwickeln. Es klappt ganz gut (Raumschiff bewegen, schießen etc.), allerdings habe ich ein Problem bei der Kollisionsabfrage des Raumschiffes (Rechteck) mit einem Asteroiden (Kreis).
Ich zeichne alles auf einer pictureBox und speichere dabei die Asteroiden in einer Liste (s. Code):
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| List<GeometricObject> astroids = new List<GeometricObject>(); foreach (var item in listBox1.Items) { if (item is Asteroid) { astroids.Add((Asteroid)item); } } |
Diese Objekte in der Liste (Asteroiden) vergleiche ich mit dem Raumschiff mit Hilfe der Methode "CheckCollision".
In meiner Basisklasse (GeometricObject) habe ich eine Methode, die um alle gezeichnete Objekte (also um Kreis, Rechteck, Dreieck usw.) ein Rechteck zeichnet, um die Kollisionsabfrage fürs Erste einfacher zu gestalten. Die Kollisionsabfrage habe ich auch in meiner Basisklasse geschrieben.
Mein Code in der Basisklasse:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29:
| public virtual void Boundaries(Graphics g) { g.DrawRectangle(Pens.White, (float)X, (float)Y, (float)Width, (float)Height); } public Collision CheckCollison(List<GeometricObject> otherObjects) { foreach (var item in otherObjects) { var collison = CheckCollison(item); if (collison != null) return (collison); } return null; } public Collision CheckCollison(GeometricObject otherObject) { asteroid = new Asteroid(); rectangle = new Rectangle(); 1. if ((asteroid.X > rectangle.X && asteroid.X < rectangle.X + rectangle.Width) && (asteroid.Y > rectangle.Y && asteroid.Y < rectangle.Y + rectangle.Height)) { return new Collision() { Object1 = this, Object2 = otherObject }; } 2. if ((asteroid.x > this.X && asteroid.X < this.X + Width) && (asteroid.Y > this.Y && asteroid.Y < this.Y + Height)) { return new Collision() { Object1 = this, Object2 = otherObject }; } return null; } |
Wie man in der unteren
CheckCollision-Methode sieht, habe ich schon einiges ausprobiert.
Mein Problem:
In 1. werden die Werte der einzelnen Objekte irgendwie nicht erfasst, wodurch die Position von den Objekten (x und y) immer auf 0 stehen...
In 2. bekomme ich zwar mit "this.X" die Koordinaten des Rechteckes vom Raumschiff (klar, weil ich ja auch in dieser Klasse das umschließende Rechteck zeichne), aber bei "asteroid.X" und bei "asteroid.Y" steht immer noch 0...
Wie kann ich diesen Wert (also den Wert von dem oberen linken Punkt des Rechteckes, das den Asteroiden umschließt) bekommen?
Danke schon mal! :)
Moderiert von
Th69: C#-Tags hinzugefügt
YK18415 - Do 05.01.17 15:59
Ach so,
die Auswertung habe ich in Form1.cs in meiner Methode, die alles zeichnet wie folgt geschrieben:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| if (item is Spaceship) { var collison = ((Spaceship)item).CheckCollison(astroids); if (collison != null) { MessageBox.Show("Bum: " + collison.Object2.ToString()); } } |
Moderiert von
Th69: C#-Tags hinzugefügt
Ralf Jansen - Do 05.01.17 16:00
Zitat: |
C#-Quelltext 1: 2:
| asteroid = new Asteroid(); rectangle = new Rectangle(); | |
Du erzeugst einfach zwei neue Objekte, initialisierst die nicht, vergleichst die aber. Warum sollte da was vernünftiges rauskommen?
Th69 - Do 05.01.17 16:01
Du erstellst ja auch in der Zeile über 1. sowohl einen neuen Asteroiden als auch ein neues leeres Rechteck (alle Werte werden dabei auf 0 gesetzt), welche du dann vergleichst - dies macht wohl keinen Sinn. Überlege dir genau was du miteinander vergleichen willst.
PS: Und bitte füge selbständig die C#-Tags hinzu...
jfheins - Do 05.01.17 16:02
Soweit logisch 8)
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| public Collision CheckCollison(GeometricObject otherObject) { asteroid = new Asteroid(); rectangle = new Rectangle();
if ((asteroid.X > rectangle.X && asteroid.X < rectangle.X + rectangle.Width) && (asteroid.Y > rectangle.Y && asteroid.Y < rectangle.Y + rectangle.Height)) { return new Collision() { Object1 = this, Object2 = otherObject }; } if ((asteroid.x > this.X && asteroid.X < this.X + Width) && (asteroid.Y > this.Y && asteroid.Y < this.Y + Height)) { return new Collision() { Object1 = this, Object2 = otherObject }; } return null; } |
Bei 1 vergleichst du ja asteroid mit rectangle, die du beide erst direkt darüber erzeugt hast.
Bei 2 vergleichst du
this mit asteroid.
this hat dann wohl schon von 0 verschiedene Werte, aber die Variable asteroid wird ja immer noch direkt oberhalb erzeugt und initialisiert.
In keiner Variante benutzt du den Parameter otherObject.
YK18415 - Do 05.01.17 16:11
Naja, initialisiert habe ich die schon, allerdings direkt am Anfang der Basisklasse mit "Rectangle rectangle;" und mit "Asteroid asteroid;".
Ja stimmt @jfheins :D :roll:
Wenn ich diesen Parameter benutze, dann klappt es auch.
Vielen Dank für eure Zeitinvestition! :D
PS: Man merkt ich bin ein Anfänger...
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!