Skip to content
Permalink
master
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time
170 lines (137 sloc) 5.3 KB
"""This example lets you dynamically create static walls and dynamic balls
"""
__docformat__ = "reStructuredText"
import pygame
import pymunk
from pymunk import Vec2d
X, Y = 0, 1
### Physics collision types
COLLTYPE_DEFAULT = 0
COLLTYPE_MOUSE = 1
COLLTYPE_BALL = 2
def flipy(y):
"""Small hack to convert chipmunk physics to pygame coordinates"""
return -y + 600
def mouse_coll_func(arbiter, space, data):
"""Simple callback that increases the radius of circles touching the mouse"""
s1, s2 = arbiter.shapes
s2.unsafe_set_radius(s2.radius + 0.15)
return False
def main():
pygame.init()
screen = pygame.display.set_mode((600, 600))
clock = pygame.time.Clock()
running = True
### Physics stuff
space = pymunk.Space()
space.gravity = 0.0, -900.0
## Balls
balls = []
### Mouse
mouse_body = pymunk.Body(body_type=pymunk.Body.KINEMATIC)
mouse_shape = pymunk.Circle(mouse_body, 3, (0, 0))
mouse_shape.collision_type = COLLTYPE_MOUSE
space.add(mouse_body, mouse_shape)
space.add_collision_handler(
COLLTYPE_MOUSE, COLLTYPE_BALL
).pre_solve = mouse_coll_func
### Static line
line_point1 = None
static_lines = []
run_physics = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
running = False
elif event.type == pygame.KEYDOWN and event.key == pygame.K_p:
pygame.image.save(screen, "balls_and_lines.png")
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
p = event.pos[X], flipy(event.pos[Y])
body = pymunk.Body(10, 100)
body.position = p
shape = pymunk.Circle(body, 10, (0, 0))
shape.friction = 0.5
shape.collision_type = COLLTYPE_BALL
space.add(body, shape)
balls.append(shape)
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 3:
if line_point1 is None:
line_point1 = Vec2d(event.pos[X], flipy(event.pos[Y]))
elif event.type == pygame.MOUSEBUTTONUP and event.button == 3:
if line_point1 is not None:
line_point2 = Vec2d(event.pos[X], flipy(event.pos[Y]))
shape = pymunk.Segment(
space.static_body, line_point1, line_point2, 0.0
)
shape.friction = 0.99
space.add(shape)
static_lines.append(shape)
line_point1 = None
elif event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
run_physics = not run_physics
p = pygame.mouse.get_pos()
mouse_pos = Vec2d(p[X], flipy(p[Y]))
mouse_body.position = mouse_pos
if pygame.key.get_mods() & pygame.KMOD_SHIFT and pygame.mouse.get_pressed()[0]:
body = pymunk.Body(10, 10)
body.position = mouse_pos
shape = pymunk.Circle(body, 10, (0, 0))
shape.collision_type = COLLTYPE_BALL
space.add(body, shape)
balls.append(shape)
### Update physics
if run_physics:
dt = 1.0 / 60.0
for x in range(1):
space.step(dt)
### Draw stuff
screen.fill(pygame.Color("white"))
# Display some text
font = pygame.font.Font(None, 16)
text = """LMB: Create ball
LMB + Shift: Create many balls
RMB: Drag to create wall, release to finish
Space: Pause physics simulation"""
y = 5
for line in text.splitlines():
text = font.render(line, True, pygame.Color("black"))
screen.blit(text, (5, y))
y += 10
for ball in balls:
r = ball.radius
v = ball.body.position
rot = ball.body.rotation_vector
p = int(v.x), int(flipy(v.y))
p2 = p + Vec2d(rot.x, -rot.y) * r * 0.9
p2 = int(p2.x), int(p2.y)
pygame.draw.circle(screen, pygame.Color("blue"), p, int(r), 2)
pygame.draw.line(screen, pygame.Color("red"), p, p2)
if line_point1 is not None:
p1 = int(line_point1.x), int(flipy(line_point1.y))
p2 = mouse_pos.x, flipy(mouse_pos.y)
pygame.draw.lines(screen, pygame.Color("black"), False, [p1, p2])
for line in static_lines:
body = line.body
pv1 = body.position + line.a.rotated(body.angle)
pv2 = body.position + line.b.rotated(body.angle)
p1 = int(pv1.x), int(flipy(pv1.y))
p2 = int(pv2.x), int(flipy(pv2.y))
pygame.draw.lines(screen, pygame.Color("lightgray"), False, [p1, p2])
### Flip screen
pygame.display.flip()
clock.tick(50)
pygame.display.set_caption("fps: " + str(clock.get_fps()))
if __name__ == "__main__":
doprof = 0
if not doprof:
main()
else:
import cProfile
import pstats
prof = cProfile.run("main()", "profile.prof")
stats = pstats.Stats("profile.prof")
stats.strip_dirs()
stats.sort_stats("cumulative", "time", "calls")
stats.print_stats(30)