😉
回転する六角形の中でボールが跳ね返るデモアプリの作ってみる
はじめに
@denwaya34です。😉
タイトルの通り、よくみるこのデモアプリがちゃんとできるか確認してみます。
cursorエディタとopenai o4-miniで作ってみます。
プロンプト
write a Python program that shows a ball bouncing inside a spinning hexagon.
The ball should be affected by gravity and friction, and it must bounce off the rotating walls realistically.
日本語訳
回転する六角形の中でボールが弾む様子を示すPythonプログラムを書きなさい。
ボールは重力と摩擦の影響を受け、回転する壁をリアルに跳ね返らなければならない。
結果
ちゃんとできた😉
コードはこんな感じ
# main.py
# ボールが重力と摩擦を受けながら回転する六角形内で跳ね返るプログラム
# 必要パッケージ: pygame(pip install pygame)
import pygame
import sys
import math
import random
WIDTH, HEIGHT = 800, 600
CENTER = pygame.math.Vector2(WIDTH/2, HEIGHT/2)
HEX_RADIUS = 250
BALL_RADIUS = 15
GRAVITY = 500 # px/s^2
FRICTION = 0.999
BOUNCE = 0.9
FPS = 60
ROT_SPEED = math.radians(30) # 回転速度 (rad/s)
def main():
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Ball in Spinning Hexagon")
clock = pygame.time.Clock()
ball_pos = pygame.math.Vector2(CENTER)
ball_vel = pygame.math.Vector2(random.uniform(-200, 200), random.uniform(-200, 200))
angle = 0.0
running = True
while running:
dt = clock.tick(FPS) / 1000.0
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# 物理演算
ball_vel.y += GRAVITY * dt
ball_vel *= FRICTION
ball_pos += ball_vel * dt
# 回転更新
angle += ROT_SPEED * dt
# 六角形頂点計算
hex_points = []
for i in range(6):
theta = angle + i * 2 * math.pi / 6
x = CENTER.x + HEX_RADIUS * math.cos(theta)
y = CENTER.y + HEX_RADIUS * math.sin(theta)
hex_points.append(pygame.math.Vector2(x, y))
# 衝突判定
for i in range(len(hex_points)):
A = hex_points[i]
B = hex_points[(i + 1) % len(hex_points)]
edge = B - A
mid = (A + B) * 0.5
to_center = CENTER - mid
normal = pygame.math.Vector2(edge.y, -edge.x).normalize()
if normal.dot(to_center) < 0:
normal = -normal
dist = (ball_pos - A).dot(normal)
proj = (ball_pos - A).dot(edge.normalize())
if dist < BALL_RADIUS and proj > 0 and proj < edge.length():
# 壁速度
r = ball_pos - CENTER
v_wall = pygame.math.Vector2(-ROT_SPEED * r.y, ROT_SPEED * r.x)
v_rel = ball_vel - v_wall
v_rel_reflected = v_rel - 2 * v_rel.dot(normal) * normal
ball_vel = (v_rel_reflected + v_wall) * BOUNCE
ball_pos += normal * (BALL_RADIUS - dist)
# 描画
screen.fill((30, 30, 30))
pygame.draw.polygon(screen, (200, 200, 200), [(p.x, p.y) for p in hex_points], 2)
pygame.draw.circle(screen, (255, 100, 100), (int(ball_pos.x), int(ball_pos.y)), BALL_RADIUS)
pygame.display.flip()
pygame.quit()
sys.exit()
if __name__ == "__main__":
main()
その他
録画をしたい場合
プログラム作成後、下記のプロンプトを入力して録画を作成するように指示します。
このプログラムが起動したら、pygameの画面を起動時点から30秒録画するようにしてください
Discussion