【问题标题】:Is there a way to move an object in pygame in random directions smoothly? [duplicate]有没有办法在 pygame 中以随机方向平滑移动对象? [复制]
【发布时间】:2020-04-24 22:22:51
【问题描述】:

我试图让 blob 在随机方向上移动几帧,而不是只移动一次,以使其看起来不那么生涩和更平滑,但一直无法这样做。在选择另一个随机方向并执行相同操作之前,有什么方法可以让每个对象在同一方向上移动几个刻度?

我的代码(大部分无关紧要):

import pygame
import random
import numpy as np

WIDTH = 1800
HEIGHT = 1000
BLUE = (15,15,180)
RED = (150,0,0)

class Blob:
    def __init__(self, colour, x_boundary, y_boundary, size):
        self.colour = colour
        self.size = size
        self.x_boundary = x_boundary
        self.y_boundary = y_boundary
        self.x = random.randrange(0, self.x_boundary)
        self.y = random.randrange(0, self.y_boundary)

    def move(self):
        self.x += random.randrange(-6,7)
        self.y += random.randrange(-6,7)

    def limits(self):
        if self.x < 0:
            self.x = 0
        elif self.x > self.x_boundary:
            self.x = self.x_boundary
        if self.y < 0:
            self.y = 0
        elif self.y > self.y_boundary:
            self.y = self.y_boundary

    def __add__(self, other_blob):
        if other_blob.size > self.size:
                other_blob.size += int(self.size * 0.5)
                self.size = 0

class FastBlob(Blob):
    def __init__(self, colour, x_boundary, y_boundary, size):
        super().__init__(colour, x_boundary, y_boundary, size)
    def move(self):
        self.x += random.randrange(-20,21)
        self.y += random.randrange(-20,21)

pygame.init()
game_display = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Blob world')
clock = pygame.time.Clock()

def is_touching(b1,b2):
    return np.linalg.norm(np.array([b1.x,b1.y])-np.array([b2.x,b2.y])) < (b1.size + b2.size)

def handle_collisions(blob_list):
    blues, reds, slow_reds = blob_list
    for first_blobs in blues, reds, slow_reds:
        for first_blob_id, first_blob in first_blobs.copy().items():
            for other_blobs in blues, reds, slow_reds:
                for other_blob_id, other_blob in other_blobs.copy().items():
                    if first_blob == other_blob:
                        pass
                    else:
                        if is_touching(first_blob, other_blob):
                            first_blob + other_blob
    return blues, reds, slow_reds

def draw_environment(blob_list):
    game_display.fill((210,210,210))
    handle_collisions(blob_list)
    for blob_dict in blob_list:
        for blob_id in blob_dict:
            blob = blob_dict[blob_id]
            pygame.draw.circle(game_display, blob.colour, [blob.x, blob.y], blob.size)
            blob.move()
            blob.limits()
    pygame.display.update()

def main():
    blue_blobs = dict(enumerate([FastBlob(BLUE, WIDTH, HEIGHT, random.randrange(10,15)) for i in range(20)]))
    red_blobs = dict(enumerate([FastBlob(RED, WIDTH, HEIGHT, random.randrange(5,10)) for i in range(30)]))
    slow_red_blobs = dict(enumerate([Blob(RED, WIDTH, HEIGHT, random.randrange(20,30)) for i in range(5)]))
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                quit()
        draw_environment([blue_blobs, red_blobs, slow_red_blobs])
        clock.tick(7)

if __name__ == '__main__':
    main()

【问题讨论】:

  • 您可以有一个变量,例如move_randomly = False,然后在几个循环之后,将其设置为 true,移动对象,然后再将其设置为 false 进行几个循环。
  • 你也可以看看 perlin noise。

标签: python random pygame


【解决方案1】:

在这里,我的游戏中有类似的问题,当敌人必须随机改变方向时,玩家无法预测。

def goblin_move():                                                  #Goblin auto (random) movement

    if goblin.x < 0:
        goblin.go_right()
    elif goblin.x > 500:
        goblin.go_left()
    else:
        if goblin.x > (rnd_1 * win_width) and goblin.move_flag == -1:
            goblin.go_left()
            goblin.move_flag = -1

        else:
            goblin.go_right()
            goblin.move_flag = 1

    if goblin.x > (rnd_2 * win_width):
        goblin.move_flag = -1


def set_random(rnd_1, rnd_2):                                       #Random function generator

    rnd_1 = round(random.uniform(0, 0.45), 2)
    rnd_2 = round(random.uniform(0.65, 0.95), 2)

    return rnd_1, rnd_2

这就是我在主循环中设置它的方式:

if round(pg.time.get_ticks()/1000) % 3 == 0:        #Calling random function
        (rnd_1, rnd_2) = set_random(rnd_1, rnd_2)

希望你会发现它有用。

【讨论】:

    【解决方案2】:

    使用pygame.math.Vector2 进行计算。将 blob 的坐标存储到 Vector2 并定义最大距离 (self.maxdist)、速度 (self.speed)、随机距离 (self.dist) 和随机方向 (self.dir)。随机方向是一个长度为1的向量(Unit vector)和一个随机的天使(rotate()):

    class Blob:
        def __init__(self, colour, x_boundary, y_boundary, size):
            self.colour = colour
            self.size = size
            self.x_boundary = x_boundary
            self.y_boundary = y_boundary
            self.x = random.randrange(0, self.x_boundary)
            self.y = random.randrange(0, self.y_boundary)
            self.pos = pygame.math.Vector2(self.x, self.y)
            self.maxdist = 7
            self.speed = 1
            self.dist = random.randrange(self.maxdist)
            self.dir = pygame.math.Vector2(1, 0).rotate(random.randrange(360))
    

    当 blob 移动时,按速度缩放方向并将其添加到位置 (self.pos += self.dir * self.speed)。减小距离 (self.dist -= self.speed) 并将 self.x、self.y 更新为圆角 (round) 位置。如果self.dist低于0,则创建一个新的随机方向和距离:

    class Blob:
        # [...]
    
        def move(self):
            self.pos += self.dir * self.speed
            self.dist -= self.speed
            self.x, self.y = round(self.pos.x), round(self.pos.y)
    
            if self.dist <= 0:
                self.dist = random.randrange(self.maxdist)
                self.dir = pygame.math.Vector2(1, 0).rotate(random.randrange(360))
    

    在limit 方法中,您必须确保self.pos 在范围内。最后你要更新self.x,self.y:

    class Blob:
        # [...]
    
        def limits(self):
            if self.pos.x < 0:
                self.pos.x = 0
            elif self.pos.x > self.x_boundary:
                self.pos.x = self.x_boundary
            if self.pos.y < 0:
                self.pos.y = 0
            elif self.pos.y > self.y_boundary:
                self.pos.y = self.y_boundary
            self.x, self.y = round(self.pos.x), round(self.pos.y)
    

    FastBlob 类不需要自己的move 方法。定义自己的self.maxdist 和self.speed 就足够了:

    class FastBlob(Blob):
        def __init__(self, colour, x_boundary, y_boundary, size):
            super().__init__(colour, x_boundary, y_boundary, size)
            self.maxdist = 35
            self.speed = 5
    

    【讨论】:

      猜你喜欢
      • 2017-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-15
      • 2010-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多