Use collidelist in class

点点圈 提交于 2021-02-10 06:13:00

问题


I have created a class to create rectangles and put them in a list . I don't want them to collide so I use collidelist but it isn't working.rectangles are still colliding .

I also want rectangles to move down and change x position when hit a specific point ,

I can do that but I am not sure if it is preventing collidelist from working

Look the code below for more clarification.

import pygame
import random
from pygame.locals import *
import time 
pygame.init()
a = 255,255,255
b = 0,0,0
c = 80,255,0
d = 0,125,125
r1 = (b,c,d)
r = random.choice(r1)
p_x = 500
p_y = 1399
width = 500
height = 1890

display = pygame.display.set_mode((width,height))
title = pygame.display.set_caption("Game")
clock = pygame.time.Clock()

run = False
exit_game = False

x = random.randrange(10,900)
y = random.randrange(10,900)

sy = 10
w = random.randrange(40,90)
h = random.randrange(40,90)

rectangles =[]

class Rectangle:
    def __init__(self ,color ,x,y,w,h):
        self.c = color
        self.x = x
        self.y = y
        self.w = w
        self.h = h
        self.rect =pygame.Rect(self.x ,self.y ,self.w ,self.h)
        
    def draw(self):
        pygame.draw.rect(display , self.c ,(self.x ,self.y ,self.w,self.h))
        
        self.y += sy
        if self.y > height:
                self.y = -25
                self.x = random.randint(10,900)
                return self.rect
        return self.rect
                
        
    
                
            
            


for count in range(5):
    r_c = random.randint(0,255) , random.randint(0,255) , random.randint(0,255) 
    
    r_x = random.randint(10,900)
    r_y = random.randint(10,79)
    r_w = random.randint(60,100) 
    r_h = random.randint(40,80) 
    
    
    rectangle = Rectangle(r_c ,r_x,r_y,r_w,r_h)
    rectangles.append(rectangle)

    
    
    
    

while not run:
    display.fill(a)
    p =pygame.draw.rect(display,c,(p_x ,p_y ,56,56))
    
    

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit_game = True
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_q:
                p_x -= 60
            if event.key == pygame.K_p:
                p_x += 60
                
    for rectangle in rectangles:
        if rectangle.rect.collidelist(rectangles) > -1:     
            rectangle.draw()

        

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

pygame.quit()
quit()
    

回答1:


collidelist() evaluates the collisions between a singe pygame.Rect object and a list of pygame.Rect objects. Remove the attributes .x, .y, .w and .h from the class, but add an new method update:

class Rectangle:
    def __init__(self, color, x, y, w, h):
        self.c = color
        self.rect = pygame.Rect(x, y, w, h)
    def update(self):
        self.rect.y += sy
        if self.rect.y > height:
            self.rect.y = -25
            self.rect.x = random.randint(10,900)
    def draw(self):
        pygame.draw.rect(display, self.c, self.rect)

Before the collision test you have to generate a list of pygame.Rect objects. Since each rectangle is in the list, the collision test will always find at leas one rectangle (itself). Use collidelistall() and test if the number of colliding rectangles is less than 2:

while not run:
    # [...]

    for rectangle in rectangles:
        rectangle.update()
        rectlist = [r.rect for r in rectangles]
        if len(rectangle.rect.collidelistall(rectlist)) < 2:     
            rectangle.draw()

Anyway, I recommend to create rectangles, which are not intersecting. At initialization:

rectangles = []        
rectlist = []           
for count in range(5):
    r_c = random.randint(0,255) , random.randint(0,255) , random.randint(0,255) 
    
    create_new = True
    while create_new:
        r_x = random.randint(10,900)
        r_y = random.randint(10,79)
        r_w = random.randint(60,100) 
        r_h = random.randint(40,80) 
        rectangle = Rectangle(r_c, r_x,r_y,r_w,r_h)
        create_new = rectangle.rect.collidelist(rectlist) > -1
    
    rectangles.append(rectangle)
    rectlist.append(rectangle.rect)

And in the method update of the class Rectangle:

class Rectangle:
    # [...]

    def update(self, rectangles):
        self.rect.y += sy
        if self.rect.y > height:
            rectlist = [r.rect for r in rectangles if r != self]
            self.rect.y = -25
            self.rect.x = random.randint(10,900)
            while self.rect.collidelist(rectlist) > -1:
                self.rect.x = random.randint(10,900)

Complete Example:

import pygame
import random
from pygame.locals import *
import time 
pygame.init()
a = 255,255,255
b = 0,0,0
c = 80,255,0
d = 0,125,125
r1 = (b,c,d)
r = random.choice(r1)
p_x = 500
p_y = 1399
width = 500
height = 1890

display = pygame.display.set_mode((width,height))
title = pygame.display.set_caption("Game")
clock = pygame.time.Clock()

run = False
exit_game = False

sy = 10

class Rectangle:
    def __init__(self, color, x, y, w, h):
        self.c = color
        self.rect = pygame.Rect(x, y, w, h)

    def update(self, rectangles):
        self.rect.y += sy
        if self.rect.y > height:
            rectlist = [r.rect for r in rectangles if r != self]
            self.rect.y = -25
            self.rect.x = random.randint(10,900)
            while self.rect.collidelist(rectlist) > -1:
                self.rect.x = random.randint(10,900)
    
    def draw(self):
        pygame.draw.rect(display, self.c, self.rect)

rectangles = []        
rectlist = []           
for count in range(5):
    r_c = random.randint(0,255) , random.randint(0,255) , random.randint(0,255) 
    
    create_new = True
    while create_new:
        r_x = random.randint(10,900)
        r_y = random.randint(10,79)
        r_w = random.randint(60,100) 
        r_h = random.randint(40,80) 
        rectangle = Rectangle(r_c, r_x,r_y,r_w,r_h)
        create_new = rectangle.rect.collidelist(rectlist) > -1
    
    rectangles.append(rectangle)
    rectlist.append(rectangle.rect)

while not run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit_game = True
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_q:
                p_x -= 60
            if event.key == pygame.K_p:
                p_x += 60
                
    for rectangle in rectangles[:]:
        rectangle.update(rectangles)
    
    display.fill(a)
    p = pygame.draw.rect(display,c,(p_x ,p_y ,56,56))
    for rectangle in rectangles:
        rectangle.draw()
    pygame.display.update()
    clock.tick(60)
    
pygame.quit()
quit()


来源:https://stackoverflow.com/questions/63705475/use-collidelist-in-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!