0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PyxelとPymunkでサンプルプログラム その8

Last updated at Posted at 2025-11-13

生成AI、いろいろやっていると、古いAPIを参照していたりして、設定テキストを作成して調整するのが面白いところです。
物理シミュレーションは、何を使って、どのように動かすのか、実験装置を作るような感じでしょうか、どのような表現があるか、AIから出力したサンプルを紹介します。

プロンプト例1


次の仕様に沿った「pyxel」と「pymunk」を使った簡易 2D 物理シミュレーションを行う Python コードを生成してください。

ウィンドウ設定

解像度:幅 640px × 高さ 480px
タイトル:「2D Physics Simulation」
マウスカーソル表示オン
物理空間の設定

pymunk.Space を使い、重力は下向きに (0, -900)
Space のステップタイムステップは 1/60 秒
地面の作成(静的オブジェクト)

ボディタイプ:STATIC
位置:画面下部中央(x = 幅/2、y = 20)
形状:幅 640 × 高さ 40 の長方形
摩擦係数:0.8
反発係数(elasticity):0.4
描画色:青(COLOR_BLUE = 5)
落下する矩形オブジェクト(動的オブジェクト)

サイズ:60 × 30
質量:5
慣性モーメントは pymunk.moment_for_box で計算
初期位置:画面上部中央(x = 幅/2、y = 450)
摩擦係数:0.5
反発係数:0.6
描画色:赤(COLOR_RED = 8)
操作

キー「R」を押すとシミュレーションをリセット(地面と矩形を再生成)
描画方法

pyxel.cls(0) で背景をクリア
地面は pymunk.Shape.bb(Bounding Box)から得た座標を pyxel.rect で描画
矩形は pymunk.Poly の頂点を world 座標に変換し、さらに pyxel の Y 軸に合わせて反転し、
バウンディングボックスで pyxel.rect を使って描画
以上の仕様を満たす、実行可能な完全な Python スクリプトを出力してください。


import pyxel
import pymunk

COLOR_RED = 8
COLOR_BLUE = 5

class PhysicsSimulation:
    def __init__(self):
        self.width = 640
        self.height = 480
        pyxel.init(self.width, self.height, title="2D Physics Simulation")
        pyxel.mouse(True)
        self.reset()
        pyxel.run(self.update, self.draw)

    def reset(self):
        self.space = pymunk.Space()
        # 重力は下向き(pymunkのy軸は上向きなので負の値)
        self.space.gravity = (0, -900)

        # 地面の作成 (青い長方形)
        ground_body = pymunk.Body(body_type=pymunk.Body.STATIC)
        ground_body.position = (self.width / 2, 20)
        ground_shape = pymunk.Poly.create_box(ground_body, (self.width, 40))
        ground_shape.friction = 0.8
        ground_shape.elasticity = 0.4
        self.space.add(ground_body, ground_shape)
        self.ground_shape = ground_shape

        # 落下する赤い長方形
        size = (60, 30)
        mass = 5
        moment = pymunk.moment_for_box(mass, size)
        self.rect_body = pymunk.Body(mass, moment)
        # 中央上部から落とす(y=450)
        self.rect_body.position = (self.width / 2, 450)
        rect_shape = pymunk.Poly.create_box(self.rect_body, size)
        rect_shape.friction = 0.5
        rect_shape.elasticity = 0.6
        self.space.add(self.rect_body, rect_shape)
        self.rect_shape = rect_shape

    def update(self):
        if pyxel.btnp(pyxel.KEY_R):
            self.reset()

        dt = 1 / 60.0
        self.space.step(dt)

    def draw(self):
        pyxel.cls(0)

        # 地面描画
        ground_bb = self.ground_shape.bb
        pyxel.rect(
            int(ground_bb.left),
            int(self.height - ground_bb.top),
            int(ground_bb.right - ground_bb.left),
            int(ground_bb.top - ground_bb.bottom),
            COLOR_BLUE
        )

        # 回転する長方形の描画(pymunkのPoly頂点をワールド座標に変換)
        verts = [self.rect_body.local_to_world(v) for v in self.rect_shape.get_vertices()]

        # pymunkのy軸は上向き、pyxelは下向きなのでy座標を反転させる必要あり
        verts_pyxel = [(int(x), int(self.height - y)) for x, y in verts]

        # 四角形の頂点は順序通りなので三角形2つに分割して描画する方法もありますが、
        # 今回は単純にバウンディングボックスで描画します。
        min_x = min(v[0] for v in verts_pyxel)
        max_x = max(v[0] for v in verts_pyxel)
        min_y = min(v[1] for v in verts_pyxel)
        max_y = max(v[1] for v in verts_pyxel)

        width_rect = max_x - min_x
        height_rect= max_y - min_y

        pyxel.rect(min_x, min_y, width_rect, height_rect, COLOR_RED)

if __name__ == "__main__":
    PhysicsSimulation()

プロンプト例2


参照せずに独立して生成します。画面サイズは640x480で、Pyxelのタイトルは「2D Physics Simulation」とします。マウスカーソルを表示し、物理空間を初期化します。重力は下向き(0, -900)に設定し、静的な青い長方形の地面を画面下部に設置します。サイズは画面幅いっぱいで高さ40、位置は画面下から20の高さです。動的な赤い長方形はサイズ60x30、質量5で、画面中央上部(y=450)に配置し、摩擦0.5、弾性0.6を設定します。更新処理では60FPSの固定時間ステップで物理空間を進め、Rキーを押すとリセットします。描画では背景を黒でクリアし、地面を青い長方形で描画し、赤い長方形はpymunkの頂点座標をワールド座標に変換し、y軸を反転させた後、バウンディングボックスの矩形で描画します。コード内にコメントや空行は含めず、完全動作するプログラムを生成してください。


pyxel.rect()なので、角速度を付けたら、赤い長方形の幅と高さが変化するアニメーションになりました。頂点の最大値と最小値が変わるからですか。

   self.rect_body.angular_velocity = 5

pyxel.tri()を使えば、回転します。
日々,いろいろ,気づきですね。ありがとうございます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?