from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import Color, Ellipse
from kivy.core.window import Window
from kivy.clock import Clock
import random
import math
# ウィンドウサイズ
Window.size = (400, 400)
class Ball:
def __init__(self, canvas, x, y, radius, dx, dy, color=(1, 0, 0)):
self.x = x
self.y = y
self.radius = radius
self.dx = dx
self.dy = dy
self.color = color
with canvas:
Color(*self.color)
self.ellipse = Ellipse(pos=(self.x - self.radius, self.y - self.radius),
size=(2 * self.radius, 2 * self.radius))
def update(self):
# 移動
self.x += self.dx
self.y += self.dy
# 壁との反射
if self.x - self.radius <= 0 or self.x + self.radius >= Window.width:
self.dx *= -1
if self.y - self.radius <= 0 or self.y + self.radius >= Window.height:
self.dy *= -1
# 位置座標を更新
self.ellipse.pos = (self.x - self.radius, self.y - self.radius)
class BouncingBallApp(Widget):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.balls = [] # 複数のボールオブジェクトを入れる配列を定義
self.max_balls = 20 # 最大ボール数
# 0.5秒ごとに新しいボールを追加
Clock.schedule_interval(self.add_ball, 0.5)
# 毎フレーム更新
Clock.schedule_interval(self.update, 1/60)
def add_ball(self, dt):
if len(self.balls) < self.max_balls: #生成したボールが最大数に達していないとき
# 中心から発射
x, y = Window.width / 2, Window.height / 2
radius = 10
# ランダム方向・速度
speed = 2
angle = random.uniform(0, 2 * math.pi)
# random.uniform(a, b) は、 a から b の範囲でランダムな実数を返す 関数
# math.pi は円周率 (π ≒ 3.14159)、0 ~ 2π は、円を1周する角度の範囲(ラジアン単位)
dx = speed * math.cos(angle)
dy = speed * math.sin(angle)
# angle=0のときcos=1,sin=0で右方向
# angle=π/2のときcos=0,sin=1で上方向
# angle=πのときcos=-1,sin=0で左方向
# angle=3π/2のときcos=0,sin=-1で下方向
# ランダム色 (RGB 0〜1)
color = (random.random(), random.random(), random.random())
ball = Ball(self.canvas, x, y, radius, dx, dy, color)
self.balls.append(ball)
def update(self, dt):
for ball in self.balls:
ball.update()
class MyApp(App):
def build(self):
return BouncingBallApp()
if __name__ == "__main__":
MyApp().run()