Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python pygame中的弹丸运动和重力有时才起作用_Python_Pygame - Fatal编程技术网

Python pygame中的弹丸运动和重力有时才起作用

Python pygame中的弹丸运动和重力有时才起作用,python,pygame,Python,Pygame,为了回答另一个问题,我深入研究了python+pygame。基本上我想创造一个精灵,然后当以初始速度和角度“发射”时,它的行为符合重力和牛顿物理学 我的演示应用程序创建了一堆随机投射物。对于一些射弹,它们在着陆前以正确的抛物线路径向上飞行;太好了 然而: 似乎没有射弹能够向左(270-360度方向)发射 有些射弹从不着陆 我怀疑这是因为math.cos()和math.sin()函数会根据象限改变结果的符号。我想我也有一个错误的假设,0度是“12点”,而这实际上是90度 显然,理想的结果是粒子

为了回答另一个问题,我深入研究了python+pygame。基本上我想创造一个精灵,然后当以初始速度和角度“发射”时,它的行为符合重力和牛顿物理学

我的演示应用程序创建了一堆随机投射物。对于一些射弹,它们在着陆前以正确的抛物线路径向上飞行;太好了

然而:

  • 似乎没有射弹能够向左(270-360度方向)发射
  • 有些射弹从不着陆
我怀疑这是因为
math.cos()
math.sin()
函数会根据象限改变结果的符号。我想我也有一个错误的假设,0度是“12点”,而这实际上是90度

显然,理想的结果是粒子可以左右移动,并且没有粒子飞入轨道

ball.png:

这个应用程序的公式直接取自维基百科的文章


在[-45,45]范围内设置一个随机角度

NOW\u MS=pygame.time.get\u ticks()
SPRITES=pygame.sprite.Group()
对于范围(20)内的i:
速度=随机。随机范围(10,50)
角度=数学弧度(随机范围(-45,45))
新精灵=投射物精灵(精灵图像、速度、角度)
雪碧。添加(新雪碧)
该角度定义了相对于窗口向上方向的传出方向。 因此,
displacement\ux
取决于
math.sin(self.angle)
displacement\uy
取决于
math.cos(self.angle)
。注:必须添加
half\u gravity\u time\u squared
,因为
self.gravity
是负值:

half_gravity_time_squared=self.gravity*time_change*time_change/2.0
位移x=自速度*数学sin(自角度)*时间变化
位移y=自速度x数学cos(自角度)*时间变化+重力的一半时间的平方
请参见示例,其中我将建议应用于您的原始代码:

导入pygame
随机输入
输入数学
#窗口大小
窗宽=1000
窗户高度=400
FPS=60
#背景色
墨灰色=(128128128)
#启动后的毫秒数
现在_MS=0
类ProjectleSprite(pygame.sprite.sprite):
重力=-9.8
def u uu init u uuu(自,位图,速度=0,角度=0):
pygame.sprite.sprite.\uuuuu init\uuuuuuu(自我)
self.image=位图
self.rect=bitmap.get_rect()
self.start\u x=窗口宽度//2
self.start\u y=窗口高度-self.rect.HEIGHT
self.rect.center=((self.start\u x,self.start\u y))
#物理学
self.setInitialVelocityRadians(速度、角度)
def设置初始速度半径(自身、速度、角度):
全球现在
self.start\u time=NOW\u MS
自速度=速度
self.angle=角度
def更新(自我):
全球现在
如果(自速度>0):
time_change=(NOW_MS-self.start_time)/150.0应该是1000,但100看起来更好
如果(时间变化>0):
#重新计算速度
半重力时间平方=self.gravity*时间变化*时间变化/2.0
位移x=自速度*数学sin(自角度)*时间变化
位移y=自速度x数学cos(自角度)*时间变化+重力的一半时间的平方
#重新定位雪碧
self.rect.center=((self.start_x+int(displacement_x),self.start_y-int(displacement_y)))
#停在窗口的底部
如果(self.rect.y>=窗口高度-self.rect.HEIGHT):
self.rect.y=窗高度-self.rect.HEIGHT
自速度=0
#self.kill()
###主要
pygame.init()
SURFACE=pygame.HWSURFACE | pygame.DOUBLEBUF | pygame.resizeable
WINDOW=pygame.display.set_模式((窗口宽度,窗口高度),表面)
pygame.display.set_标题(“投射物运动示例”)
#加载资源映像
sprite_image=pygame.image.load(“ball.png”)#.convert_alpha()
#做些雪碧
现在\u MS=pygame.time.get\u ticks()
SPRITES=pygame.sprite.Group()
对于范围(20)内的i:
速度=随机。随机范围(10,50)
角度=数学弧度(随机范围(-45,45))
新精灵=投射物精灵(精灵图像、速度、角度)
雪碧。添加(新雪碧)
clock=pygame.time.clock()
完成=错误
虽然没有这样做:
现在\u MS=pygame.time.get\u ticks()
#处理用户输入
对于pygame.event.get()中的事件:
如果(event.type==pygame.QUIT):
完成=正确
elif(event.type==pygame.KEYDOWN):
如果(event.unicode=='+'或event.scancode==pygame.K_PLUS):
#按“+”可添加新的投射精灵
速度=随机。随机范围(10100)
角度=数学弧度(随机范围(-45,45))
新精灵=投射物精灵(精灵图像、速度、角度)
雪碧。添加(新雪碧)
如果event.key==pygame.K\n:
对于精灵中的s:
s、 开始时间=现在
s、 速度=随机。随机范围(10,50)
#处理连续按键
keys=pygame.key.get_pressed()
如果(键[pygame.K_ESCAPE]):
#[Esc]也退出
完成=正确
#重新粉刷屏幕
窗口填充(墨灰色)
SPRITES.update()#重新定位精灵
精灵。画(窗)#画精灵
pygame.display.flip()
#更新窗口,但不超过60帧/秒
时钟。勾选忙循环(FPS)
pygame.quit()
使用
print()
在不同时刻显示变量中的值,并显示代码的哪一部分是e的信息
import pygame
import random
import math

# Window size
WINDOW_WIDTH  =1000
WINDOW_HEIGHT = 400
FPS           = 60

# background colours
INKY_GREY    = ( 128, 128, 128 )

# milliseconds since start
NOW_MS = 0

class ProjectileSprite( pygame.sprite.Sprite ):
    GRAVITY          = -9.8  

    def __init__( self, bitmap, velocity=0, angle=0 ):
        pygame.sprite.Sprite.__init__( self )
        self.image       = bitmap
        self.rect        = bitmap.get_rect()
        self.start_x     = WINDOW_WIDTH // 2
        self.start_y     = WINDOW_HEIGHT - self.rect.height
        self.rect.center = ( ( self.start_x, self.start_y ) )
        # Physics
        self.setInitialVelocityRadians( velocity, angle )

    def setInitialVelocityRadians( self, velocity, angle_rads ):
        global NOW_MS
        self.start_time = NOW_MS
        self.velocity   = velocity
        self.angle      = angle_rads 

    def update( self ):
        global NOW_MS
        if ( self.velocity > 0 ):
            time_change = ( NOW_MS - self.start_time ) / 150.0  # Should be 1000, but 100 looks better
            if ( time_change > 0 ):
                # re-calcualte the velocity
                velocity_x = self.velocity * math.cos( self.angle )
                velocity_y = self.velocity * math.sin( self.angle ) - ( self.GRAVITY * time_change )
                # re-calculate the displacement
                # x
                displacement_x  = velocity_x * time_change * math.cos( self.angle ) 
                # y
                half_gravity_time_squared = ( self.GRAVITY * ( time_change * time_change ) ) / 2.0
                displacement_y  = ( velocity_y * time_change * math.sin( self.angle ) ) - half_gravity_time_squared 

                # reposition sprite
                self.rect.center = ( ( self.start_x + int( displacement_x ), self.start_y - int( displacement_y ) ) )

                # Stop at the bottom of the window
                if ( self.rect.y >= WINDOW_HEIGHT - self.rect.height ):
                    self.rect.y = WINDOW_HEIGHT - self.rect.height
                    self.velocity = 0
                    #self.kill()



### MAIN
pygame.init()
SURFACE = pygame.HWSURFACE | pygame.DOUBLEBUF | pygame.RESIZABLE
WINDOW  = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), SURFACE )
pygame.display.set_caption("Projectile Motion Example")

# Load resource image(s)
sprite_image = pygame.image.load( "ball.png" )#.convert_alpha()

# Make some sprites 
SPRITES = pygame.sprite.Group()   
for i in range( 20 ):
    speed = random.randrange( 10, 50 )
    if ( random.randrange( -100, 101 ) > 0 ):
        angle = math.radians( random.randrange( 0, 45 ) )  # 0-45 degrees
    else:
        angle = math.radians( random.randrange( 315, 360 ) )  # minus 0-45 degrees
    new_sprite = ProjectileSprite( sprite_image, speed, angle )
    SPRITES.add( new_sprite )


clock = pygame.time.Clock()
done  = False
while not done:
    NOW_MS = pygame.time.get_ticks()

    # Handle user-input
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True
        elif ( event.type == pygame.KEYDOWN ):
            if ( event.unicode == '+' or event.scancode == pygame.K_PLUS ):
                # Pressing '+' adds a new projectile sprite
                speed = random.randrange( 10,100 )
                angle = math.radians( random.randrange( -45, 45 ) )
                new_sprite = ProjectileSprite( sprite_image, speed, angle )
                SPRITES.add( new_sprite )

    # Handle continuous-keypresses
    keys = pygame.key.get_pressed()
    if ( keys[pygame.K_ESCAPE] ):
        # [Esc] exits too
        done = True

    # Repaint the screen
    WINDOW.fill( INKY_GREY )
    SPRITES.update()          # re-position the sprites
    SPRITES.draw( WINDOW )    # draw the sprites

    pygame.display.flip()
    # Update the window, but not more than 60fps
    clock.tick_busy_loop( FPS )

pygame.quit()