传送带运动学python

发布于 2025-02-07 21:33:44 字数 3063 浏览 3 评论 0原文

我正在尝试为带有对象的传送带创建一个模拟,以了解行为的方式。我正在玩耍,但在传送带的功能上挣扎。目前,我尝试在物体与皮带发生碰撞时将冲动或速度添加到这些物体时,但我还没有得到很好的效果。但是,这只是我尝试如何将脉冲脉冲给对象的一个​​示例,但是,每当我添加一个新对象(使用鼠标事件)时,新的脉冲仅适用于最新对象。

import pygame
import pymunk
import pymunk.pygame_util
import math
import sys

pygame.init()
space = pymunk.Space()
WIDTH, HEIGHT = 1920,800
mu = 2

window = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Kinematics approximation ")

def calculate_distance(p1, p2):
    return math.sqrt((p2[1] - p1[1])**2 + (p2[0] - p1[0])**2)

def calculate_angle(p1, p2):
    return math.atan2(p2[1] - p1[1], p2[0] - p1[0])

def draw(space, window,draw_options):
    window.fill("white")
    space.debug_draw(draw_options) 
    pygame.display.update()
    



def create_belt(space):
    belts = [
        [(0,500), (600,500), 5],
        [(600,500), (800,400), 6],
        [(800,400), (WIDTH,400), 6]
    ]

    for pos_1, pos_2, width in belts:
        shape = pymunk.Segment(space.static_body,pos_1, pos_2, width) 
        shape.body.position = 0,0
        shape.friction = mu
        space.add(shape)





def create_object(space, mass, pos):
    body = pymunk.Body(body_type = pymunk.Body.DYNAMIC)
    body.position = pos
    shape = pymunk.Poly.create_box(body, size = (20,10))
    shape.mass = mass
    shape.color = (255,0,0, 100)
    shape.body.friction = mu
    #shape.body.velocity = (80,0)
    space.add(body,shape)
    return shape





def run(window, width, height):
    run = True
    clock = pygame.time.Clock()
    fps = 240
    dt = 1/fps

    space = pymunk.Space()
    space.gravity = (0,981)

 
    create_belt(space)





    def coll_begin(arbiter, space, data):
        print(arbiter)
        #angle = calculate_angle(*)
        #force = calculate_distance(*line) * 50
        #fx = math.cos(angle) * force
        #fy = math.sin(angle) * force

        return True

    def coll_pre(arbiter, space, data):
        for object in objects:
               object.body.apply_impulse_at_local_point((12, 0),(0,0))
        return True

    def coll_post(arbiter, space, data):
        #print(velocity_at_local_point)
        pass

    def coll_separate(arbiter, space, data):
        pass

    handler = space.add_default_collision_handler()
    handler.begin = coll_begin
    handler.pre_solve = coll_pre
    handler.post_solve = coll_post
    handler.separate = coll_separate
    

    draw_options = pymunk.pygame_util.DrawOptions(window)

    pressed_pos = None

    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()    
        
            if event.type == pygame.MOUSEBUTTONDOWN:
                pressed_pos = pygame.mouse.get_pos()
                objects = []
                objects.append(create_object(space,10, pressed_pos))
                

        draw(space,window, draw_options)
        space.step(dt)
        clock.tick(fps)
        

    pygame.quit()
    sys.exit()



if __name__ == "__main__":
    run(window, WIDTH, HEIGHT)

I'm trying to create a simulation for a conveyor belt with objects on it, to see how the behaviour would be. I am playing around but struggling with the functionality of the conveyor belt. Right now, I try to add impulse or velocity to the objects whenever they have a collision with the belt, but I have yet to get a good result. Here is just an example of how I tried to give impulse to the objects, however, whenever I add a new object (with mouse event), the new impulse only applies to the newest object.

import pygame
import pymunk
import pymunk.pygame_util
import math
import sys

pygame.init()
space = pymunk.Space()
WIDTH, HEIGHT = 1920,800
mu = 2

window = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Kinematics approximation ")

def calculate_distance(p1, p2):
    return math.sqrt((p2[1] - p1[1])**2 + (p2[0] - p1[0])**2)

def calculate_angle(p1, p2):
    return math.atan2(p2[1] - p1[1], p2[0] - p1[0])

def draw(space, window,draw_options):
    window.fill("white")
    space.debug_draw(draw_options) 
    pygame.display.update()
    



def create_belt(space):
    belts = [
        [(0,500), (600,500), 5],
        [(600,500), (800,400), 6],
        [(800,400), (WIDTH,400), 6]
    ]

    for pos_1, pos_2, width in belts:
        shape = pymunk.Segment(space.static_body,pos_1, pos_2, width) 
        shape.body.position = 0,0
        shape.friction = mu
        space.add(shape)





def create_object(space, mass, pos):
    body = pymunk.Body(body_type = pymunk.Body.DYNAMIC)
    body.position = pos
    shape = pymunk.Poly.create_box(body, size = (20,10))
    shape.mass = mass
    shape.color = (255,0,0, 100)
    shape.body.friction = mu
    #shape.body.velocity = (80,0)
    space.add(body,shape)
    return shape





def run(window, width, height):
    run = True
    clock = pygame.time.Clock()
    fps = 240
    dt = 1/fps

    space = pymunk.Space()
    space.gravity = (0,981)

 
    create_belt(space)





    def coll_begin(arbiter, space, data):
        print(arbiter)
        #angle = calculate_angle(*)
        #force = calculate_distance(*line) * 50
        #fx = math.cos(angle) * force
        #fy = math.sin(angle) * force

        return True

    def coll_pre(arbiter, space, data):
        for object in objects:
               object.body.apply_impulse_at_local_point((12, 0),(0,0))
        return True

    def coll_post(arbiter, space, data):
        #print(velocity_at_local_point)
        pass

    def coll_separate(arbiter, space, data):
        pass

    handler = space.add_default_collision_handler()
    handler.begin = coll_begin
    handler.pre_solve = coll_pre
    handler.post_solve = coll_post
    handler.separate = coll_separate
    

    draw_options = pymunk.pygame_util.DrawOptions(window)

    pressed_pos = None

    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()    
        
            if event.type == pygame.MOUSEBUTTONDOWN:
                pressed_pos = pygame.mouse.get_pos()
                objects = []
                objects.append(create_object(space,10, pressed_pos))
                

        draw(space,window, draw_options)
        space.step(dt)
        clock.tick(fps)
        

    pygame.quit()
    sys.exit()



if __name__ == "__main__":
    run(window, WIDTH, HEIGHT)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

听不够的曲调 2025-02-14 21:33:44

代码中有两个问题:

首先,每次创建新对象时,您都在重置对象列表。这意味着,当您将脉冲应用于对象列表中的所有对象时,仅将脉冲应用于创建的最后一个对象。通过将Objects = []行从游戏循环中移出,可以轻松修复这一点。

修复此操作后,您可能已经注意到,无论是否触摸皮带,所有物体都会发生冲动。这是由以下内容引起的:每当任何物体与输送带碰撞时,您都会向所有物体应用脉冲。这会导致所有物体向前移动,而不仅仅是与传送带相撞的物体。

您可以使用arbiter.shapes元组来修复上述两个错误,该元素作为参数提供给coll_pre函数的参数。该元组包含两个对方碰撞的对象,因此您要移动的对象。第二个对象是要移动的新对象。此更改还使对象列表毫无用处,因为您不再使用它来应用脉冲。

这是代码:

def coll_pre(arbiter, space, data):
    print(arbiter)
    arbiter.shapes[1].body.apply_impulse_at_local_point((12, 0),(0,0))
    return True

我还建议增加给出的冲动,因为现在这些物体慢慢传播以抵抗皮带倾斜部分的重力。 40的价值对我有用。

There are two problems in your code:

First, you are resetting the objects list every time a new object is created. This means that when you apply impulse to all objects in the objects list, only impulse is applied to the last object created. This can be easily fixed by moving the objects = [] line out of the game loop.

After fixing this, you might have noticed that all objects are getting impulse, whether they touch the belt or not. This is caused by the following: whenever any object is colliding with the conveyor belt, you apply an impulse to all objects. This causes all objects to move forward, not only the one that collides with the conveyor belt.

You can fix the two above errors using the Arbiter.shapes tuple that is provided as an argument to the coll_pre function. This tuple contains the two objects colliding with eachother, and thus also the object you want to move. The second object is the new object you want to move. This change also makes the objects list useless, as you don't use it anymore to apply the impulse.

Here's the code:

def coll_pre(arbiter, space, data):
    print(arbiter)
    arbiter.shapes[1].body.apply_impulse_at_local_point((12, 0),(0,0))
    return True

I would also recommend increasing the impulse given, as now the objects travel to slowly to resist to gravity on the inclined part of the belt. A value of 40 worked for me.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文