I am working with Pygame and Pymunk and my ball which is done with pymunk won’t stop rolling I think it has something to do with the friction but i do not know. Please help me. Thanks already. Is there a way to maybe set a rotation speed(but i think this would not fix it either since it is just glitching if i set the mass high up, and it still moves). I do not really know what to write here now since this is my first Question but just ask me and I will respond soon. Also I know that there are not that many people that have experience with Pymunk but I hope I find some!
Here is my code:
import pymunk
import math
import pymunk.pygame_util
pygame.init()
pygame.display.init()
WIDTH, HEIGHT = 1500, 960
BLACK = (0, 0, 0)
window = pygame.display.set_mode((WIDTH, HEIGHT))
trys_left = 3
font1 = pygame.font.SysFont(None, 25)
font = pygame.font.Font('C:\\Users\\Admin\\Downloads\\Decay-M5RB.ttf', 10)
run = True
RED = (255, 0, 0)
def message_to_screen(msg, color):
screen_text = font1.render(msg, True, color)
window.blit(screen_text, (30, 30))
def message_to_screen2(msg, color):
screen_text = font.render(msg, True, color)
window.blit(screen_text, (20, 200))
def message_to_screen3(msg, color):
screen_text = font.render(msg, True, color)
window.blit(screen_text, (20, 200))
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, line):
global run
window.fill("white")
message_to_screen(f"You got: {trys_left} tries", RED)
message_to_screen2(f"You can only place balls in this field", RED)
#if run == False:
# message_to_screen3()
if line:
pygame.draw.line(window, "black", line[0], line[1], 3)
pygame.draw.rect(window, "black", pygame.Rect(0, 0, 300, 200),1)
#pygame.draw.line(window, "black", (300, 0), (300, 200))
#pygame.draw.line(window, "black", (0, 200), (300, 200))
space.debug_draw(draw_options)
pygame.display.update()
def level_rects(space, width, height):
rects = [
[(width / 3, height - 300), (width, 5)],
[(width / 1, height - 200), (width / 1, 5)]
]
for pos, size in rects:
body = pymunk.Body(body_type=pymunk.Body.STATIC)
body.position = pos
shape = pymunk.Poly.create_box(body, size)
shape.color = (255, 0, 0, 100)
shape.elasticity = 0.1
shape.friction = 2
space.add(body, shape)
def create_boundaries(space, width, height):
rects = [
[(width / 4, height - 10), (width, 20)], [(width / 2, 10), (width, 20)], [(10, height / 2), (20, height)], [(width - 10, height / 2), (20, height)]
]
for pos, size in rects:
body = pymunk.Body(body_type=pymunk.Body.STATIC)
body.position = pos
shape = pymunk.Poly.create_box(body, size)
shape.elasticity = 0.8
shape.friction = 0.5
space.add(body, shape)
def create_structure(space, width, height):
BROWN = (139, 69, 19,100)
CYAN = (0, 100, 100, 100)
rects = [
[(300, height - 120), (40, 200), CYAN, 100],
[(600, height - 120), (40, 200), BROWN, 100],
[(450, height - 240), (340, 40), BROWN, 150],
#[(1000, height - 600), (340, 40), BROWN, 150]#dieses Stäbchen
]
for pos, size, color , mass in rects:
body = pymunk.Body()
body.position = pos
shape = pymunk.Poly.create_box(body, size, radius = 2)
shape.color = color
shape.mass = mass
shape.collision_type = 2
shape.elasticity = 0.4
shape.friction = 0.4
space.add(body, shape)
print("pos is: ",pos )
print("size is: " ,size)
print("color is: " , color)
print("mass is: " , mass)
def create_swinging_ball(space):
rotation_center_body = pymunk.Body(body_type=pymunk.Body.STATIC)
rotation_center_body.position = (500, 170)
body = pymunk.Body()
body.position = (500, 200 )
line = pymunk.Segment(body, (0, 0), (255, 0), 5)
circle = pymunk.Circle(body, 40, (255, 0))
line.friction = 1
circle.friction = 1
line.mass = 8
circle.mass = 30
circle.elasticity = 0.95
rotation_center_joint = pymunk.PinJoint(body, rotation_center_body, (0, 0))
space.add(circle, line, body, rotation_center_joint)
def create_ball(space, radius, mass, pos):
body = pymunk.Body(body_type=pymunk.Body.STATIC)
body.position = pos
shape = pymunk.Circle(body, radius)
shape.mass = mass
shape.collision_type = 1
shape.elasticity = 0.9
shape.friction = 0.4
shape.color = (255, 0, 0, 100)
space.add(body, shape)
global trys_left
trys_left -= 1
#if body.is_sleeping:
# pygame.quit()
return shape # warum?
def collide(arbiter, space, data):
global run
run = False
print("GG U WON")
def run(window, width, height):
global run
run = True
clock = pygame.time.Clock()
fps = 60
dt = 1 / fps
space = pymunk.Space()
space.gravity = (0, 981)
create_boundaries(space, width, height)
create_structure(space, width, height)
create_swinging_ball(space)
level_rects(space, width, height)
handler = space.add_collision_handler(1, 2)
handler.separate = collide
draw_options = pymunk.pygame_util.DrawOptions(window)
#ball = create_ball(space, 30, 10)
pressed_pos = None
ball = None
while run:
pygame.display.update()
line = None
if ball and pressed_pos:
line = [pressed_pos, pygame.mouse.get_pos()]
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
break
if event.type == pygame.MOUSEBUTTONDOWN:
if not ball:
pressed_pos = pygame.mouse.get_pos()
#if pressed_pos[0] <= 300 or pressed_pos[1] <= 200: keine ahnung was das ist
#if not pressed_pos[0] < 300 or not pressed_pos[1] < 200:
#if pressed_pos[0] >= 300 or pressed_pos[1] >= 200:
if pressed_pos[0] <= 300 and pressed_pos[1] <= 200:
#geht nicht zeichen
ball = create_ball(space, 30, 10, pressed_pos)
#and is only true when both are true
#or is true when at least one is true
#create_ball(space, 30, 10, pressed_pos)
if trys_left == -1:
return False
#return True
elif pressed_pos:
ball.body.body_type=pymunk.Body.DYNAMIC
angle = calculate_angle(*line)
force = calculate_distance(*line) * 60
fx = math.cos(angle) * force
fy = math.sin(angle) * force
ball.body.apply_impulse_at_local_point((fx, fy), (0, 0))
pressed_pos = None
else:
space.remove(ball, ball.body)
ball = None
draw(space, window, draw_options, line)
space.step(dt)
clock.tick(fps)
pygame.quit()
if __name__ == "__main__":
run(window, WIDTH, HEIGHT)