Permalink
Cannot retrieve contributors at this time
"""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) |