Autor Beitrag
YK18415
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 05.01.17 15:53 
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):
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
// grap all astroids
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:
ausblenden 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 != nullreturn (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 user profile iconTh69: C#-Tags hinzugefügt
YK18415 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 05.01.17 15:59 
Ach so,

die Auswertung habe ich in Form1.cs in meiner Methode, die alles zeichnet wie folgt geschrieben:
ausblenden 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 user profile iconTh69: C#-Tags hinzugefügt
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Do 05.01.17 16:00 
Zitat:
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 918
Erhaltene Danke: 158

Win 10
VS 2013, VS2015
BeitragVerfasst: Do 05.01.17 16:02 
Soweit logisch 8)

ausblenden 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(); 

  // 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
}


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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: 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...