LoginSignup

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

More than 3 years have passed since last update.

Lesson7 27020718

Last updated at Posted at 2020-06-06
1 / 19

複数のボールを動かそう

今回も同様に4つのSTEPで作っていきます


はじめに

完成形となるLesson7-8,7-9の内容がvscodeでなぜか実行を押しても動きませんでした。解決方法を模索しましたが未だ改善していません。ですので今回の実際に動かしてみた時の様子は、vscodeの画面ではないことをご了承ください。


追記(6月8日)

ご指摘いただいたところ無事動きました。最終行のmainloopの後の()が抜けていたようです。ミスに気付かず猛省しました。
しかしそうなると今度はなぜidleのほうでは動いたのかが謎になりました。。。。


1STEP:円を自動で動かそう


Lesson7-4.py
# 円の座標
x = 400
y = 300

def move():
    global x, y
    #いまの円を消す
    canvas.create_oval(x - 20, y - 20,x + 20,y + 20,fill="white", width=0)
    # x座標を動かす
    x = x + 1
    # 次の位置に円を描く
    canvas.create_oval(x - 20,y - 20,x + 20,y + 20, fill="red", width=0)
    # 再びタイマー
    root.after(10, move)

これで円が右にスーっと動きます…
もっと速く動かしたい!!


⇒メモ 

  • x=x + 1をx + 2にすることで、x座標が2倍で進む。
  • after の数字を小さくすればいい(?/1000秒の間隔で円を描いている)

2STEP:往復して円を動かそう

往復して動かすためには次の3つがカギとなります。

Lesson7-5.py
# 移動量
dx = 1

# x座標を動かす
    x = x + dx

# 端を超えたら反対に
    if x >= canvas.winfo_width():
       dx = -1
    if x <= 0:
       dx = +1

メモ

  • 円の判定は中心で、実際は半径も含めたほうがいい。(含めないほうが簡単)
  • 同様にしてy方向に円を動かすことができる。

3STEP:同時にいくつか動かそう

今度は3つ同時に動かします。
先ほどと同じことをもう2つ用意すればいいんですが・・・面倒!
そこで、ディクショナリリストを利用します。


メモ

  • ディクショナリ:円に関係するデータをまとめる。
  • リスト:すべての円をまとめる。

Lesson7-7.py
# 円をリストで管理する
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,y座標を動かす
        b["x"] = b["x"] + b["dx"]
        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)
        # x座標:端を超えたら
        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



4STEP:△▢も動かそう(問題有)

このステップではディクショナリとリストで円を描いたのをクラスとオブジェクトに変更します。
(変更したら動かなくなった。)


メモ

  • オブジェクト:今回でいう円のこと

何が違うの???

ディクショナリとリスト クラスとオブジェクト
円を作る。
それぞれにデータを与える
データを持った円に命令(メソッド)

ムズカシイ;;


実際のコード↓

Lesson7-9.py
# coding:utf-8
import tkinter as tk
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):
        # いまの円を消す
        self.erase(canvas)
        # x,y座標を動かす
        self.x = self.x + self.dx
        self.y = self.y + self.dy
        # 次の位置に円を描く
        self.draw(canvas)
        # x座標:端を超えたら
        if (self.x >= canvas.winfo_width()):
            self.dx = -1
        if (self.x <= 0):
            self.dx = 1
        # y座標:端を超えたら
        if (self.y >= canvas.winfo_height()):
            self.dy = -1
        if (self.y <= 0):
            self.dy = 1

    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():
    # 動かす
    for b in balls:
        b.move(canvas)
    # もう一回
    root.after(10,loop)

# ウィンドウを描く
root = tk.Tk()
root.geometry("800x600")

# キャンバスを置く
canvas =tk.Canvas(root, width =800,height = 600, bg="#fff")
canvas.place(x = 0, y = 0)

# タイマーをセット
root.after(10, loop)

root.mainloop


vscodeでは動かなかったので、、、
IDLEのほうで試したところ動きました。
どうしてこうなったか模索中です。(ほかのLessonで作ったものは動く。)


コメント 2020-06-07 125207.png


追記6月8日 vscode版
2020-06-08 (3).png


今回学んだ大事なこと

  • クラスとオブジェクト技法(まだ理解が追い付いていない)
  • リストがわかりやすく、そこそこ使いやすいことを実感

追記:

3

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