【问题标题】:Adding gravity to a bouncing ball using vectors使用向量为弹跳球添加重力
【发布时间】:2017-09-29 09:26:22
【问题描述】:

我有一个重力向量(形式为 [r, theta]),我将它添加到我的球的速度向量中。由于某种原因,球在弹起后并没有回到原来的高度,而是零星地慢慢失去高度。我猜我正在使用的计算中有一些舍入错误或某些东西,但我无法隔离问题。

这是我的代码。您需要文件和 pygame 来运行它。对不起,如果它有点混乱。如果你愿意,我可以再评论一些。

每当球达到其最大高度时,我都会添加一个标记,所以你们就是我的意思。我希望球在每次反弹时都返回到完全相同的高度。

我去掉了一些不必要的代码。完整的程序在 pastebin 链接下。


https://pastebin.com/FyejMCmg - PhysicsSim

import pygame, sys, math, tools, random, time
from pygame.locals import *

clock = pygame.time.Clock()
lines = []

class Particle:
    def __init__(self,screen,colour, mass, loc, vel):
        self.screen = screen
        self.colour = colour

        self.mass = mass

        self.x = loc[0]
        self.y = loc[1]
        self.location = self.x,self.y
        self.speed = vel[0]
        self.angle = vel[1]


    def update(self):
        global lines

        # add gravity
        self.speed,self.angle = tools.add_vectors2([self.speed,self.angle], tools.GRAVITY)

        # update position
        dt = clock.tick(60)
        self.x += self.speed * tools.SCALE * math.cos(self.angle) * dt
        self.y -= self.speed * tools.SCALE * math.sin(self.angle) * dt
        self.location = int(self.x),int(self.y)

        # border checking
        do = False
        n=[]
        if ((self.y+self.mass) > tools.SCREEN_HEIGHT):
            self.y = tools.SCREEN_HEIGHT-self.mass
            n = [0,1]
            do = True

        # adds position to array so max height so max height can be recorded
        if (self.speed==0):
            lines.append([self.screen, self.location, self.mass])

        # bounce
        if do:
            #init, convert everything to cartesian
            v = tools.polarToCartesian([self.speed, self.angle])

            #final -> initial minus twice the projection onto n, where n is the normal to the surface
            a = tools.scalarP(2*abs(tools.dotP(v,n)),n) #vector to be added to v
            v = tools.add_vectors(v,a)

            self.angle = tools.cartesianToPolar(v)[1] # does not set magnitude


        # drawing
        pygame.draw.circle(self.screen, self.colour, self.location, self.mass, 0)

# draws max height line
def draw_line(l):
    screen = l[0]
    location = l[1]
    radius = l[2]
    pygame.draw.line(screen, tools.BLACK, [location[0] + 15, location[1]-radius],[location[0] - 15, location[1]-radius])

def main():
    pygame.init()

    DISPLAY = pygame.display.set_mode(tools.SCREEN_SIZE,0,32)
    DISPLAY.fill(tools.WHITE)

    particles = []
    particles.append(Particle(DISPLAY, tools.GREEN, 10, [100,100], [0,0]))

    done = False
    while not done:
        global lines
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()

        DISPLAY.fill(tools.WHITE)
        for i in particles:
            i.update()

        for l in lines:
            draw_line(l)

        pygame.display.update()

main()

https://pastebin.com/Epgqka31 - 工具

import math

#colours
WHITE =     (255, 255, 255)
BLUE =      (  0,   0, 255)
GREEN =     (  0, 255,   0)
RED =       ( 255,  0,   0)
BLACK =     (   0,  0,   0)

COLOURS = [WHITE,BLUE,GREEN,RED,BLACK]

#screen
SCREEN_SIZE = SCREEN_WIDTH,SCREEN_HEIGHT = 1000,700

#vectors
GRAVITY = [5.0, 3*math.pi/2] # not 9.8 because it seems too high
SCALE = 0.01

# converts polar coordinates to cartesian coordinates in R2
def polarToCartesian(v):
    return [v[0]*math.cos(v[1]), v[0]*math.sin(v[1])]

# converts cartesian coordinates to polar coordinates in R2
def cartesianToPolar(v):
    return [math.sqrt(v[0]**2 + v[1]**2), math.atan2(v[1],v[0])]

# dots two cartesian vectors in R2
def dotP(v1, v2):
    return v1[0]*v2[0] + v1[1]*v2[1]

# multiplies cartesian vector v by scalar s in Rn
def scalarP(s,v):
    v_=[]
    for i in v:
        v_.append(s*i)
    return v_

# returns the sum of two cartesian vectors in R2
def add_vectors(v1, v2):
    return [v1[0]+v2[0], v1[1]+v2[1]]

# returns the sum of two polar vectors in R2, equations from https://math.stackexchange.com/questions/1365622/adding-two-polar-vectors
def add_vectors2(v1,v2):
    r1,r2,t1,t2 = v1[0],v2[0],v1[1],v2[1]
    return [math.sqrt(r1**2 + r2**2 + 2*r1*r2*math.cos(t2-t1)), t1 + math.atan2(r2*math.sin(t2 - t1), r1 + r2*math.cos(t2 - t1))]

【问题讨论】:

  • 欢迎来到 StackOverflow。请阅读并遵循帮助文档中的发布指南。 Minimal, complete, verifiable example 适用于此。在您发布 MCVE 代码并准确描述问题之前,我们无法有效地帮助您。我们应该能够将您发布的代码粘贴到文本文件中并重现您描述的问题。
  • @Prune 我不想复制粘贴它,因为它很长,但我想我会的。
  • 请隔离问题并发布MCVE。球是否完全有弹性?一个普通的球(在现实生活中)在弹跳后也不会回到原来的高度。
  • @AdamSmith 我打算稍后再添加,但我没有添加任何内容使其无弹性。
  • 好多了。关闭投票被撤回,反对票变为赞成票。

标签: python pygame game-physics


【解决方案1】:

您的时间间隔dt = clock.tick(60) 不是一个常数。如果您将其更改为dt = 60,您的程序将按预期运行。

查看Verlet Algorithm 并在您的代码中实现它。你在正确的轨道上!

【讨论】:

  • 干得好。我正在寻找退回代码中的截断错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-05
  • 1970-01-01
  • 1970-01-01
  • 2010-09-25
  • 2013-05-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多