2017-08-21 9 views
2

この質問はpymunkに関するものですが、Chimpunkのユーザがたくさんいることを知っています。あなたの答えがC/Chipmunkコードを含んでいれば大丈夫です。私はCコードの記述方法はわかりませんが、他の誰かを読むと、何が起きているのか把握することができます。衝突中のある物体から別の物体へのエネルギーの移動

セットアップ

私は(カールやシャッフルボードを考える)トップダウンスライドオブジェクトのゲームをシミュレートしています。 私は(質問の最後に)コードの関連部分の最小限の例を作ったが、それの心は次のとおりです。

  • 2つの同一の物理オブジェクトが作成される(カーリングの用語を以下、私はそれらを呼び出します'stones')
  • 位置は同じx値ですが、y値が異なります(1つは直線上にあります)。

私は何を望んでいる

とき達成するために、下の石がまっすぐに他の石で「打ち上げ」される(他の方法が試みられたものの、今のところ)apply_impulse使用

  • 石が衝突すると、下の石が突然停止するか(または少し戻ってくる - 私はまだその詳細を汗ばませていない)、そのエネルギーのすべてまたは大部分が上部石に移動し、移動するupscreen。

    私は石が衝突すると、下の石が停止しない代わりに

    を得ている、と上部の石upscreenを押して開始します。 下の方が上よりも質量が大きいようですが、同じ関数で作成されているので同じでなければなりません。

    私はそれが助け場合は、このことを示しているimgurする.GIFをアップロードしました: http://imgur.com/a/FF6Xq

    をそれが実際にスクリプトを実行しているときよりも低いフレームレートだが、それはまだ何が起こっているのかを示します。私は、関連するかもしれないすべてのボディと形状の特性を特定しようとする、pygameのドキュメントを通じて読む

    を試してみた何

    は、私は様々な組み合わせで、次のすべてを調整しようとしました:

    • body.mass shape.friction
    • 形状。弾性
    • 「接地摩擦」(トップダウンシナリオで接地摩擦をシミュレートピボット制約のmax_force)
    • 下石を起動している時に「電源」(apply_impulseに渡される引数のうちの1つ)
    • どの/これらの全てが目立たや石の行動の変化を期待しますが、どれも、彼らが衝突したとき、他のを押して一石の根本的な問題を変更しない微調整の代わりにapply_impulse

    のapply_forceを使用して

  • 私はpymunk.CollisionHandler()の使用について読んでいますが、まだ使用しようとしていません。ドキュメントから、これは主に、衝突に何かの基本的な物理を変更するのではなく、衝突に追加の効果を加えることを主な目的としているということがわかります。しかし、私は誤解している可能性があり、いかなる示唆にも開放しています。

    私はpymunkデモのいくつかを見てきました。特に注目すべきは、newtons_cradle.pyというデモが、私が望む動作を示すことです。それは5つの球が連続して停止しているそれらのガジェットの1つのシミュレーションです。ユーザーが最後のボールを1つ後ろに引くと、残りの行に当たってエネルギーが反対側のボールに移動します。 newtons_crade.pyは私のコードから2つの大きな違いがあります。それは

  • (そう、重力が0より大きい)「サイドビュー」だというよりもapply_impulseまたはapply_forceを使用

    • を、重力のみをするために使用されますボールを他のものに向けて推進する(制約によって制約される)。

    残念ながら、私のトップダウン設定で重力を使用することはできません。 問題は私がapply_impulse/apply_forceを使用している可能性がありますが、これらの使用方法を変更する方法はありません(私はすでにさまざまな組み合わせの力と質量を試していますが、制約の設定も調整しています) 。

    正しい方向で私を指差しても、それ以外の何かを読んでいるかもしれないというアドバイスや、改めて試してみようと思うことがあります。私はpymunk/chipmunkでこれを試す最初の人になることはできませんが、私は例を見つけることができませんでした。少なくともpymunk側ではない。もし私が勉強することができるC/Chipmunkの良い例があれば、それも役に立つだろう。

    ありがとうございます。

    最小限のコード例

    それは質問を理解するためのコードを勉強する必要はありませんが、私はそれが便利です念のためにそれをここに掲載しました。コードの中心を示すために削除されましたが、完全なスクリプトであり、実行することができます。 Python 3にあります。

    #!/usr/bin/env python 
    # -*- coding: utf-8 -*- 
    
    import sys 
    import pygame 
    from pygame.locals import * 
    import pymunk 
    import pymunk.pygame_util 
    
    def add_and_tether_stone(space,sx,sy): 
        """Creates a stone and its corresponding shape, and tethers it with constraints that simulate ground friction and govern spin.""" 
        #body 
        mass = stone_mass 
        radius = stone_radius 
        moment = pymunk.moment_for_circle(mass, 0, radius) 
        body = pymunk.Body(mass, moment) 
        body.position = sx,sy 
        #shape 
        shape = pymunk.Circle(body, radius) 
        shape.friction = stone_friction 
        shape.elisticity = stone_elisticity 
        space.add(body, shape) 
        #constraints 
        fpiv = pymunk.constraint.PivotJoint(space.static_body,body,(0.0,0.0),(0.0,0.0)) 
        fpiv.max_force = ground_friction 
        fpiv.max_bias = 0.0 
        fmot = pymunk.constraint.SimpleMotor(space.static_body,body,0) 
        fmot.max_force = 5000000 #arbitry 'very high' value clamps down on the high rotation imparted by apply_impulse or apply_force 
        space.add(fpiv) 
        space.add(fmot) 
        return body,shape,fpiv,fmot 
    
    def launch_stone(body,power): 
        """Launches a stone in the manner of a player taking a shot.""" 
        body.apply_impulse_at_world_point((0,power),(0,0)) #force(x,y),offset(x,y) 
    
    def main(): 
        global ground_friction,stone_mass,stone_radius,stone_friction,stone_elisticity 
        running = True 
        #PyGame setup 
        pygame.init() 
        screen = pygame.display.set_mode((500,500)) 
        clock = pygame.time.Clock() 
        sheet = pygame.Surface((500,500)) 
        sheetcolor = (0,0,0) 
        sheet.fill(sheetcolor) 
        sheet = sheet.convert() 
        sheetblit = (0,0) 
        screen.blit(sheet,sheetblit) 
    
        #PyMunk setup 
        space = pymunk.Space() #space.damping defaults to 1.0, and space.gravity defaults to (0.0, 0.0). 
        draw_options = pymunk.pygame_util.DrawOptions(sheet) #used only for the pygame_util debug draw mode 
    
        #Constants to Tweak 
        stone_mass = 1.4 
        stone_radius = 20 
        power = 340 #in a full implementation, this would vary with player input 
        ground_friction = 4.5 
        stone_friction = 2.0 
        stone_elisticity = 1.0 
    
        #Setup for the minimal example: add two stones and launch one at the other. 
        stone_a = add_and_tether_stone(space,40,260) 
        stone_b = add_and_tether_stone(space,40,21) 
        launch_stone(stone_b[0],power) 
    
        while running: 
         for event in pygame.event.get(): #listen for controls (all the controls except 'esc' have been removed for the minimal example) 
          if event.type == KEYDOWN and event.key == K_ESCAPE: 
           running = False 
         #Draw, update physics, and advance 
         sheet.fill(sheetcolor) 
         space.debug_draw(draw_options) #from pymunk.pygame-util (handy!) 
         screen.blit(sheet,sheetblit) 
         space.step(1/50.0) 
         pygame.display.flip() 
         clock.tick(50) 
    
    if __name__ == '__main__': 
        sys.exit(main()) 
    

    ありがとうございました。

  • 答えて

    1

    多分私はあなたのコードで何かを逃した(私はあなたのスクリプトを実行することができないので、ここにコマンドラインのpythonを持っている)が、あなたの問題を再現することはできません。ここで

    は、あなたが望むように動作するようです私が試した短いコードです:

    import pymunk 
    
    s = pymunk.Space() 
    
    b1 = pymunk.Body(1,10) 
    b1.position = 0,0 
    
    b2 = pymunk.Body(1,10) 
    b2.position = 0,10 
    
    c1 = pymunk.Circle(b1, 1) 
    c1.elasticity = 1.0 
    c2 = pymunk.Circle(b2, 1) 
    c2.elasticity = 1.0 
    
    j1 = pymunk.constraint.PivotJoint(s.static_body, b1, (0,0),(0,0)) 
    j1.max_force = 4.5 
    j1.max_bias = 0 
    
    j2 = pymunk.constraint.PivotJoint(s.static_body, b2, (0,0),(0,0)) 
    j2.max_force = 4.5 
    j2.max_bias = 0 
    
    j3 = pymunk.constraint.SimpleMotor(s.static_body,b1,0) 
    j3.max_force = 5000000 
    j4 = pymunk.constraint.SimpleMotor(s.static_body,b2,0) 
    j4.max_force = 5000000 
    
    s.add(b1,b2,c1,c2,j1,j2,j3,j4) 
    
    b1.apply_impulse_at_world_point((0,30),(0,0)) 
    
    for x in range(25): 
        s.step(0.02) 
        print(b1.position, b2.position) 
    

    これは私の画面上でこれをプリントアウトする(そうB1が停止し、すべての動きがB2に転送されます):

    Vec2d(0.0, 0.6) Vec2d(0.0, 10.0) 
    Vec2d(0.0, 1.1982) Vec2d(0.0, 10.0) 
    Vec2d(0.0, 1.7946) Vec2d(0.0, 10.0) 
    Vec2d(0.0, 2.3891999999999998) Vec2d(0.0, 10.0) 
    Vec2d(0.0, 2.9819999999999998) Vec2d(0.0, 10.0) 
    Vec2d(0.0, 3.573) Vec2d(0.0, 10.0) 
    Vec2d(0.0, 4.1622) Vec2d(0.0, 10.0) 
    Vec2d(0.0, 4.7496) Vec2d(0.0, 10.0) 
    Vec2d(0.0, 5.3352) Vec2d(0.0, 10.0) 
    Vec2d(0.0, 5.9190000000000005) Vec2d(0.0, 10.0) 
    Vec2d(0.0, 6.501) Vec2d(0.0, 10.0) 
    Vec2d(0.0, 7.081200000000001) Vec2d(0.0, 10.0) 
    Vec2d(0.0, 7.659600000000001) Vec2d(0.0, 10.0) 
    Vec2d(0.0, 8.2362) Vec2d(0.0, 10.0) 
    Vec2d(0.0, 8.228112001309862) Vec2d(0.0, 10.584682725252637) 
    Vec2d(0.0, 8.228112001309862) Vec2d(0.0, 11.159477451815137) 
    Vec2d(0.0, 8.228112001309862) Vec2d(0.0, 11.732472178377638) 
    Vec2d(0.0, 8.228112001309862) Vec2d(0.0, 12.303666904940137) 
    Vec2d(0.0, 8.228112001309862) Vec2d(0.0, 12.873061631502637) 
    Vec2d(0.0, 8.228112001309862) Vec2d(0.0, 13.440656358065137) 
    
    +0

    ありがとうございました!あなたのコードと私を比較することで、私は問題を見つけることができました。 shape.elasticityを1.0(デフォルトの0から)に設定することは、決定的な違いを生み出しました。そして、私にとって恥ずかしいことに、「弾力性」という言葉のタイプミスは、私が弾力性を設定していると思っていましたが、実際に変更されたことはありません。私のコードをS.Oに投稿することで、どのようなタイプミスを見つけることができますか?さて、ご協力いただきありがとうございます。ご迷惑をおかけして申し訳ございません。 –