问题
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