0

I want to code a collision. I have 2 classes and if they collide one of them should undraw for 1 second

#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

First class that spawn an object that only can move left and right

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

Second class that spawn trees that are coming from above

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)

This is the collision but its unfinished

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()
Kingsley
  • 14,398
  • 5
  • 31
  • 53

1 Answers1

0

Ok, firstly is the standard response to these sort of questions: If you use the PyGame Sprite functions, after some extra work initially, your program will be easier to write and maintain.

To make good collisions on arbitrary objects, first you need a "bounding box". This is a rectangle which surrounds your object.

Looking at the code for the Schlitten/Sleigh I have to calculate this from the various drawing co-ordinates (but I'm only doing a quick/rough job). It looks like from Schlitten.x and Schlitten.y the rendering extends another 31 pixels in x and 75 pixels in y. You may want to temporarily add some code to draw the bounding-box to check it.

So to define a collision function, we need a 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 )

As you can see from the code, a PyGame Rect just needs the co-ordinates. The .rect will need to be updated as the object moves, but we can do that right before the collision test. We added the self.width and self.height so our code is not peppered with meaningless numbers all over the place. Also if the drawing of the sleigh changes, these numbers need be adjusted only in one place.

Anyway, so now for the collision function:

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 a similar change for your Baum class - at least to the point where the code has a 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

This then allows the code to quickly and easily check for collisions:

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!

Note: The tree-drawing function paints the trees as-if the y co-ordinate is the bottom-left corner. The changes I made do not account for this, so either change the drawing code, or change the position of the Baum.rect to suit this negative-y layout.

Kingsley
  • 14,398
  • 5
  • 31
  • 53