这是我第一次使用stackoverflow,希望你们中的一些人能帮我解决这个问题。
我正在设计一个需要随机显示模式的心理物理实验,如下所示:
https://www.dropbox.com/s/n09vkvbqxagt8hd/dot%20pairs.png?dl=0
但是,我仍然需要指定其余几个参数,但我不知道如何:
每个对象(点对的导入图像)需要随机分布,但要保持与任何其他对象和背景矩形边缘的最小非重叠距离。
每个对象(点对图像)必须具有随机方向。
我希望有人能帮助我尽快在1和2下添加两个参数!
谢谢你!
我找到,改编并用于生成此处给出的插图的代码是(有9个图像,每个图像由点对组成,用&#34命名; stim" * .png):
import random
import pygame
WHITE = (255,255,255)
BLACK = (0 ,0 ,0 )
class Player():
def __init__(self, image, x=0, y=0):
self.image = pygame.image.load(image) #.convert()
#self.image.set_colorkey(WHITE)
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.centery = y
#------------
def draw(self, screen):
screen.blit(self.image, self.rect)
#------------
def update(self):
# here change randomly positon
self.rect.topleft = random.randint(60,220+1), random.randint( 0, 475+1)
class Game():
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((800,600))
self.background = pygame.image.load("background.jpg").convert()
self.multi_players = []
# create stimuli
for i in range(1,10):
player = Player("stim"+str(i)+".png")
player.update() # set random position on start
self.multi_players.append(player)
#------------
def run(self):
clock = pygame.time.Clock()
RUNNING = True
while RUNNING:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
RUNNING = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
RUNNING = False
# changes position when key is pressed
for player in self.multi_players:
player.update()
# --- updates ----
# place for updates
# --- draws ---
self.screen.fill(BLACK)
self.screen.blit(self.background, self.background.get_rect())
for player in self.multi_players:
player.draw(self.screen)
pygame.display.flip()
# --- FPS ---
clock.tick(20)
# --- quit ---
pygame.quit()
Game().run()
答案 0 :(得分:1)
由于这是我第一次与pygame库取得联系,可能是有更好的解决方案,但经过一个小小的研究后我认为检测重叠的最佳方法是使用检测.png mask上的像素完美碰撞。也就是说,pygame允许通过为玩家定义掩码来检查玩家的颜色重叠。我修改了你的代码,它似乎现在运作良好:
import random
import pygame
WHITE = (255,255,255)
BLACK = (0 ,0 ,0 )
RED = (255,0,0)
PLAYERS = []
class Player():
def __init__(self, image, x=0, y=0):
self.image = pygame.image.load(image).convert_alpha() #.convert()
#self.image.set_colorkey(WHITE)
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.centery = y
#self.image.set_colorkey(BLACK)
#------------
def draw(self, screen):
screen.blit(self.image, self.rect)
#------------
def update(self):
#randomly rotate
angle = random.randint(0,360)
#self.image = pygame.transform.rotate(self.image, angle)
self.image = pygame.transform.rotozoom(self.image, angle, 1)
# here change randomly positon
self.rect.topleft = random.randint(60,220+1), random.randint( 0, 475+1)
searchAgain = 0
while (searchAgain < 1):
self.rect.topleft = random.randint(60,220+1), random.randint( 0, 475+1)
searchAgain = 1
for p in PLAYERS:
# creating masks for the images
myImage_mask = pygame.mask.from_surface(self.image)
myOtherImage_mask = pygame.mask.from_surface(p.image)
# this is where the images are
myImage_rect = self.rect
myOtherImage_rect = p.rect
# this is where we check for pixel perfect collision
# observe the order mask variables are used in calculating offset and in overlap method
offset_x, offset_y = (myOtherImage_rect.left - myImage_rect.left), (myOtherImage_rect.top - myImage_rect.top)
print (offset_x, offset_y )
if (myImage_mask.overlap(myOtherImage_mask, (offset_x, offset_y)) != None):
print 'Collision Detected!'
#if we detect collision of players stay in the loop so that we get another pair of coordinates for the new player
searchAgain = 0
else:
print 'None'
class Game():
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((800,600))
self.background = pygame.image.load("background.jpg").convert()
self.multi_players = []
# create stimuli
for i in range(1,10):
player = Player("stim"+str(i)+".png")
#player = Player("stim6.gif")
player.update() # set random position on start
PLAYERS.append(player)
self.multi_players.append(player)
#------------
def run(self):
clock = pygame.time.Clock()
RUNNING = True
while RUNNING:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
RUNNING = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
RUNNING = False
# changes position when key is pressed
for player in self.multi_players:
player.update()
# --- updates ----
# place for updates
# --- draws ---
self.screen.fill(WHITE)
self.screen.blit(self.background, self.background.get_rect())
for player in self.multi_players:
player.draw(self.screen)
pygame.display.flip()
# --- FPS ---
clock.tick(20)
# --- quit ---
pygame.quit()
Game().run()
大多数更改是在Player类的update()函数中完成的,但一般来说,我所做的是:
至于对,我不太明白你是否需要创建相反的点对,但无论如何我希望你有足够的时间继续我在这里发布的内容。您可以在此处获取完整示例:on my dropbox link
希望它有所帮助, 最好的祝福, Gazmend。
另外,作为补充,当使用透明PNG文件以避免在旋转非方形png图像后出现黑色背景问题时,只需在上面的代码中注释self.image.set_colorkey(BLACK)行。我这样说,从个人的经验来看,似乎在使用PNG时,你不需要通过定义颜色键来保持透明度。
答案 1 :(得分:0)
我现在无法使用pygame测试此代码,因为没有在此计算机上安装,但是对于理论建议:
1)避免物体重叠。您应该维护已放置项目的列表,并验证生成随机位置时其边界框是否重叠。
一个例子可能是
在__init__
方法中添加self.surfaces = []
然后在绘制对象时将它们添加到self.surfaces
。每次生成一个新的随机对象时,请执行以下操作:
def test_overlapping_with_other_surfaces(self, myRandomlyPlacedImage):
""" Tests if the randomly placed image overlap with an already existing image. """
for surface in self.surface:
if surface.get_rect.colliderect(myRandomlyPlacedImage.get_rect):
return False
return True
如果对此函数的调用返回false,则将图像随机移动到另一个位置并再次测试。
2)方向的随机化似乎非常简单。实际上,请参阅官方文档http://www.pygame.org/docs/ref/transform.html#pygame.transform.rotate
def randomly_rotate_image(self, image):
""" Returns the image randomly rotated. """
angle = randint(0,360)
return pygame.transform.rotate(image, angle)
并使用self.randomly_rotate_image(image).clip()
代替image.clip()
希望它有所帮助。
亚瑟。