获取pymunk旋转动力学体的更新坐标

问题描述

下面是一个旋转的动态Pymunk物体,其中有一个质量。动画开始播放后,有没有办法获取“ body_type”顶部水平部分的中点。最初,我感兴趣的动力学物体上的点具有坐标(400,500)。旋转开始后,如何打印相关点的更新坐标

import pymunk
import pymunk.pygame_util
import pygame

GRAY = (220,220,220)

width_mass=50
height_mass=50

pygame.init()
size = 800,600
screen = pygame.display.set_mode(size)
draw_options = pymunk.pygame_util.DrawOptions(screen)

space = pymunk.Space()
space.gravity = (0,-50)

pts = [(-27,-238.5),(27,238.5),(-27,238.5)]
body_type=pymunk.Body(body_type=pymunk.Body.KINEMATIC)  
body_type.position = (400,263.5)  
space.add(body_type)
for i in range(4):
    segment = pymunk.Segment(body_type,pts[i],pts[(i+1)%4],2)
    segment.elasticity = 0
    segment.friction=0
    space.add(segment)

body_type.angular_veLocity=1

body = pymunk.Body(mass=1,moment=100)
body.position = 400,400

mass = pymunk.poly.create_Box(body,(width_mass,height_mass))
mass.elasticity = 0
space.add(body,mass)

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
            #pygame.image.save(screen,'intro1.png')

    screen.fill(GRAY)
    space.debug_draw(draw_options)
    pygame.display.update()
    space.step(0.01)

解决方法

Body的当前位置存储在position属性中(例如space.bodies[0].position)。
PyGame使用左上角为(0,0)的坐标系。由于y轴通常指向上方,因此y轴需要反转(screen.get_height() - pos[1]),但是在PyGame坐标系中,y轴轴指向下方。

running = True
while running:
    # [...]

    # draw a dot in at the center of the bodies
    for body in space.bodies:
        pos = body.position
        pygame.draw.circle(screen,(255,0),(pos[0],screen.get_height()-pos[1]),7)

    pygame.display.update()
    space.step(0.01)

Body的当前角度存储在angle属性中(例如body_type.angle)。
可以通过将旋转的相对位置与绝对位置相加来计算点的当前位置。可以通过简单的Trigonometry计算旋转位置:

pos = abs_pos[0] + rel_dist * math.cos(angle),abs_pos[1] + rel_dist * math.sin(angle)

首先,您必须根据相对值Polar coordinates计算相对值Cartesian coordinates

rel_pos = (0,238.5)
rel_dist,rel_angle = math.hypot(*rel_pos),math.atan2(rel_pos[1],rel_pos[0])

将当前角度添加到极坐标角:

angle = rel_angle + body_type.angle

例如:

running = True
while running:
    # [...]

    abs_pos = body_type.position
    rel_pos = (0,238.5)
    rel_dist,rel_pos[0])
    
    angle = rel_angle + body_type.angle
    pos = abs_pos[0] + rel_dist * math.cos(angle),abs_pos[1] + rel_dist * math.sin(angle)
    pygame.draw.circle(screen,255,screen.get_height() - pos[1]),7)

    pygame.display.update()
    space.step(0.01)

最小示例:

import pymunk
import pymunk.pygame_util
import pygame
import math

GRAY = (220,220,220)
width_mass=50
height_mass=50
pygame.init()

size = 800,600
screen = pygame.display.set_mode(size)
draw_options = pymunk.pygame_util.DrawOptions(screen)

space = pymunk.Space()
space.gravity = (0,-50)

pts = [(-27,-238.5),(27,238.5),(-27,238.5)]
body_type=pymunk.Body(body_type=pymunk.Body.KINEMATIC)  
body_type.position = (400,263.5)  
space.add(body_type)
for i in range(4):
    segment = pymunk.Segment(body_type,pts[i],pts[(i+1)%4],2)
    segment.elasticity = 0
    segment.friction=0
    space.add(segment)

body_type.angular_velocity=0.5

body = pymunk.Body(mass=1,moment=100)
body.position = 400,400

mass = pymunk.Poly.create_box(body,(width_mass,height_mass))
mass.elasticity = 0
space.add(body,mass)

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
            #pygame.image.save(screen,'intro1.png')

    screen.fill(GRAY)
    space.debug_draw(draw_options)

    for body in space.bodies:
        pos = body.position
        pygame.draw.circle(screen,7)

    abs_pos = body_type.position
    rel_pos = (0,rel_pos[0])
    angle = rel_angle + body_type.angle
    print( body_type.position.angle)
    pos = abs_pos[0] + rel_dist * math.cos(angle),7)

    pygame.display.update()
    space.step(0.01)