1

我创建了一个小示例程序,我使用 pymunk 来做物理和 tkinter 来做 GUI 的东西(因为我已经放弃尝试让 pygame 安装在我的 Mac 上......)

我让它在单个球被创建、掉落和从地板上反弹的地方工作。如果我倾斜地板,它会开始正确地向左或向右弹跳。

我无法弄清楚的是如何最初对球施加力,使其初始速度向右。

我在下面包括我的代码。这可能是非常简单的事情,但我不是物理学家,对时刻等一无所知。

谢谢。

维克

"""Simple example that bounces one ball against a floor.
The BallPhysics class defines the "model".  The Ball class is the "view".

@author: Victor Norman
"""

from tkinter import *
import pymunk
import pymunk.util
from pymunk import Vec2d
import math, sys, random


class Ball:

    RADIUS = 10

    def __init__(self, window):
        self._window = window
        self._window.title("Bouncing Ball with pymunk physics")

        self._model = BallPhysics()

        self._width = 400

        self._canvas = Canvas(self._window, bg='black',
                              width=self._width, height=self._width)
        self._canvas.pack()

        self._render()

    def _render(self):

        self._model.next_step()
        x, y = self._model.get_xy_for_ball()

        # subtract y values from self._width because y increases from 0 downward.
        self._canvas.create_oval(x - self.RADIUS, self._width - (y - self.RADIUS),
                                 x + self.RADIUS, self._width - (y + self.RADIUS),
                                 fill = 'white')
        self._canvas.after(20, self._render)


class BallPhysics:
    def __init__(self):

        self._space = pymunk.Space()
        self._space.gravity = (0.0, -900.0)

        self._balls = []

        mass = 10
        inertia = pymunk.moment_for_circle(mass, 0, Ball.RADIUS, (0, 0))
        body = pymunk.Body(mass, inertia)
        x = random.randint(50, 350)
        body.position = x, 400
        shape = pymunk.Circle(body, Ball.RADIUS, Vec2d(0,0))
        shape.elasticity = 0.9
        self._space.add(body, shape)
        self._balls.append(shape)

        # floor
        floor = pymunk.Segment(self._space.static_body, (0.0, 10.0), (400.0, 10.0), 1.0)
        floor.friction = 1.0
        floor.elasticity = 0.9
        self._space.add(floor)


    def next_step(self):
        # Remove balls that are below the bottom.
        balls_to_remove = []
        for ball in self._balls:
            if ball.body.position.y < 0:
                balls_to_remove.append(ball)
        for ball in balls_to_remove:
            self._space.remove(ball, ball.body)
            self._balls.remove(ball)

        if len(self._balls) >= 1:
            v = self._balls[0].body.position
            print("point = %.2f, %.2f" % (v.x, v.y))

        self._space.step(1 / 50)

    def get_xy_for_ball(self):
        ball_num = 0
        return (self._balls[ball_num].body.position.x,
                self._balls[ball_num].body.position.y)


main = Tk()
app = Ball(main)
main.mainloop()
4

1 回答 1

2

您可以在要推动的身体上使用body.apply_impulse_at_local_point(或)。*at_world_point此处描述了 API:http: //www.pymunk.org/en/latest/pymunk.html#pymunk.Body.apply_impulse_at_local_point

因此,在您的代码中,您可以body.apply_impulse_at_local_point((10000,0))在将 body 位置设置为x,400. 请注意,您需要修改冲动的强度以获得您想要的效果。通常我会在我希望它推动的方向上创建一个长度为 1 的向量,然后将它与我想要的脉冲相乘。像这样:body.apply_impulse_at_local_point(10000 * Vec2d(1,0))。然后,例如,可以轻松地稍微向上瞄准。

此示例包括使用应用脉冲的射击球:https ://github.com/viblo/pymunk/blob/master/examples/box2d_vertical_stack.py

于 2017-11-16T16:19:26.993 回答