Pygame:如何以随机方向拍摄物体?

问题描述

对象都在同一条线上(向左 45 度)... 当我提取 random_direction 函数来单独测试它时,它给出了相同的向量,只是翻转了 180 度,或者 x 是相同的,y 是相同的,但是是负数......诸如此类。

import pygame
import os
import math
import random
from pygame.math import Vector2

def random_direction():
    vector = Vector2(random.uniform(-max_speed,max_speed),random.uniform(-max_speed,max_speed))
    if vector.length() == 0:
        return vector
    else:
        return Vector2.normalize(vector)


def scaled(vector,scale):
    if vector.length() == 0:
        return vector
    else:
        return Vector2.normalize(vector) * scale


def clamped(vector,limit):
    if vector.length() <= limit or vector.length() == 0:
        return vector
    else:
        return Vector2.normalize(vector) * limit


def shoot():
    for i in range(len(boids)):
        boids[i]['veLocity'] = boids[i]['desired_direction'] * max_speed
        boids[i]['boid'].x += boids[i]['veLocity'].x
        boids[i]['boid'].y += boids[i]['veLocity'].x
        # if boids[i]['boid'].x >= WIDTH:
        #     boids[i]['boid'].x = 0
        # elif boids[i]['boid'].x <= 0:
        #     boids[i]['boid'].x = WIDTH
        # elif boids[i]['boid'].y >= HEIGHT:
        #     boids[i]['boid'].y = 0
        # elif boids[i]['boid'].y <= 0:
        #     boids[i]['boid'].y = HEIGHT

def draw_window():
    WIN.fill((0,0))
    # for i in range(n):
    #     rot_image = pygame.transform.rotate(image_scaled,math.degrees(math.atan2(boids[i]['veLocity'].x,boids[i]['veLocity'].y)) +180)
    #     WIN.blit(rot_image,(boids[i]['boid'].x - int(rot_image.get_width()/2),boids[i]['boid'].y - int(rot_image.get_height()/2))) #########
    for i in range(len(boids)):
        WIN.blit(image_scaled,(boids[i]['boid'].x,boids[i]['boid'].y))
    pygame.display.update()


WIDTH,HEIGHT = 1440,720 #1680,990
WIN = pygame.display.set_mode((WIDTH,HEIGHT))
pygame.display.set_caption('Sim')
FPS = 60

image = pygame.image.load(os.path.join('Assets','long_fish.png'))
image_width,image_height = 40,40
image_scaled = pygame.transform.scale(image,(image_width,image_height))
#boid = pygame.Rect(WIDTH/2,HEIGHT/2,image_width,image_height)
max_speed = 10 #2
steer_strength = 0.04 #2
wander_strength = 0.4 #0.2
# desired_direction = Vector2(0,0)
# veLocity = Vector2(0,0)
# shoot_direction = random_direction()
n = 30
boids = []
for i in range(n):
    boids.append({'boid': pygame.Rect(WIDTH/2,image_height),'desired_direction': random_direction(),'veLocity': Vector2(0,0)})


def main():

    clock = pygame.time.Clock()
    run = True
    while run:
        clock.tick(FPS)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False

        shoot()

        draw_window()

    pygame.quit()

if __name__ == '__main__':
    main()

我之前在 pygame 上做过这样的事情并且他们工作,但我不确定他们为什么这样做而这没有。

解决方法

您的矢量生成器生成一个正方形的边界: enter image description here

因为你的设置方式。然后将向量归一化,将它提出的任何内容放入边界圆中。由于这种方法,更接近角落的值更有可能被选择。从原点到边缘,有一个距离。从原点到拐角,有 1.41 的距离。因此,标准化到角落的值更有可能被选择

这会给您一种没有真正随机值的印象,因为某些值比其他值更频繁地弹出。

解决这个问题的方法是生成一个已经归一化的向量,py 从圆中选择一个点。

最好的方法是生成一个角度,以弧度为单位。例如:

>>> angle = math.radians(random.randint(0,360))

然后,使用一些基本的三角函数将该角度变成一个点

>>> x = math.cos(angle)
>>> y = math.sin(angle)

元组 (x,y) 应该是一个无偏值,它和你的伪随机一样随机(计算机如何随机,它实际上是一个很大的复杂方程,它生成一个非常接近随机的值,但它实际上不是) 生成器会得到。

在您的代码中实现这一点:

def random_direction():
    a = math.radians(random.randint(0,360))
    return pygame.Vector2(math.cos(a),math.sin(a))