python - 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 上做过这样的事情并且它们可以工作,但我不确定它们为什么会这样做,而这不会。
解决方案
因为你设置它的方式。然后,您对向量进行归一化,将它提出的任何内容放入边界圆中。由于这种方法,更接近角落的值更有可能被选择。从原点到边缘,有一个距离。从原点到拐角处的距离为 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))
推荐阅读
- solidity - BEP20 如何从 maxlimit 函数中排除销毁钱包
- python - python如何在列表显示中跳过行
- c# - 创建鼠标悬停词定义目录
- powerbi - PowerBI 中的层级动态排名
- javascript - 从 SQL 中反应删除
- git - 使用 vscode 作为 git 版本 (2.31.1) difftool
- ios - 如何仅从我的 iPhone 相机中获取媒体文件(图像/视频)?
- tensorflow - 从检查点加载 keras 权重
- python - 有没有办法在删除表时删除 BigQuery 视图?
- reactjs - 使用 React Hooks 显示下拉值选择选项