生成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()を使えば、回転します。
日々,いろいろ,気づきですね。ありがとうございます。