Pymunk make box slowly push up from one of its corners

69 Views Asked by At

I have this pymunk universe. How can I make the box slowly push up from one of its corners with a set intensity for a set amount of time? (like pushes up with 50% effort (or something like that) for 2-3ish seconds?)

import pygame
import pymunk
import pymunk.pygame_util
import math

pygame.init()


WIDTH, HEIGHT = 1280, 720
window = pygame.display.set_mode((WIDTH, HEIGHT))

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

def create_invisible_border(space, width, height, collision_type, friction=0.4, elasticity=0.9, thickness=100):
    body = pymunk.Body(body_type=pymunk.Body.STATIC)
    body.position = (width/2, height/2)
    space.add(body)
    
    top_border = pymunk.Segment(body, (-width/2, height/2 + thickness), (width/2, height/2 + thickness), thickness)
    bottom_border = pymunk.Segment(body, (-width/2, -height/2 - thickness), (width/2, -height/2 - thickness), thickness)
    left_border = pymunk.Segment(body, (-width/2 - thickness, height/2), (-width/2 - thickness, -height/2), thickness)
    right_border = pymunk.Segment(body, (width/2 + thickness, height/2), (width/2 + thickness, -height/2), thickness)

    top_border.collision_type = collision_type
    bottom_border.collision_type = collision_type
    left_border.collision_type = collision_type
    right_border.collision_type = collision_type

    top_border.friction = friction
    bottom_border.friction = friction
    left_border.friction = friction
    right_border.friction = friction

    top_border.elasticity = elasticity
    bottom_border.elasticity = elasticity
    left_border.elasticity = elasticity
    right_border.elasticity = elasticity
    
    space.add(top_border, bottom_border, left_border, right_border)

def create_static_circle(space, x_pos, y_pos, collision_type, radius):
    body = pymunk.Body(body_type=pymunk.Body.STATIC)
    body.position = x_pos, y_pos
    space.add(body)
    shape = pymunk.Circle(body, radius)
    shape.collision_type = collision_type
    space.add(shape)

    return body

def create_object(space, mass, size, x, y, collision_type, friction = 0.4, elasticity = 0.9):
    moment = pymunk.moment_for_box(mass, size)
    body = pymunk.Body(mass, moment)
    body.position = x, y
    shape = pymunk.Poly.create_box(body, size)
    shape.elasticity = elasticity
    shape.friction = friction
    shape.collision_type = collision_type
    space.add(body, shape)

    return body


def run(window, width, height):
    run = True
    clock = pygame.time.Clock()
    fps = 60
    dt = 1/fps
    space = pymunk.Space()
    space.gravity = (0, 981)

    create_invisible_border(space, width, height, 2)
    create_static_circle(space, 1050, 160, 3, 25)
    object = create_object(space, 1, (100, 100), 300, 300, 1, elasticity = 0.2)

    draw_options = pymunk.pygame_util.DrawOptions(window)
    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                break
        draw(space, window, draw_options)
        space.step(dt)
        clock.tick(fps)
    pygame.quit()

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

I tried playing with impulses and came to this code, but it is nothing like how I want it to work, though I think it is a step in the right direction.

def jump(body, angle, strength):
    x = strength * math.cos(math.radians(angle))
    y = strength * math.sin(math.radians(angle))
    body.apply_impulse_at_local_point((x, y))

def jump_if_collided(arbiter, space, data, body, degrees, intensity):
    if arbiter.shapes[0].collision_type == 1 and arbiter.shapes[1].collision_type == 2:
        jump(body, degrees, intensity)
    return True

Then, this was called in the run function

space.add_collision_handler(1, 2).begin = lambda arbiter, space, data: jump_if_collided(arbiter, space, data, object, 135, 1000)
0

There are 0 best solutions below