创建具有指定的最小距离和随机方向的图像对象的随机模式

时间:2014-09-17 06:35:44

标签: python python-2.7 pygame

这是我第一次使用stackoverflow,希望你们中的一些人能帮我解决这个问题。

我正在设计一个需要随机显示模式的心理物理实验,如下所示:

https://www.dropbox.com/s/n09vkvbqxagt8hd/dot%20pairs.png?dl=0

但是,我仍然需要指定其余几个参数,但我不知道如何:

  1. 每个对象(点对的导入图像)需要随机分布,但要保持与任何其他对象和背景矩形边缘的最小非重叠距离。

  2. 每个对象(点对图像)必须具有随机方向。

  3. 我希望有人能帮助我尽快在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()
    

2 个答案:

答案 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()函数中完成的,但一般来说,我所做的是:

  1. 我定义了一个全局的玩家列表,我添加了每个新创建的玩家
  2. 在每次更新中,我首先旋转播放器以获得随机角度
  3. 然后我给它一个随机的x,y位置
  4. 然后我检查新创建的玩家是否会与玩家列表中的现有玩家重叠。我通过掩码比较进行检查
  5. 如果没有碰撞 - 我添加了玩家,如果发生碰撞 - 我会要求另一组随机坐标。
  6. 至于对,我不太明白你是否需要创建相反的点对,但无论如何我希望你有足够的时间继续我在这里发布的内容。您可以在此处获取完整示例: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()

希望它有所帮助。

亚瑟。