Как запрограммировать столкновение - PullRequest
0 голосов
/ 25 марта 2020

Я хочу закодировать коллизию. У меня есть 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 Ответ

0 голосов
/ 25 марта 2020

Хорошо, во-первых, это стандартный ответ на такие вопросы: если вы используете функции 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

Make аналогичное изменение для вашего 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 в соответствии с этим макетом с отрицательным знаком y.

...