如何使用图形绘制炮弹

0 投票
1 回答
1001 浏览
提问于 2025-04-17 20:32

你好,我现在需要写一个类来绘制炮弹的飞行轨迹。我写了这段代码,但似乎无法在图表上绘制出炮弹。我需要根据每个时间间隔来绘制炮弹。

from graphics import*
from math import sin, cos, radians

class Tracker:

    def __init__(self,window,objToTrack):
         self.objToTrack = objToTrack
         self.circ = Circle(Point(objToTrack.getX(), objToTrack.getY()), 2)
         self.circ.draw(window)

    def update(self):
         point = self.circ.getCenter()
         x = point.getX()
         y = point.getY()
        self.circ.move(self.objToTrack.getX() - x, self.objToTrack.getY() - y)




class Projectile:

    def __init__(self, angle, velocity, height):
         self.xpos = 0.0
         self.ypos = height
         theta = radians(angle)
         self.xvel = velocity * cos(theta)
         self.yvel = velocity * sin(theta)

    def update(self, time):
         self.xpos = self.xpos + time * self.xvel
         yvel1 = self.yvel - 9.8 * time
         self.ypos = self.ypos + time * (self.yvel + yvel1) / 2.0
         self.yvel = yvel1

    def getY(self):
         return self.ypos

    def getX(self):
         return self.xpos

    def getInputs():
         a = eval(input("Enter the launch angle (in degrees): "))
         v = eval(input("Enter the initial velocity (in meters/sec): "))
         h = eval(input("Enter the initial height (in meters): "))
         t = eval(input("Enter the time interval between position calculations: "))
         return a,v,h,t

    def main():
        angle, vel, h0, time = getInputs()
        cball = Projectile(angle, vel, h0)
        while cball.getY() >= 0:
           cball.update(time)        
        print("\nDistance traveled: {0:0.1f} meters.".format(cball.xpos))

       Tracker(GraphWin("Tracker",500,500),cball)




 if __name__ == "__main__": 
     main()

1 个回答

0

首先,考虑以下问题和提示:

  • Tracker.update() 什么时候会被调用?
  • 你的窗口是什么时候创建的?
  • 你什么时候真的在窗口上画了一个圆?
  • 看看 观察者模式

你的 Tracker 类没有收到关于它对象更新的通知。而且你是在炮弹飞行的模拟之后才创建 Tracker 和窗口。现在你调用 Tracker(GraphWin("Tracker",500,500),cball) 只会在炮弹的最终位置上进行一次绘制。

要绘制出曲线,你需要这样做:

def main():
    angle, vel, h0, time = getInputs()
    cball = Projectile(angle, vel, h0)

    win = GraphWin("Tracker",500,500,autoflush=False)
    while cball.getY() >= 0:
       cball.update(time)
       Tracker(win,cball)
    print("\nDistance traveled: {0:0.1f} meters.".format(cball.xpos))

    input("Ready to close? Type any key")
    win.close()

现在你在每次更新后创建一个 Tracker,这样就会在图形窗口上画一个圆。这会导致很多圆重叠在一起,从而绘制出曲线。不过,绘制的图像还是颠倒的,所以你需要再想想你的坐标系统。此外,要在 Tracker 对象外部创建窗口,否则一旦 Tracker 对象被删除,窗口就会关闭。

为了让炮弹动画能够正常运行,你需要修改你的 main() 函数,让 Tracker 知道发生了变化。对于更复杂的情况,观察者模式会很有用,但在这个情况下,只需在炮弹更新后调用 Tracker::update():

import time as sleeper
def main():
    angle, vel, h0, time = getInputs()
    cball = Projectile(angle, vel, h0)

    win = GraphWin("Tracker",500,500)
    win.setCoords(0, 0, 500, 500) #fixed coordinates

    tracker = Tracker(win,cball)
    while cball.getY() >= 0:
        sleeper.sleep(0.1) # wait 0.1 seconds for simple animation timing
        cball.update(time)
        tracker.update()
    print("\nDistance traveled: {0:0.1f} meters.".format(cball.xpos))

    input("Ready to close? Type any key") #keep the window open
    win.close()

撰写回答