首页 > 解决方案 > 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, 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, HEIGHT/2, image_width, 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 上做过这样的事情并且它们可以工作,但我不确定它们为什么会这样做,而这不会。

标签: pythonpygame

解决方案


您的矢量生成器生成的边界为正方形: 在此处输入图像描述

因为你设置它的方式。然后,您对向量进行归一化,将它提出的任何内容放入边界圆中。由于这种方法,更接近角落的值更有可能被选择。从原点到边缘,有一个距离。从原点到拐角处的距离为 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))

推荐阅读