代码之家  ›  专栏  ›  技术社区  ›  ScalaBoy

如何模拟物体更真实的运动?

  •  0
  • ScalaBoy  · 技术社区  · 6 年前

    我正在写一个游戏环境,在这个环境中,一个人(工人)应该在区域内随机移动,直到它与绿色障碍物(定义为 pygame.draw.rect(screen, GREEN, [510,150,75,52]) pygame.draw.rect(screen, GREEN, [450,250,68,40]) ).

    到目前为止,我可以模拟一个工人的随机移动,但它的移动不知何故不规则且不平稳,在同一区域跳跃并缓慢地移动到右下角。

    如何更新函数 create_randomPATH 支持屏幕区域内工人更真实流畅的移动?我试着把蜱虫的数量增加到70甚至更多( clock.tick(70) )正如在一个线程中指出的,但它似乎无法解决问题。

    import pygame, random
    import sys
    
    WHITE = (255, 255, 255)
    GREEN = (20, 255, 140)
    GREY = (210, 210 ,210)
    RED = (255, 0, 0)
    PURPLE = (255, 0, 255)
    
    SCREENWIDTH=1000
    SCREENHEIGHT=578      
    
    class Worker(pygame.sprite.Sprite):
        def __init__(self, image_file, location):
            pygame.sprite.Sprite.__init__(self)
            self.image = pygame.image.load(image_file)
            self.rect = self.image.get_rect()
            self.rect.left, self.rect.top = location
    
        def create_randomPATH(self,x,y):
            randomX = random.randint(1,5)
            randomY = random.randint(1,5)
            if random.uniform(0,1)>0.5:
                valX = x  + randomX
                valY = y  + randomY
            else:
                valX = x  - randomX
                valY = y  - randomY   
            return valX, valY
    
    class Background(pygame.sprite.Sprite):
        def __init__(self, image_file, location):
            pygame.sprite.Sprite.__init__(self)
            self.image = pygame.image.load(image_file)
            self.rect = self.image.get_rect()
            self.rect.left, self.rect.top = location
    
    pygame.init()
    
    size = (SCREENWIDTH, SCREENHEIGHT)
    screen = pygame.display.set_mode(size)
    screen_rect=screen.get_rect()
    pygame.display.set_caption("TEST")
    
    worker = Worker("worker.png", [0,0])
    w_x = worker.rect.left
    w_y = worker.rect.top
    
    bg = Background("background.jpg", [0,0])
    
    carryOn = True
    clock=pygame.time.Clock()
    
    while carryOn:
            for event in pygame.event.get():
                if event.type==pygame.QUIT:
                    carryOn=False
                    pygame.display.quit()
                    pygame.quit()
                    quit()
    
            # Draw floor layout 
            screen.blit(pygame.transform.scale(bg.image, (SCREENWIDTH, SCREENHEIGHT)), bg.rect)
    
            # Draw obstacles
            pygame.draw.rect(screen, GREEN, [510,150,75,52])
            pygame.draw.rect(screen, GREEN, [450,250,68,40])
    
            w_x,w_y = worker.create_randomPATH(w_x,w_y)
    
            # worker should not go outside the screen area
            worker.rect.clamp_ip(screen_rect)
    
            screen.blit(worker.image, (w_x,w_y))
    
            # Refresh Screen
            pygame.display.flip()
    
            clock.tick(5)
    
    pygame.display.quit()
    pygame.quit()
    quit()
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   Jimenemex    6 年前

    采取 screen.blit(worker.image, (w_x,w_y)) 把它用自己的方法。然后可以从 oldX oldY 到新的位置 create_randomPATH 你甚至可以让它们在 x y 每次都是随机的。

    下面是一个粗略的例子,但是您可能需要修改它以匹配您的代码。

    def UpdatePerson(image, x, y):
        screen.blit(image, x, y)
    
    while carryOn:
    
        ...
        ...
    
        oldX = w_x
        oldY = w_y
    
        w_x,w_y = worker.create_randomPATH(w_x,w_y)
    
    
        while(oldX < w_x || oldY < w_y):
            randomDir = random.randint(1,2)
    
            if randomDir == 1 && oldX < w_x:
                UpdatePerson(worker.image, oldX, w_y)
                oldX += 1
            elif randomDir == 2 && oldY < w_x
                UpdatePerson(worker.image, w_x, oldY)
                oldY += 1
    
        2
  •  1
  •   Snackoverflow Chris Johnsen    6 年前

    你需要额外的 direction 代码中的变量,该变量指示播放器当前正在向哪个方向移动。四个值之一:向上、向右、向下或向左。每隔一段时间更新一次这个方向变量。同时,一次只能在该方向移动一个坐标。

    def create_randomPATH(self, x, y, dir):
        if random.uniform(0,1)>0.8:
            # there is a 20% chance every time that direction is changed
            dir = random.randInt(1,4)
    
        if dir == 1:
            return x, y+1, dir # up
        if dir == 2:
            return x+1, y, dir # right
        if dir == 3:
            return x, y-1, dir # down
        if dir == 4:
            return x-1, y, dir # left
    

    在您的代码中,还需要全局方向变量,最初它还应该有一个值1、2、3或4:

    w_x,w_y,w_dir = worker.create_randomPATH(w_x,w_y,w_dir)
    

    通过每次迭代只移动一步,我们可以保证运动速度始终是恒定的。在你的代码中,它从1步到5步不等。另外,如果你在一个给定的方向上直线移动几步,看起来比经常突然改变方向更自然。试着用这个百分比(现在是20%的几率)来计算方向改变的频率,看看它是否能使移动更加平滑。

    编辑:

    由于移动的随机性,最终移动的对象将到达游戏的边界并可能离开屏幕。每次移动后调整位置:

    w_x,w_y,w_dir = worker.create_randomPATH(w_x,w_y,w_dir)
    
    if (w_x + worker.rect.width > SCREENWIDTH): w_x = SCREENWIDTH - worker.rect.width
    if (w_x < 0): w_x = 0
    if (w_y + worker.rect.height > SCREENHEIGHT): w_y = SCREENHEIGHT - worker.rect.height
    if (w_y < 0): w_y = 0
    

    然后,对象将不会退出屏幕,并最终将随机在其他方向再次移动。因为每个方向的可能性都一样,所以它会在屏幕上正确地移动。