Pymunk:是一個易於使用的pythonic 2d物理庫

1 說明:

=====

1.1 中英文介紹:

Pymunk is a easy-to-use pythonic 2d physics library

pymunk是一個易於使用的pythonic 2d物理庫

1.2 多基於pygame和pyglet的動畫。

1.3 官網示意圖:

Pymunk:是一個易於使用的pythonic 2d物理庫

圖1:index_video.gif,可以實現

2 準備:

=====

2.1 官網:

<code>http://www.pymunk.org/en/latest/
https://pypi.org/project/pymunk/
https://github.com/viblo/pymunk/<code>

2.2 環境:

華為筆記本電腦、深度deepin-linux操作系統、谷歌瀏覽器、python3.8和微軟vscode編輯器。

2.3 安裝:

<code>pip install pymunk
#本機安裝,且推薦國內源安裝
sudo pip3.8 install pymunk -i https://mirrors.aliyun.com/pypi/simple/<code>

3 官方example:

Pymunk:是一個易於使用的pythonic 2d物理庫

arrow


Pymunk:是一個易於使用的pythonic 2d物理庫

bouncing_balls


Pymunk:是一個易於使用的pythonic 2d物理庫

Pymunk:是一個易於使用的pythonic 2d物理庫


Pymunk:是一個易於使用的pythonic 2d物理庫

4 拿官網的動畫gif來講解:

======================

4.1 圖1:index_video.gif,也可以實現,代碼量太多了,省略,屬於example。

4.2 蜘蛛網:spiderweb.py對代碼進行修改,註釋,bug改進。

Pymunk:是一個易於使用的pythonic 2d物理庫

5 spiderweb.py代碼:

===============

提前看看效果圖:

Pymunk:是一個易於使用的pythonic 2d物理庫


5.1 第1步:導入模塊

<code>import math, random
import pyglet
import pymunk
from pymunk.vec2d import Vec2d/<code>

5.2 第2步:初始化參數設定

<code>config = pyglet.gl.Config(sample_buffers=1, samples=2, double_buffer=True)
window = pyglet.window.Window(config=config, vsync = False,
    #窗口大小和標題名設定
    width=800,
    height=800,
    caption="spiderweb",
    resizable=True)

#pymunk物理參數設定
space = pymunk.Space()
space.gravity = 0,-900
space.damping = .999
#中心點座標
c = Vec2d(window.width /2., window.height / 2.)        
        
#WEB參數
web_group = 1
bs = []
dist = .3

cb = pymunk.Body(1,1)
cb.position = c  #位置中心點座標
s = pymunk.Circle(cb, 15) # to have something to grab
s.filter = pymunk.ShapeFilter(group = web_group)
s.ignore_draw = True
space.add(cb, s)/<code>

5.3 第3步:織網

<code>#generate each crossing in the net
for x in range(0,101):
    b = pymunk.Body(1, 1)
    v = Vec2d.unit()
    v.angle_degrees = x*18
    scale = window.height / 2. / 6. * .5
    
    dist += 1/18. 
    dist = dist ** 1.005
    
    offset = 0
    offset = [0.0, -0.80, -1.0, -0.80][((x*18) % 360)//18 % 4]
    offset = .8 + offset
    
    offset *= dist**2.8 / 100.
    
    v.length = scale * (dist + offset) 
    
    b.position = c + v
    s = pymunk.Circle(b, 15)
    s.filter = pymunk.ShapeFilter(group = web_group)
    s.ignore_draw = True
    space.add(b,s)
    bs.append(b)

#連接線
def add_joint(a,b):
    rl = a.position.get_distance(b.position) * 0.9
    stiffness = 5000.
    damping = 100
    j = pymunk.DampedSpring(a, b, (0,0), (0,0), rl, stiffness, damping)
    j.max_bias = 1000
    j.max_force = 50000
    space.add(j)
    
for b in bs[:20]:
    add_joint(cb,b)
    
for i in range(len(bs)-1):
    add_joint(bs[i], bs[i+1])

    i2 = i+20
    if len(bs) > i2:
        add_joint(bs[i], bs[i2]) /<code>

5.4 網和點的關係

<code>static_bs = []
for b in bs[-17::4]:
    static_body = pymunk.Body(body_type = pymunk.Body.STATIC)
    static_body.position = b.position
    static_bs.append(static_body)
    
    j = pymunk.PivotJoint(static_body, b, static_body.position)
    j = pymunk.DampedSpring(static_body, b, (0,0), (0,0), 0, 0, 0)
    j.damping = 100
    j.stiffness = 20000
    space.add(j)

#更新
def update(dt):
    r = 10
    for x in range(r):
        space.step(1./30./r)                

pyglet.clock.schedule_interval(update, 1/30.)

selected = None
selected_joint = None
mouse_body = pymunk.Body(body_type = pymunk.Body.KINEMATIC)/<code>

5.5 第5步:窗口事件綁定和運行

<code>#第5步:窗口時間綁定
@window.event
def on_mouse_press(x, y, button, modifiers):
    mouse_body.position = x,y
    hit = space.point_query_nearest((x,y), 10, pymunk.ShapeFilter())
    if hit != None:
        global selected
        body = hit.shape.body
        rest_length = mouse_body.position.get_distance(body.position)
        stiffness = 1000
        damping = 10
        selected = pymunk.DampedSpring(mouse_body, body, (0,0), (0,0), rest_length, stiffness, damping)
        space.add(selected)
        
@window.event
def on_mouse_release(x, y, button, modifiers):
    global selected
    if selected != None:
        space.remove(selected)
        selected = None
    
@window.event
def on_mouse_drag(x, y, dx, dy, buttons, modifiers):
    mouse_body.position = x,y
   
@window.event
def on_key_press(symbol, modifiers):
    #保存設置,當按p就是保存
    if symbol == pyglet.window.key.P:
        pyglet.image.get_buffer_manager().get_color_buffer().save('spiderweb.png')

   
fps_display = pyglet.window.FPSDisplay(window)

@window.event
def on_draw():
    #窗口背景顏色設置,默認為黑色(0,0,0,255),最後一個255為透明度
    #pyglet.gl.glClearColor(240,240,240,255)  #白色
    #pyglet.gl.glClearColor(0,0,0,255)  #黑色,不設置也是黑色
    window.clear()
    
    fps_display.draw()
    
    # static attach points
    pyglet.gl.glColor3f(1,0,1)
    pyglet.gl.glPointSize(6)
    a = []
    for b in static_bs:
        a += [b.position.x, b.position.y]
        pyglet.graphics.draw(len(a)//2, pyglet.gl.GL_POINTS, ('v2f',a))
    
    # web crossings / bodies
    pyglet.gl.glColor3f(.8,.8,.8)
    a = []
    for b in bs:
        a += [b.position.x, b.position.y]
    pyglet.gl.glPointSize(4)
    pyglet.graphics.draw(len(a)//2, pyglet.gl.GL_POINTS, ('v2f',a))
    
   
    # web net / constraints
    a = []
    for j in space.constraints:
        a += [j.a.position.x, j.a.position.y, j.b.position.x, j.b.position.y]
        pass
    
    pyglet.graphics.draw(len(a)//2, pyglet.gl.GL_LINES, ('v2f',a))
     
pyglet.app.run()
/<code>

關注我,不迷路。

學習你學不到的python知識,作為你編程的補充。


分享到:


相關文章: