Kollisionsabfrage zwischen Klassen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
k-net
User
Beiträge: 24
Registriert: Donnerstag 22. Oktober 2020, 16:43

Hallo,
ich habe eine grundlegende Frage, ob ich zwischen unterschiedlichen Klassen z. B. Kollisionsabfragen durchführen kann.

Mal angenommen ich habe zwei Objekte die sich aufeinander zubewegen, wie in folgendem Code:

Code: Alles auswählen

#Module importieren
import pygame
import sys
import random

#Fenster
pygame.init()
screen = pygame.display.set_mode([1200, 700])
pygame.display.set_caption("Objekte")
clock = pygame.time.Clock()

#Klassen
class Objekte_rechts():
    def __init__(self):
        self.pos_x_r = 1178
        self.pos_y_r = random.randint(54, 678)
        self.breite_r = 20
        self.hoehe_r = 20
        self.color_r = (255, 255, 255)
        self.speed_r = 10
    def zeichnen(self):
        objekt_rechts = pygame.draw.rect(screen, (self.color_r), (self.pos_x_r, self.pos_y_r, self.breite_r, self.hoehe_r), self.speed_r)
        if self.pos_x_r <= 1178:
            self.pos_x_r = self.pos_x_r - self.speed_r
        if self.pos_x_r <= 2:
            self.pos_x_r = 1178
            self.pos_y_r = random.randint(54, 678)

class Objekte_links():
    def __init__(self):
        self.pos_x_l = 2
        self.pos_y_l = random.randint(54, 678)
        self.breite_l = 20
        self.hoehe_l = 20
        self.color_l = (255, 255, 255)
        self.speed_l = 10
    def zeichnen(self):
        objekt_links = pygame.draw.rect(screen, (self.color_l), (self.pos_x_l, self.pos_y_l, self.breite_l, self.hoehe_l), self.speed_l)
        if self.pos_x_l >= 2:
            self.pos_x_l = self.pos_x_l + self.speed_l
        if self.pos_x_l >= 1178:
            self.pos_x_l = 2
            self.pos_y_l = random.randint(54, 678)

objekt_von_rechts = Objekte_rechts()
objekt_von_links = Objekte_links()

#Loop
go = True
while go:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

    screen.fill((0, 0, 0))

    objekt_von_rechts.zeichnen()
    objekt_von_links.zeichnen()

    pygame.display.update()
    clock.tick(60)

Früher oder später werden die sich ja treffen und dann möchte ich ein Event auslösen. Ich weiß dass ich eine einzige Klasse mit dem Titel "Objekte" erstellen könnte und dann eine Abfrage wie z. B.

Code: Alles auswählen

if objekt_rechts.colliderect(objekt_links):
            pygame.time.delay(700)
            sys.exit()
verwenden könnte. Aber das möchte ich nicht. Wie also führe ich die Kollisionsabfrage zwischen zwei Objekten unterschiedlicher Klassen durch?

Vielen Dank!
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

`Objekte` ist für EIN Rechteck ein komischer Name. Es macht hier keinen Sinn, zwei Klassen zu haben, da mußt Du schon ganz genau erklären, warum Du das nicht möchtest.
Und warum Du deshalb nicht colliderect benutzen kannst, verstehe ich nicht.
k-net
User
Beiträge: 24
Registriert: Donnerstag 22. Oktober 2020, 16:43

Der vollständige Code sieht aktuell so aus:

Code: Alles auswählen

#Module importieren
import pygame
import sys
import random

#Fenster
pygame.init()
screen = pygame.display.set_mode([1200, 700])
pygame.display.set_caption("Don't touch!")
hintergrund = pygame.image.load("graphic/bg_space.png")
clock = pygame.time.Clock()

#Farben
black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
yellow = (255, 255, 0)
purple = (255, 0, 255)
teal = (0, 255, 255)

#Variablen und Listen
colors = [red, green, blue, yellow, purple, teal]

#Grenzen
rand_oben = pygame.draw.rect(screen, (white), (0,0,1200,2),2)
rand_rechts = pygame.draw.rect(screen, (white), (1198,0,2,700), 2)
rand_unten = pygame.draw.rect(screen, (white), (0,698,1200,2), 2)
rand_links = pygame.draw.rect(screen, (white), (0,0,2,698), 2)
trennlinie = pygame.draw.rect(screen, (white), (0,50,1200,2),2)

#Fensterstruktur
def fenster():
    screen.blit(hintergrund, (0, 50))
    pygame.draw.rect(screen, (white), (0, 0, 1200, 2), 2)
    pygame.draw.rect(screen, (white), (1198, 0, 2, 700), 2)
    pygame.draw.rect(screen, (white), (0, 698, 1200, 2), 2)
    pygame.draw.rect(screen, (white), (0, 0, 2, 698), 2)
    pygame.draw.rect(screen, (white), (0, 50, 1200, 2), 2)

#Klassen
class Objekte():
    def __init__(self):
        self.pos_x_sp = 590
        self.pos_y_sp = 313
        self.breite_sp = 25
        self.hoehe_sp = 25
        self.color_sp = (white)
        self.speed_sp = 6
        self.pos_x_u = random.randint(2, 1178)
        self.pos_y_u = 678
        self.breite_u = 20
        self.hoehe_u = 20
        self.color_u = colors[random.randint(0, len(colors) - 1)]
        self.speed_u = random.randint(2, 10)
        self.pos_x_l = 2
        self.pos_y_l = random.randint(54, 678)
        self.breite_l = 20
        self.hoehe_l = 20
        self.color_l = colors[random.randint(0, len(colors) - 1)]
        self.speed_l = random.randint(2, 10)
        self.pos_x_o = random.randint(2, 1178)
        self.pos_y_o = 54
        self.breite_o = 20
        self.hoehe_o = 20
        self.color_o = colors[random.randint(0, len(colors) - 1)]
        self.speed_o = random.randint(2, 10)
        self.pos_x_r = 1178
        self.pos_y_r = random.randint(54, 678)
        self.breite_r = 20
        self.hoehe_r = 20
        self.color_r = colors[random.randint(0, len(colors) - 1)]
        self.speed_r = random.randint(2, 10)

    def zeichnen(self):
        game_quadrat = pygame.draw.rect(screen, (self.color_sp), (self.pos_x_sp, self.pos_y_sp, self.breite_sp, self.hoehe_sp), self.speed_sp)
        pressed = pygame.key.get_pressed()
        if pressed[pygame.K_UP] and not game_quadrat.colliderect(trennlinie):
            self.pos_y_sp -= self.speed_sp
        if pressed[pygame.K_RIGHT] and not game_quadrat.colliderect(rand_rechts):
            self.pos_x_sp += self.speed_sp
        if pressed[pygame.K_DOWN] and not game_quadrat.colliderect(rand_unten):
            self.pos_y_sp += self.speed_sp
        if pressed[pygame.K_LEFT] and not game_quadrat.colliderect(rand_links):
            self.pos_x_sp -= self.speed_sp

        objekte_unten = pygame.draw.rect(screen, (self.color_u), (self.pos_x_u, self.pos_y_u, self.breite_u, self.hoehe_u), self.speed_u)
        if self.pos_y_u <= 678:
            self.pos_y_u = self.pos_y_u - self.speed_u
        if self.pos_y_u <= 54:
            self.pos_y_u = 678
            self.pos_x_u = random.randint(0, 1178)
            self.speed_u = random.randint(2, 10)
            self.color_u = colors[random.randint(0, len(colors) - 1)]
        if objekte_unten.colliderect(game_quadrat):
            pygame.time.delay(700)
            sys.exit()

        objekte_links = pygame.draw.rect(screen, (self.color_l), (self.pos_x_l, self.pos_y_l, self.breite_l, self.hoehe_l), self.speed_l)
        if self.pos_x_l >= 2:
            self.pos_x_l = self.pos_x_l + self.speed_l
        if self.pos_x_l >= 1178:
            self.pos_x_l = 2
            self.pos_y_l = random.randint(54, 678)
            self.speed_l = random.randint(2, 10)
            self.color_l = colors[random.randint(0, len(colors) - 1)]
        if objekte_links.colliderect(game_quadrat):
            pygame.time.delay(700)
            sys.exit()

        objekte_oben = pygame.draw.rect(screen, (self.color_o), (self.pos_x_o, self.pos_y_o, self.breite_o, self.hoehe_o), self.speed_o)
        if self.pos_y_o >= 54:
            self.pos_y_o = self.pos_y_o + self.speed_o
        if self.pos_y_o >= 678:
            self.pos_y_o = 54
            self.pos_x_o = random.randint(2, 1178)
            self.speed_o = random.randint(2, 10)
            self.color_o = colors[random.randint(0, len(colors) - 1)]
        if objekte_oben.colliderect(game_quadrat):
            pygame.time.delay(700)
            sys.exit()

        objekte_rechts = pygame.draw.rect(screen, (self.color_r), (self.pos_x_r, self.pos_y_r, self.breite_r, self.hoehe_r), self.speed_r)
        if self.pos_x_r <= 1178:
            self.pos_x_r = self.pos_x_r - self.speed_r
        if self.pos_x_r <= 2:
            self.pos_x_r = 1178
            self.pos_y_r = random.randint(54, 678)
            self.speed_r = random.randint(2, 10)
            self.color_r = colors[random.randint(0, len(colors) - 1)]
        if objekte_rechts.colliderect(game_quadrat):
            pygame.time.delay(700)
            sys.exit()

spieler = Objekte()
leben = Objekte()
quadrat_unten1 = Objekte()
quadrat_links1 = Objekte()
quadrat_oben1 = Objekte()
quadrat_rechts1 = Objekte()

#Loop
go = True
while go:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

    fenster()

    spieler.zeichnen()
    quadrat_unten1.zeichnen()
    quadrat_links1.zeichnen()
    quadrat_oben1.zeichnen()
    quadrat_rechts1.zeichnen()

    pygame.display.update()
    clock.tick(60)

Wenn das weiße Quadrat in der Mitte (der Spieler) von einem der anderen berührt wird, dann wird das Fenster geschlossen. Ich möchte aber eigentlich, dass in dem Fall der Loop unterbrochen wird, und gefragt wird, ob man das Spiel beenden möchte oder nochmal starten möchte. Aber ich bekomme es nicht hin, aus der Klasse heraus so in den Loop einzugreifen. Werte die ich in der Klasse definiere, kann ich so im Loop nicht verwenden und Werte außerhalb der Klasse, die ich im Loop verwenden kann, kennt die Klasse nicht. Daher hatte ich auf eine Möglichkeit gehofft, in die Klassen quasi von außen einzugreifen oder umgekehrt.

Möglicherweise ist aber auch meine Grundstruktur schon verkehrt. Mal abgesehen davon, finde ich die Klasse recht überfrachtet. Welche Variante würdet ihr mir empfehlen, ggf. noch Werte zusammen zu fassen oder auch Gruppen zu bilden? Sofern möglich.

Und ich verstehe nicht, warum meine Quadrate in der Mitte ein Loch haben. Warum sind die nicht vollständig ausgefüllt?

Vielen Dank!
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

Das ist der Grund, warum man sys.exit nicht verwenden sollte. Statt dessen benutzt man Funktionen mit Rückgabewerten.
Eine Kollisionsprüfung hat in einer Funktion, die zeichnen heißt, auch nicht vorkommen.
k-net
User
Beiträge: 24
Registriert: Donnerstag 22. Oktober 2020, 16:43

Okay. Könntest du mir diesbezüglich bitte noch etwas auf die Sprünge helfen? Wie würdest du es lösen? Zumindest so ungefähr...
Danke!
Antworten