change of impulse direction Pymunk (python)

Hi i would like to create a small drone simulator. Two engines on the left and right. I was based on examples from the pymunk library. But I have no idea how to add engine power to make it hit the point, i.e. make the object rotate. This can be done easily with the help of this library? Thank you for any help

import sys,math
import pygame
from pygame.locals import *
from pygame.color import *

import pymunk
from pymunk.vec2d import Vec2d
import pymunk.pygame_util

width, height = 690,400
fps = 60
dt = 1./fps
JUMP_HEIGHT = 16.*2

def main():

    ### PyGame init
    pygame.init()
    screen = pygame.display.set_mode((width,height))

    clock = pygame.time.Clock()
    running = True

    ### Physics stuff
    space = pymunk.Space()
    space.gravity = 0,-1000
    draw_options = pymunk.pygame_util.DrawOptions(screen)

    # box walls
    static = [ pymunk.Segment(space.static_body, (10, 50), (680, 50), 3)
                , pymunk.Segment(space.static_body, (680, 50), (680, 370), 3)
                , pymunk.Segment(space.static_body, (680, 370), (10, 370), 3)
                , pymunk.Segment(space.static_body, (10, 370), (10, 50), 3)
                ]

    for s in static:
        s.friction = 1.
        s.group = 1
    space.add(static)

    # player
    body = pymunk.Body(5, pymunk.inf)
    body.position = 100,100

    left = pymunk.Poly(body, [(-30,25), (0, 25), (0, 0), (-30, 0)] )
    right = pymunk.Poly(body, [(0,0), (0, 25), (30, 25), (30, 0)] )

    left.color = 46,25,1,46
    right.color = 1,25,1,25

    space.add(body, left, right)

    while running:

        for event in pygame.event.get():
            if event.type == QUIT or \
                event.type == KEYDOWN and (event.key in [K_ESCAPE, K_q]):
                running = False

            elif event.type == KEYDOWN and event.key == K_LEFT:
                # here is the problem
                jump_v = math.sqrt(2.0 * JUMP_HEIGHT * abs(space.gravity.y))
                power = max(min(jump_v, 1000), 10) * 1.5
                impulse = power * Vec2d(0, 3)
                impulse.rotate(body.angle - 45)
                body.apply_impulse_at_world_point(impulse, (0,0) )

            elif event.type == KEYDOWN and event.key == K_RIGHT:
                # here is the problem
                jump_v = math.sqrt(2.0 * JUMP_HEIGHT * abs(space.gravity.y))
                power = max(min(jump_v, 1000), 10) * 1.5
                impulse = power * Vec2d(0, 3)
                impulse.rotate(body.angle + 45)
                body.apply_impulse_at_world_point(impulse, (0,0) )

        ### Clear screen
        screen.fill(pygame.color.THECOLORS["black"])

        ### Helper lines
        for y in [50,100,150,200,250,300]:
            color = pygame.color.THECOLORS['darkgrey']
            pygame.draw.line(screen, color, (10,y), (680,y), 1)

        # ### Draw stuff
        space.debug_draw(draw_options)

        pygame.display.flip()

        ### Update physics
        space.step(dt)

        clock.tick(fps)

if __name__ == '__main__':
    sys.exit(main())

1 answer

  • answered 2020-03-25 18:32 Ray B

    Your main issue is that your Body has infinite moment, which means that it can't rotate. Try creating the Body as something like:

    body = pymunk.Body(5, 500)
    

    You also need to apply the impulse somewhere that makes sense. Try:

    body.apply_impulse_at_local_point(impulse, (5, 0))
    

    and:

    body.apply_impulse_at_local_point(impulse, (-5, 0))
    

    for left and right.