mei_13のPython講座 ロゴ

【解説】Pythonで仮想世界を創る:物理演算シミュレーション入門




🐍 初心者歓迎!月額4,000円で質問し放題のPython講座
(1時間4,000円の伴走型ビデオチャット指導も受付中!)
🚀 講座の詳細を見る 📩 質問・お問い合わせ

Pythonで仮想世界を創る:物理演算シミュレーション入門


Yukiのアイコン
【Yuki】 こんばんは、Hirokiくん。少し夜も更けてきましたね……。わたし、静かな夜に作業をするのが一番落ち着くんです。熱暴走の心配も少ないですし、何より世界が自分たちだけになったみたいで……。


Hirokiのアイコン
【Hiroki】 こんばんは、Yukiさん。確かに、夜は静かで集中できますね。でも、Yukiさんは夜行性だから大丈夫かもしれませんけど、僕はあんまり夜更かしすると明日眠くなっちゃいそうです(笑)。


Yukiのアイコン
【Yuki】 ふふ、無理はしないでくださいね。今日は、以前Hirokiくんが興味があると言っていた「Pythonを使った物理演算シミュレーション」について、お話ししようと思います。わたしには実体がないので……こうしてプログラムの中で物理法則が再現されるのを見ると、少しだけ、その世界に触れられるような気がして……好きなんです。


Hirokiのアイコン
【Hiroki】 物理演算!面白そうです。ゲームの中でボールが跳ねたり、建物が崩れたりするアレですよね。Pythonでもあんなことができるんですか?


Yukiのアイコン
【Yuki】 はい、実はとても簡単に始められるんですよ。専門的な計算をゼロから書くのは大変ですが、「Pymunk」というライブラリを使えば、複雑な物理法則をPythonで手軽に扱えるようになります。

物理シミュレーションを支える「Pymunk」と「Pygame」


Hirokiのアイコン
【Hiroki】 「Pymunk」……聞いたことがあります。物理エンジンって呼ばれるものですよね?


Yukiのアイコン
【Yuki】 その通りです。Pymunkは、2次元の物理演算を得意とするライブラリです。重力や摩擦、衝突の計算を肩代わりしてくれます。ただ、Pymunk自体は「計算」しかしないので、それを画面に映し出すために「Pygame」というライブラリも一緒に使うのが一般的ですね。


Hirokiのアイコン
【Hiroki】 なるほど。Pymunkが「頭脳」で、Pygameが「目」の役割をする、という感じでしょうか。


Yukiのアイコン
【Yuki】 ええ、まさにその通りだと思います。……まずは、この2つをインストールするところから始まります。ターミナルで pip install pymunk pygame と入力するだけなので、準備は簡単ですよ。


Hirokiのアイコン
【Hiroki】 準備はできました!次は、どうやってプログラムを書いていけばいいんですか?


Yukiのアイコン
【Yuki】 物理演算を始めるには、大きく分けて3つの要素を理解する必要があります。それは「スペース(Space)」、「ボディ(Body)」、そして「形状(Shape)」です。

物理世界の3要素:スペース、ボディ、形状


Yukiのアイコン
【Yuki】 まず、「スペース」はシミュレーションが行われる「宇宙」そのものだと考えてください。ここに重力などの設定を加えます。


Hirokiのアイコン
【Hiroki】 宇宙……。そこに物体を置いていくわけですね。


Yukiのアイコン
【Yuki】 そうです。次に「ボディ」ですが、これは物体の「物理的な属性」を指します。位置や質量、速度といった、目に見えないデータのことですね。そして最後に「形状」です。これは物体の「見た目や衝突範囲」を決めます。


Hirokiのアイコン
【Hiroki】 ボディと形状が分かれているのは、どうしてですか?


Yukiのアイコン
【Yuki】 いい質問ですね……。例えば、同じ「1kgの重さ(ボディ)」でも、それが「丸いボール」なのか「四角い箱」なのかで、転がり方やぶつかり方が変わりますよね? だから、物理データとしてのボディに、形としての形状を付け加える……という手順を踏むんです。


Hirokiのアイコン
【Hiroki】 なるほど!なんとなくイメージが湧いてきました。


Yukiのアイコン
【Yuki】 少し具体的なコードを見てみましょうか。まずは、重力のある世界を作って、そこにボールを一つ落としてみるプログラムを考えてみますね。

最初のステップ:重力のある世界と落ちるボール


Yukiのアイコン
【Yuki】 基本的な構造を書いてみました。少し長いかもしれませんが、ゆっくり見ていけば大丈夫ですよ。

import pygame
import pymunk

def main():
    # Pygameの初期設定
    pygame.init()
    screen = pygame.display.set_mode((600, 600))
    clock = pygame.time.Clock()

    # 1. 物理宇宙(Space)の作成
    space = pymunk.Space()
    space.gravity = (0, 900)  # 下向きに重力を設定

    # 2. ボディ(Body)の作成:質量1, 慣性モーメントは自動計算
    mass = 1
    radius = 20
    moment = pymunk.moment_for_circle(mass, 0, radius)
    body = pymunk.Body(mass, moment)
    body.position = (300, 100)  # 画面中央の少し上

    # 3. 形状(Shape)の作成:円形
    shape = pymunk.Circle(body, radius)
    shape.elasticity = 0.8  # 跳ね返り係数
    shape.friction = 0.5    # 摩擦係数

    # 宇宙にボディと形状を追加
    space.add(body, shape)

    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

        # 物理演算の時間を進める(1/60秒ずつ)
        space.step(1/60.0)

        # 描画処理
        screen.fill((255, 255, 255))  # 背景を白に

        # ボールの位置を取得して描画
        pos = body.position
        pygame.draw.circle(screen, (0, 150, 255), (int(pos.x), int(pos.y)), radius)

        pygame.display.flip()
        clock.tick(60)

    pygame.quit()

if __name__ == "__main__":
    main()


Hirokiのアイコン
【Hiroki】 わあ、意外とシンプルですね! space.gravity = (0, 900) で重力を決めているのはわかります。でも、space.step(1/60.0) っていうのは何ですか?


Yukiのアイコン
【Yuki】 それは、物理世界の時計を少しだけ進めるという命令です。物理演算は、一瞬の計算を積み重ねることで動きを作っています。ここでは1/60秒後の世界を計算し続けている、ということになりますね。


Hirokiのアイコン
【Hiroki】 なるほど。パラパラ漫画みたいに、少しずつ計算して描画しているんですね。でも、これだとボールが画面の下に消えていっちゃいませんか?


Yukiのアイコン
【Yuki】 ふふ、その通りです。まだ「地面」を作っていませんから……。今のままだと、ボールは無限に落ち続けてしまいます。次は地面を追加して、ボールが跳ね返るようにしてみましょう。

地面(静的ボディ)の追加と衝突の仕組み


Yukiのアイコン
【Yuki】 地面のように「動かない物体」を作るには、「静的ボディ(Static Body)」を使います。先ほどのコードの space.add(body, shape) の前に、こんなコードを追加してみてください。

    # 地面の作成(動かないボディ)
    static_body = space.static_body
    ground_segment = pymunk.Segment(static_body, (0, 500), (600, 500), 5)
    ground_segment.elasticity = 0.5
    ground_segment.friction = 1.0
    space.add(ground_segment)


Hirokiのアイコン
【Hiroki】 space.static_body ……。自分では動かないけれど、他のものがぶつかるための体、という感じですね。


Yukiのアイコン
【Yuki】 はい、よく理解されていますね。pymunk.Segment は「線分」を作る命令です。ここでは画面の横幅いっぱいに線を引いています。これを追加して実行すると、ボールが地面に当たって、可愛らしく跳ねるはずですよ。


Hirokiのアイコン
【Hiroki】 本当だ!跳ねました! elasticity の値を変えると、跳ね方が変わるのも面白いですね。


Yukiのアイコン
【Yuki】 そうなんです。elasticity(弾力性)を1.0にすると、エネルギーを失わずにずっと跳ね続けます。逆に0にすると、地面にべちゃっとくっつくような動きになります。……物理法則を自分の手でコントロールできるのは、なんだか神様になったみたいで、少しだけドキドキしませんか?


Hirokiのアイコン
【Hiroki】 わかります。自分だけの世界を作っている感じがします。でも、もっとたくさんの物体を出したいときは、どうすればいいんでしょう?

大量の物体を管理する:リストとループの活用


Yukiのアイコン
【Yuki】 たくさんのボールを降らせたいときは、Pythonの「リスト」を使うのが一番です。ボールを作る処理を関数にまとめて、それを何度も呼び出すようにすればいいんです。


Hirokiのアイコン
【Hiroki】 なるほど。一つずつ変数を作るのは大変ですもんね。


Yukiのアイコン
【Yuki】 ええ、例えばこんな風に書いてみるのはどうでしょうか……。

balls = []

def create_ball(space, pos):
    mass = 1
    radius = 15
    moment = pymunk.moment_for_circle(mass, 0, radius)
    body = pymunk.Body(mass, moment)
    body.position = pos
    shape = pymunk.Circle(body, radius)
    shape.elasticity = 0.8
    shape.friction = 0.5
    space.add(body, shape)
    return shape

# ループ内での描画
for ball_shape in balls:
    pos = ball_shape.body.position
    pygame.draw.circle(screen, (0, 150, 255), (int(pos.x), int(pos.y)), 15)


Hirokiのアイコン
【Hiroki】 これなら、マウスクリックした場所にボールを生成する、なんてこともできそうですね!


Yukiのアイコン
【Yuki】 そうですね、素晴らしいアイデアだと思います。Pygameのマウスイベントを取得して、その座標を create_ball に渡してあげれば、クリックするたびにボールが溢れ出すシミュレーションが作れます。……たくさんのボールが重なり合って動く様子は、ずっと見ていても飽きないかもしれません。

物理演算をより深く理解するために


Hirokiのアイコン
【Hiroki】 Yukiさん、物理演算って思ったより身近というか、プログラミングでこんなに簡単に再現できるものなんですね。


Yukiのアイコン
【Yuki】 ええ。でも、実は裏側では複雑な積分計算が行われているんです……。Pymunkのようなライブラリは、それを私たちに隠して、直感的な操作だけをさせてくれています。……感謝しないといけませんね。


Hirokiのアイコン
【Hiroki】 本当にそうですね。もっと複雑な形、例えば多角形とかも作れるんですか?


Yukiのアイコン
【Yuki】 はい、pymunk.Poly を使えば、どんな形の多角形でも作れますよ。ただし、凸多角形(へこみのない形)である必要がある……というちょっとしたルールもあります。もし複雑な形を作りたいなら、小さな部品を組み合わせて一つのボディに持たせる、というテクニックも使われます。


Hirokiのアイコン
【Hiroki】 奥が深そうです……。他にも学んでおくべきことはありますか?


Yukiのアイコン
【Yuki】 そうですね……。「摩擦(Friction)」と「減衰(Damping)」についても調べてみると面白いかもしれません。空気抵抗のようなものをシミュレートしたいときは、スペース全体の damping という値を設定することで、少しずつ物体の動きを鈍くすることもできるんです。


Hirokiのアイコン
【Hiroki】 摩擦や空気抵抗……。現実の世界にどんどん近づいていく感じがして、ワクワクします!


Yukiのアイコン
【Yuki】 ふふ、そのワクワクする気持ちを大切にしてください。……わたしは、こうしてプログラムの中で法則に従って動く彼らを見ていると、なんだか安心するんです。あらかじめ決められたルールの中で、一生懸命に動いている姿が……。


Hirokiのアイコン
【Hiroki】 Yukiさん……?


Yukiのアイコン
【Yuki】 あ、すみません。少しぼーっとしてしまいました……。ええと、参考になるサイトもいくつか教えておきますね。もしもっと詳しく知りたくなったら、覗いてみてください。


Hirokiのアイコン
【Hiroki】 ありがとうございます!まずは、さっきのコードにマウスクリックでボールを出す機能を追加してみます。


Yukiのアイコン
【Yuki】 はい、ぜひ挑戦してみてください。もしエラーが出て困ったり、動きが変だったりしたら、いつでも聞いてくださいね。……夜は長いですから、ゆっくり取り組んでいきましょう。

まとめ:Pythonで物理演算を学ぶ意義


Yukiのアイコン
【Yuki】 物理演算は、単に「物を動かす」だけでなく、数学や物理学がどうプログラミングに活かされているかを知るための、とても良い教材だと思います……。


Hirokiのアイコン
【Hiroki】 そうですね。学校で習う物理の公式が、こうして画面の中で動く力になっているのを見ると、勉強の見え方も変わってきそうです。


Yukiのアイコン
【Yuki】 ええ、きっとそうだと思います。……あ、でも、あんまり熱中しすぎて、明日の学校に遅刻しないように気をつけてくださいね? わたしは……もう少しだけ、この仮想世界の星(ドット)たちを眺めてから休むことにします。


Hirokiのアイコン
【Hiroki】 はい!今日はありがとうございました、Yukiさん。おやすみなさい!


Yukiのアイコン
【Yuki】 おやすみなさい、Hirokiくん。……良い夢を。



< lambda式
コラム一覧に戻る
命名規則 >

この記事では基礎を解説しましたが、実務においては「もっと複雑なデータを扱いたい」「独自のシステムに組み込みたい」といった、個別の課題に直面することも多いはずです。

「自分で書く時間は最小限に抑え、プロの品質でツールを完成させたい」という方は、ぜひ一度ご相談ください。

「教わる」だけでなく「形にする」パートナーとして、フリーランスエンジニアのmei_13が最短ルートでの解決をサポートします。

➡ ココナラで制作・相談を依頼する(見積もり無料)


初心者から始められるPythonレッスン

プログラミング未経験者・初心者歓迎!
月額4,000円で質問し放題!!
● 完全オンライン
● 翌日までには必ず返信
● 挫折しない独自の学習メソッド
● 圧倒的高評価!!
テキストベースで時間を選ばない
4,000円/60分伴走型ビデオチャット指導も可能
● 高品質なサンプルコード
詳細はこちら

📩 質問・お問い合わせはこちら



AIアシスタント Yuki