後半
前半はこちら →前半
斜めに動かす
# x座標を動かす
x = x + dx
# y座標も動かす
y = y + dy
# 次の位置に円を描く
canvas.create_oval(x - 20, y - 20, x + 20, y + 20, fill="red",width=0)
# 端を越えていたら反対向きにする
if x >= canvas.winfo_width():
dx = -1
if x <= 0:
dx = +1
# y座標も同様
if y >= canvas.winfo_height():
dy = -1
if y <= 0:
dy = +1
# 再びタイマー
root.after(10, move)
横に動かすときはx座標に移動量を足すことで動かしていた
そのためこの横の動きに縦の動き、つまりy座標に移動量を加えることで斜めの動きを実現できる
winfo_heightメソッドを使うことで高さを取得できる
結果
動かす円を増やす
# 円をリストで用意する
balls = [{"x" : 400, "y" : 300, "dx" : 1, "dy" : 1, "color":"red"},
{"x" : 200, "y" : 100, "dx" : -1, "dy" : 1, "color":"green"},
{"x" : 100, "y" : 200, "dx" : 1, "dy" : -1, "color":"blue"}]
def move():
global balls
for b in balls:
# 今の円を消す
canvas.create_oval(b["x"] - 20, b["y"] - 20,
b["x"] + 20, b["y"] + 20,
fill="white",width=0)
# x座標を動かす
b["x"] = b["x"] + b["dx"]
# y座標も動かす
b["y"] = b["y"] + b["dy"]
# 次の位置に円を描く
canvas.create_oval(b["x"] - 20, b["y"] - 20,
b["x"] + 20, b["y"] + 20,
fill=b["color"],width=0)
# 端を越えていたら反対向きにする
if b["x"] >= canvas.winfo_width():
b["dx"] = -1
if b["x"] <= 0:
b["dx"] = +1
# y座標も同様
if b["y"] >= canvas.winfo_height():
b["dy"] = -1
if b["y"] <= 0:
b["dy"] = +1
# 再びタイマー
root.after(10, move)
複数個の円を動かすためにはリストを使う
balls = [
{"x" : 400, "y" : 300, "dx" : 1, "dy" : 1, "color":"red"},
{"x" : 200, "y" : 100, "dx" : -1, "dy" : 1, "color":"green"},
{"x" : 100, "y" : 200, "dx" : 1, "dy" : -1, "color":"blue"}]
このようにリストにすることで行数を少なくすることができる
そして円に関するデータをまとめるためにディクショナリ(Dictionary)という機能を使う
今回はballを変数名とした
ball = {"x" : 400, "y" : 300, "dx" : 1, "dy" : 1, "color":"red"}
(ディクショナリ)
変数名 = { キー名: 値, キー名: 値, ・・・}
プログラムをブロック化する
今度はディクショナリとリストを使わずに行う
オブジェクトを使用する
class Ball:
def __init__(self, x, y, dx, dy, color):
self.x = x
self.y = y
self.dx = dx
self.dy = dy
self.color = color
def move(self, canvas):
# 今の円を消す
canvas.create_oval(self.x - 20, self.y - 20,
self.x + 20, self.y + 20,
fill="white",width=0)
# x座標を動かす
self.x = self.x + self.dx
self.y = self.y + self.dy
# 次の位置に円を描く
canvas.create_oval(self.x - 20, self.y - 20,
self.x + 20, self.y + 20,
fill=self.color, width=0)
# 端を越えていたら反対向きにする
if self.x >= canvas.winfo_width():
self.dx = -1
if self.x <= 0:
self.dx = +1
if self.y >= canvas.winfo_height():
self.dy = -1
if self.y <= 0:
self.dy = +1
# 円をひとつ作る
b = Ball(400, 300, 1, 1, "red")
def loop():
オブジェクトを使う場合にはクラスをプログラムしなければならない
こうしてクラスから作ったオブジェクトのことをインスタンスと言う
(クラス)
class クラス名:
クラスの定義内容
今回ではこの部分
class Ball:
def _init_(self, x, y, dx, dy, color):
self.x = x
self.y = y
self.dx = dx
self.dy = dy
self.color = color
ここにでてくる_init_というのは最初にオブジェクトを作るときに呼び出される特殊な関数であり、コンストラクタ(constructor)と呼ばれている
オブジェクトのなかにあるxやyなどの変数をインスタンス変数という
結果
スピードを速くするために先生のサイトを参照しました→クリック
円以外も動かす
def erase(self, canvas):
canvas.create_oval(self.x - 20, self.y - 20,
self.x + 20, self.y + 20,
fill="white",width=0)
def draw(self, canvas):
canvas.create_oval(self.x - 20, self.y - 20,
self.x + 20, self.y + 20,
fill=self.color, width=0)
class Rectangle(Ball):
def erase(self, canvas):
canvas.create_rectangle(self.x - 20, self.y - 20,
self.x + 20, self.y + 20,
fill="white",width=0)
def draw(self, canvas):
canvas.create_rectangle(self.x - 20, self.y - 20,
self.x + 20, self.y + 20,
fill=self.color, width=0)
class Triangle(Ball):
def erase(self, canvas):
canvas.create_polygon(self.x, self.y - 20,
self.x + 20, self.y + 20,
self.x - 20, self.y + 20,
fill="white",width=0)
def draw(self, canvas):
canvas.create_polygon(self.x, self.y - 20,
self.x + 20, self.y + 20,
self.x - 20, self.y + 20,
fill=self.color, width=0)
# 円、四角形、三角形を用意
balls = [Ball(400, 300, 1, 1, "red"),
Rectangle (200, 100, -1, 1, "green"),
Triangle(100, 200, 1, -1, "blue")]
def loop():
クラスにはメソッド単位で処理を変更する機能があり、これをオーバーライド(override)という
さらに既存のクラスを基に新しいクラスを作ることを継承という
(継承)
class新しいクラス名(基のクラス名):
クラス名
三角形→Triangle
四角形→Rectangle