Как запрограммировать столкновение

Я хочу закодировать коллизию. У меня есть 2 класса, и если они сталкиваются, один из них должен отрыть в течение 1 секунды

#Laden der Pygame Bibliothek
import pygame
import time
import random
#Initialisierung der Pygame Bibliothek
pygame.init()

# Spiel-Fenster erstellen
size = [700, 500]
screen = pygame.display.set_mode(size)
screen.fill((255,255,255))
# Noetig um die fps zu begrenzen
clock = pygame.time.Clock()

# Speichert ob das Spiel-Fenster geschlossen wurde
done = False

Первый класс, который порождает объект, который может двигаться только влево и вправо

class Schlitten():
    def __init__(self, px, py, pscreen):
        self.FARBE1 = (139,87,66)
        self.FARBE2 = (139,90,43)
        self.braun = (104,73,71)
        self.x = px
        self.grau = (118,122,121)
        self.y = py
        self.red = (255,0,0)
        self.screen = pscreen
        self.hit = False    


    def draw(self):
        if self.hit == False:
            pygame.draw.rect(self.screen, self.FARBE2, [self.x,self.y,5,75])
            pygame.draw.rect(self.screen, self.FARBE2, [self.x+29,self.y,5,75])
            pygame.draw.rect(self.screen, self.braun, [self.x+5,self.y+20,24,3])
            pygame.draw.rect(self.screen, self.braun, [self.x+5,self.y+55,24,3])
            pygame.draw.rect(self.screen, self.FARBE1, [self.x+6,self.y+15,3,50])
            pygame.draw.rect(self.screen, self.FARBE1, [self.x+12,self.y+15,3,50])
            pygame.draw.rect(self.screen, self.FARBE1, [self.x+18,self.y+15,3,50])
            pygame.draw.rect(self.screen, self.FARBE1, [self.x+24,self.y+15,3,50])
            pygame.draw.rect(self.screen, self.grau, [self.x+5,self.y+10,24,2])

    def kollision(self):
        self.hit = True


    def movemint(self):
        keys = pygame.key.get_pressed()
        if keys [pygame.K_LEFT] :
            self.x -= 4

        if keys [pygame.K_RIGHT] :
            self.x += 4

        if self.x < 0:
            self.x += 4

        if self.x > 665:
            self.x -= 4


    def left(self):
        return self.x

    def right(self):
        return self.x+34

    def up(self):
        return self.y

    def down(self):
        return self.y+75

Второй класс, который порождает деревья, идущие сверху

class Baum():
    def __init__(self ,pos_x , pos_y ,pscreen ,pschlitten):
        self.green = (0,100,0)
        self.braun = (139,69,19)
        self.red = (255,0,0)
        self.x = pos_x
        self.y = pos_y
        self.screen = pscreen
        self.Schlitten = pschlitten


    def draw(self):
        pygame.draw.polygon(self.screen ,self.green , [(self.x+50 ,self.y-95),(self.x+0 , self.y-10),                    
        (self.x+100,self.y-10)])
        pygame.draw.rect(self.screen , self.braun , [self.x+43,self.y-10,15,30])
        pygame.draw.polygon(self.screen , self.green , [(self.x+50 , self.y-95), (self.x+5 , self.y-        
        25), (self.x+95,self.y-25)])
        pygame.draw.polygon(self.screen , self.green , [(self.x+50 , self.y-95), (self.x+10 , self.y- 
        40), (self.x+90,self.y-40)])
        pygame.draw.polygon(self.screen , self.green , [(self.x+50 , self.y-95), (self.x+15, self.y- 
        53), (self.x+85,self.y-53)])


    def bewegung(self):
        self.y += 5


    def spawn(self):
        if self.y > 600:
            self.y = -50
            self.x = random.randrange(0,700)

Это столкновение, но его незаконченное

def collision(self):
            if self.y > 385:
                self.Schlitten.hit()

#Objekt der Klasse Schlitten erzeugen
spieler1 = Schlitten(350,400,screen)
Score = score(Baum)
#Objekt der Klasse Baum erzeugen
Baum1 = Baum(500,0 ,screen , spieler1)
Baum2 = Baum(300,-525 , screen , spieler1)
Baum3 = Baum(100,-1050 , screen, spieler1)



schrift = pygame.font.SysFont("comicsans" , 30 , True ) 
# -------- Haupt-Schleife -----------
while not done:
    # Ändert den Wert von done auf True, falls Spiel-Fenster geschlossen wird
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True



    # --- hier Zeichenbefehle ergänzen---

    # Screen mit weiß fuellen
    screen.fill((255,255,255))

    pygame.mixer.music.set_volume(0.1)



    Score.anzeigen()


    # Schlitten zeichnen
    spieler1.draw()
    spieler1.movemint()




    # Baeume zeichnen
    Baum1.draw()
    Baum1.bewegung()
    Baum1.spawn()
    Baum1.collision()




    Baum2.draw()
    Baum2.bewegung()
    Baum2.spawn()
    Baum2.collision()




    Baum3.draw()
    Baum3.bewegung()
    Baum3.spawn()
    Baum3.collision()

Всего 1 ответ


Хорошо, во-первых, это стандартный ответ на такие вопросы: если вы используете функции PyGame Sprite , после некоторой дополнительной работы на начальном этапе вашу программу будет легче писать и поддерживать.

Чтобы создавать хорошие столкновения на произвольных объектах, сначала вам нужен «ограничивающий прямоугольник». Это прямоугольник, который окружает ваш объект.

Глядя на код для Schlitten / Sleigh, я должен рассчитать это по различным координатам рисования (но я делаю только быструю / грубую работу). Похоже, из Schlitten.x и Schlitten.y рендеринг расширяется еще на 31 пиксель в x и 75 пикселов в y . Вы можете временно добавить некоторый код, чтобы нарисовать ограничивающий прямоугольник, чтобы проверить его.

Итак, чтобы определить функцию столкновения, нам нужен PyGame Rect.

class Schlitten:
    def __init__( self ):
        self.x      = px
        self.y      = py        
        self.width  = 31
        self.height = 75
        self.rect   = pygame.Rect( px, py, self.width, self.height )

Как видно из кода, PyGame Rect просто нуждается в координатах. .rect нужно будет обновлять при перемещении объекта, но мы можем сделать это прямо перед тестом на столкновение. Мы добавили self.width и self.height чтобы наш код не был усыпан бессмысленными числами повсюду. Также, если рисунок салазок меняется, эти цифры нужно корректировать только в одном месте.

Во всяком случае, теперь для функции столкновения:

class Schlitten:
    ...

    def collideWith( self, other_rect ):
        """ Has the sleigh collided with the other object """
        self.rect.x = self.x              # update the rect position 
        self.rect.y = self.y
        collision   = self.rect.colliderect( other_rect )
        return collision

Сделайте аналогичное изменение для вашего класса Baum - по крайней мере до того момента, когда в коде есть baum.rect .

class Baum():
    def __init__( self, pos_x, pos_y, pscreen, pschlitten ):
        self.x      = pos_x
        self.y      = pos_y
        self.width  = 50
        self.height = 95
        self.rect   = pygame.Rect( pos_x, pos_y, self.width, self.height )

    def bewegung( self ):
        self.y      += 5
        self.rect.y += 5

    def spawn( self ):
        if self.y > 600:
            self.y      = -50
            self.x      = random.randrange(0,700)
            self.rect.x = x
            self.rect.y = y

Затем это позволяет коду быстро и легко проверять наличие коллизий:

alles_baumen = [ Baum1, Baum2, Baum3 ]    # all tree objects

# main loop
while not exiting:
    ...

    for baum in alles_baumen:                       # for each tree
        baum.draw()
        baum.bewegung()
        baum.spawn()
        if ( speiler1.collideWith( baum.rect ) ):   # player hits tree?
            speiler1.kollision()                    # Oh-noes!

Примечание. Функция рисования дерева рисует деревья так, как если бы координата y находилась в нижнем левом углу. Внесенные мною изменения не учитывают этого, поэтому либо измените код чертежа, либо измените положение Baum.rect чтобы оно соответствовало этой негативной компоновке.