简体   繁体   English

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

[英]How to simulate more realistic movement of an object?

I am writing a game environment, in which a person (worker) should move inside the area in a random direction, until it crosses with one of green-coloured obstacles (defined as pygame.draw.rect(screen, GREEN, [510,150,75,52]) and pygame.draw.rect(screen, GREEN, [450,250,68,40]) ). 我正在写一个游戏环境,其中一个人(工人)应在区域内随机移动,直到与绿色障碍物(定义为pygame.draw.rect(screen, GREEN, [510,150,75,52])pygame.draw.rect(screen, GREEN, [450,250,68,40]) )。

Until now I can simulate a random movement of a worker, but it moves somehow irregularly and non-smoothly, jumping around the same area and slowly shifting to the right bottom corner. 到现在为止,我可以模拟工人的随机运动,但是它以某种方式不规则且不平滑地运动,在相同区域周围跳跃并缓慢移至右下角。

How can I update the function create_randomPATH to support a more realistic smooth movement of a worker inside the screen area? 如何更新函数create_randomPATH以支持工作人员在屏幕区域内更真实的平滑移动? I tried to increase a tick size till 70 or even more ( clock.tick(70) ) as it is indicated in one of threads, but it does not seem to solve the problem. 我试图将刻度线的大小增加到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()

You could use an extra direction variable in your code which says in which direction the player is currently moving. 您可以在代码中使用额外的direction变量,该变量说明播放器当前正在朝哪个方向移动。 One of four values: up, right, down or left. 四个值之一:上,右,下或左。 Every once in a while update that direction variable. 偶尔更新该方向变量。 Meanwhile move only one coordinate at a time in that 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

In your code you would also need a global direction variable, initially it should also have a value 1, 2, 3 or 4: 在您的代码中,您还需要一个全局方向变量,最初它也应该具有值1、2、3或4:

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

By moving only one step on every iteration, we assure that the movement speed is always constant. 通过在每次迭代中仅移动一个步骤,我们可以确保移动速度始终恒定。 In your code, it was varying from 1 to 5 steps. 在您的代码中,它从1步到5步不等。 Also if you move a few steps in a given direction straight, it would seem more natural than changing the direction very suddenly very often. 同样,如果您沿给定的方向笔直移动几步,那似乎比经常突然改变方向更自然。 Try to play with the percentage (currently 20% chance) of how often the direction is changed and see if it makes the movement even smoother. 尝试改变方向的频率(目前有20%的机会)的百分比,看它是否使运动更加平滑。

EDIT: 编辑:

Because of the randomness of the movement, eventually the moving object will reach the borders of the game and might leave the screen. 由于移动的随机性,最终移动的对象将到达游戏的边界并可能离开屏幕。 Adjust the position after each movement: 每次移动后调整位置:

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

Then the object will not exit the screen and will eventually randomly move in other directions again. 然后,该对象将不会退出屏幕,并且最终将再次随机向其他方向移动。 Because each direction is equally likely, it will move all around the screen properly. 由于每个方向的可能性均等,因此它将在整个屏幕上正常移动。

Take screen.blit(worker.image, (w_x,w_y)) and put it in it's own method. screen.blit(worker.image, (w_x,w_y))并将其放入自己的方法中。 Then you can create a loop to loop from the oldX and oldY to the new position found by create_randomPATH You can even make the direction to move random by making them move in the x or y direction randomly each time. 然后,你可以创建一个循环,从循环oldXoldY通过发现新的位置create_randomPATH你甚至可以使方向使它们在动来动随机xy每次方向随机。

Below is a rough example, but you probably have to modify it to match your code. 以下是一个粗略的示例,但是您可能必须对其进行修改以使其与代码相匹配。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM