""" 这是一个动画,它不断地产生物理弹球,弹球掉落在由两段线条组成的L形状上会有反弹效果。
"""
import random
import pygame
from pygame.key import *
from pygame.locals import *
from pygame.color import *
import pymunk
import pymunk.pygame_util
class BouncyBalls(object):
"""
这个类实现一个简单的平台上有着随机掉落的弹球场景。
"""
def __init__(self):
self._space = pymunk.Space() # 新建重力空间
self._space.gravity = (0.0, -900.0) # 重力加速度
self._dt = 1.0 / 60.0 # 这里应该是60分之一秒更新一次重力空间
# 屏幕每一帧执行的物理刷新次数
self._physics_steps_per_frame = 1
# pygame 初始化
pygame.init()
self._screen = pygame.display.set_mode((600, 600))
self._clock = pygame.time.Clock()
self._draw_options = pymunk.pygame_util.DrawOptions(self._screen)
print(self._draw_options)
# 添加棍子,弹球碰到它会反弹
self._add_static_scenery()
# 所有的球在这个列表中
self._balls = []
# 主循环逻辑变量与产生球的时隔
self._running = True
self._ticks_to_next_ball = 10
def run(self):
"""
这里是场景的主要循环
"""
while self._running:
# 每帧执行几次物理计算过程?
for x in range(self._physics_steps_per_frame):
self._space.step(self._dt)
self._process_events()
self._update_balls()
self._clear_screen()
self._draw_objects()
pygame.display.flip()
# Delay fixed time between frames
self._clock.tick(50)
pygame.display.set_caption("fps: " + str(self._clock.get_fps()))
pygame.quit()
def _add_static_scenery(self):
"""
创建静止不动的两根棍子
"""
static_body = self._space.static_body
static_lines = [pymunk.Segment(static_body, (111.0, 280.0), (407.0, 246.0), 0.0),
pymunk.Segment(static_body, (407.0, 246.0), (407.0, 343.0), 0.0)]
for line in static_lines:
line.elasticity = 0.95
line.friction = 0.9
self._space.add(static_lines)
def _process_events(self):
"""
Handle game and events like keyboard input. Call once per frame only.
:return: None
"""
for event in pygame.event.get():
if event.type == QUIT:
self._running = False
elif event.type == KEYDOWN and event.key == K_ESCAPE:
self._running = False
elif event.type == KEYDOWN and event.key == K_p:
pygame.image.save(self._screen, "bouncing_balls.png")
def _update_balls(self):
"""
每帧调用一次,创建球或者移出y坐标小于100的弹球。Create/remove balls as necessary. Call once per frame only.
:return: None
"""
self._ticks_to_next_ball -= 1
if self._ticks_to_next_ball <= 0:
self._create_ball()
self._ticks_to_next_ball = 100
# Remove balls that fall below 100 vertically
balls_to_remove = [ball for ball in self._balls if ball.body.position.y < 100]
for ball in balls_to_remove:
self._space.remove(ball, ball.body)
self._balls.remove(ball)
def _create_ball(self):
"""
创建一个物理 弹球
"""
mass = 10
radius = 25
inertia = pymunk.moment_for_circle(mass, 0, radius, (0, 0))
body = pymunk.Body(mass, inertia)
x = random.randint(115, 350)
body.position = x, 400
shape = pymunk.Circle(body, radius, (0, 0))
shape.elasticity = 0.95 # 弹性系数
shape.friction = 0.9 # 摩擦系数
self._space.add(body, shape)
self._balls.append(shape)
def _clear_screen(self):
"""
清屏为白色
"""
self._screen.fill(THECOLORS["white"])
def _draw_objects(self):
"""
画各个物体
"""
self._space.debug_draw(self._draw_options)
if __name__ == '__main__':
game = BouncyBalls()
game.run()
以下是函数实现的,不过当小球离开屏幕时并没有把它删除,并且左边掉落的小球为什么会有瞬移现象出现呢?
import sys, random
import pygame
from pygame.locals import *
import pymunk
import pymunk.pygame_util
def add_static_L(space):
body = pymunk.Body(body_type = pymunk.Body.STATIC) # 增加静态实体
body.position = (300, 300)
shape1 = pymunk.Segment(body, (-150, 0), (255, 0), 5) # 此坐标是相对于(300,300)为原点的
shape1.elasticity = 0.95 # 弹性系数
shape1.friction = 0.9 # 摩擦系数
shape2 = pymunk.Segment(body, (-150, 0), (-150, 50), 5) # y坐标相反
shape2.elasticity = 0.95 # 弹性系数
shape2.friction = 0.9 # 摩擦系数
space.add(shape1, shape2) # 增加到物理空间
return shape1,shape2
def add_ball(space):
mass = 1
radius = 14
moment = pymunk.moment_for_circle(mass, 0, radius) # 求一定质量和半径的小球的转动惯量,返回浮点数
body = pymunk.Body(mass, moment) # 新建刚体
x = random.randint(120, 380) # 随机x坐标
body.position = x, 550 # 定位
shape = pymunk.Circle(body, radius) # 设形状
shape.elasticity = 0.95 # 弹性系数
shape.friction = 0.9 # 摩擦系数
space.add(body, shape) # 放到物理空间
return shape
def main():
pygame.init()
screen = pygame.display.set_mode((600, 600))
pygame.display.set_caption("自由落体小球")
clock = pygame.time.Clock()
space = pymunk.Space()
space.gravity = (0.0, -900.0)
lines = add_static_L(space)
balls = []
draw_options = pymunk.pygame_util.DrawOptions(screen) # 设定space内物体的渲染面
ticks_to_next_ball = 10
running = True
while running:
for event in pygame.event.get():
if event.type in( QUIT,KEYDOWN,K_ESCAPE):
running = False
break
ticks_to_next_ball -= 1
if ticks_to_next_ball <= 0:
ticks_to_next_ball = 25
ball_shape = add_ball(space)
balls.append(ball_shape)
space.step(1/50.0)
screen.fill((255,255,255))
space.debug_draw(draw_options)
pygame.display.flip()
clock.tick(50)
pygame.quit()
if __name__ == '__main__':
main()

