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.

コンピュータ演習A 22 Day 07th(5/23): c7(Bouncing Balls)「跳ね回るたまたま」

Last updated at Posted at 2021-06-07

今日は「跳ね回るたまたま」を作っていきます.何か大きなものを作るのも,小さなステップの積み重ねです.小さな動く枠組みから初めて,徐々に細かい動作を付け足していく,ゲームやアニメを作るのとよく似た作業です.アーティストになったつもりで,一歩先の動作を思い描きながら,コードを少しずつ改良していってください.

  • 動作がおかしい時は,その前の段階からいじったコードに間違いがあります.
  • その該当するテキスト(教科書)をじっくり読み込むようにしてください.
  • 作業を一つ飛ばしているとか,1行飛ばしたとか,一文字違ったとか.
  • 出力されたエラーを読んでください.
  • まずはエラー行と単語をチェックしてください.

これだけでもコーディング効率は格段に上がります.

課題

テキストp.211までのいくつかのボールを動かすプログラムを作成して,LUNAに提出しなさい.

発展課題(ボーナス3点)

クラス化した「跳ねる球たま」を作成しなさい.ただし,教科書のコードはあんまりよくないので,

を参照したコードを出しなさい.スピードが違います.

red:日の丸作成

./d11_bouncing_balls/bouncing_ball_v0_red.py
 1  import tkinter as tk
 2  
 3  root = tk.Tk()
 4  root.geometry("600x400")
 5  
 6  canvas = tk.Canvas(root, width=600, height =400, bg="white")
 7  canvas.place(x=0,y=0)
 8  
 9  canvas.create_oval(300-20, 200-20, 300+20, 200+20,fill='red',width=0)
10  
11  root.mainloop()

click:クリックに反応

./d11_bouncing_balls/bouncing_ball_v1_click.py
 1  import tkinter as tk
 2  
 3  x=300
 4  y=200
 5  
 6  def click(event):
 7      global x,y
 8      x = event.x
 9      y = event.y
10      canvas.create_oval(x-20, y-20, x+20, y+20,fill='red',width=0)
11  
12  root = tk.Tk()
13  root.geometry("600x400")
14  
15  canvas = tk.Canvas(root, width=600, height =400, bg="white")
16  canvas.place(x=0,y=0)
17  
18  canvas.bind("<Button-1>", click)
19  root.mainloop()

click.gif

move:動くたま

./d11_bouncing_balls/bouncing_ball_v2_move.py
 1  import tkinter as tk
 2  from tkinter.constants import MOVETO
 3  
 4  x=300
 5  y=200
 6  
 7  def move():
 8      global x,y
 9      canvas.create_oval(x-20, y-20, x+20, y+20,fill='white',width=0)
10      x = x+1
11      y = y
12      canvas.create_oval(x-20, y-20, x+20, y+20,fill='red',width=0)
13      root.after(10, move)
14  root = tk.Tk()
15  root.geometry("600x400")
16  
17  canvas = tk.Canvas(root, width=600, height =400, bg="white")
18  canvas.place(x=0,y=0)
19  
20  #canvas.bind("<Button-1>", click)
21  root.after(10, move)
22  root.mainloop()

mac版ではバグがあるようで,玉が消えません.消す方を少し大きめにしています.

move.gif

bounce:はねるたま

./d11_bouncing_balls/bouncing_ball_v3_bounce.py
 1  import tkinter as tk
 2  from tkinter.constants import MOVETO
 3  
 4  x = 300
 5  y = 200
 6  
 7  dx = 1
 8  dy = 1
 9  
10  
11  def move():
12      global x, y, dx, dy
13      canvas.create_oval(x-21, y-21, x+21, y+21, fill='white', width=0)
14      x = x+dx
15      y = y+dy
16      canvas.create_oval(x-20, y-20, x+20, y+20, fill='red', width=0)
17      if x >= canvas.winfo_width():
18          dx = -1
19      if x <= 0:
20          dx = 1
21      if y >= canvas.winfo_height():
22          dy = -1
23      if y <= 0:
24          dy = 1
25  
26      root.after(10, move)
27  
28  
29  root = tk.Tk()
30  root.geometry("600x400")
31  
32  canvas = tk.Canvas(root, width=600, height=400, bg="white")
33  canvas.place(x=0, y=0)
34  
35  #canvas.bind("<Button-1>", click)
36  root.after(1000, move)
37  root.mainloop()

img

balls:たくさんのたま

修正は一度に頭からするのではなく,細かくステップを切って修正してください.私は,

  1. line:6のballsの一つ目だけを追加.
  2. line:18 globalにballsを追加
  3. line:20 for b in balls:にする
  4. line:21-34にインデントを追加
  5. dx,dyをb["dx"], b["dy"]に変更
  6. x, y をb["x"], b["y"]に変更
  7. line:26のfill = 'red'をfill=b["color"]に変更

上手くいったら,ballsを付け足して全ての動作を確認

./d11_bouncing_balls/bouncing_ball_v4_balls.py
 1  import tkinter as tk
 2  from tkinter.constants import MOVETO
 3  
 4  
 5  balls = [
 6      {"x": 400, "y": 300, "dx": 1, "dy": 1, "color": "red"},
 7      {"x": 200, "y": 100, "dx": -1, "dy": 1, "color": "green"},
 8      {"x": 100, "y": 200, "dx": -1, "dy": -1, "color": "blue"}
 9  ]
10  
11  #x = 300
12  #y = 200
13  #dx = 1
14  #dy = 1
15  
16  
17  def move():
18      #    global x, y, dx, dy
19      global balls
20      for b in balls:
21          canvas.create_oval(b["x"]-21, b["y"]-21, b["x"]+21,
22                             b["y"]+21, fill='white', width=0)
23          b["x"] = b["x"]+b["dx"]
24          b["y"] = b["y"]+b["dy"]
25          canvas.create_oval(b["x"]-20, b["y"]-20, b["x"] +
26                             20, b["y"]+20, fill=b["color"], width=0)
27          if b["x"] >= canvas.winfo_width():
28              b["dx"] = -1
29          if b["x"] <= 0:
30              b["dx"] = 1
31          if b["y"] >= canvas.winfo_height():
32              b["dy"] = -1
33          if b["y"] <= 0:
34              b["dy"] = 1
35  
36      root.after(10, move)
37  
38  
39  root = tk.Tk()
40  root.geometry("600x400")
41  
42  canvas = tk.Canvas(root, width=600, height=400, bg="white")
43  canvas.place(x=0, y=0)
44  
45  # canvas.bind("<Button-1>", click)
46  root.after(2000, move)
47  root.mainloop()

img

p.211までできれば一度完成です.それをLUNAに提出してください.

balls:クラスで作るたま

これ以降は任意ですが,プログラミングの最新のコツです.じっくり読み込んでclass化が理解できるとコードが読みやすくなります.

./d11_bouncing_balls/bouncing_ball_v5_class.py
 1  import tkinter as tk
 2  from tkinter.constants import MOVETO
 3  
 4  
 5  class Ball:
 6      def __init__(self, x, y, dx, dy, color):
 7          self.x = x
 8          self.y = y
 9          self.dx = dx
10          self.dy = dy
11          self.color = color
12  
13      def move(self, canvas):
14          #    global x, y, dx, dy
15          canvas.create_oval(self.x-21, self.y-21, self.x+21,
16                             self.y+21, fill='white', width=0)
17          self.x = self.x+self.dx
18          self.y = self.y+self.dy
19          canvas.create_oval(self.x-20, self.y-20, self.x +
20                             20, self.y+20, fill=self.color, width=0)
21          if self.x >= canvas.winfo_width():
22              self.dx = -1
23          if self.x <= 0:
24              self.dx = 1
25          if self.y >= canvas.winfo_height():
26              self.dy = -1
27          if self.y <= 0:
28              self.dy = 1
29  
30  
31  b = Ball(400, 300, 1, 1, "red")
32  
33  
34  def loop():
35      b.move(canvas)
36      root.after(10, loop)
37  
38  
39  root = tk.Tk()
40  root.geometry("600x400")
41  
42  canvas = tk.Canvas(root, width=600, height=400, bg="white")
43  canvas.place(x=0, y=0)
44  
45  # canvas.bind("<Button-1>", click)
46  root.after(10, loop)
47  root.mainloop()

balls:クラスで作る速いたま

p.194のコラムで書かれているのですが,メモリリークのバグがあります.このままでは,とろい動きしかできません.以下の記事をさらに参照して修正してください.

./d11_bouncing_balls/bouncing_ball_v6_class_rev.py
 1  import tkinter as tk
 2  speed = 10
 3  class Ball:
 4    global speed
 5    def __init__(self, x, y, dx, dy, color):
 6      self.x = x
 7      self.y = y
 8      self.dx = dx
 9      self.dy = dy
10      self.color = color
11      self.ball = None
12  
13    def move(self, canvas):
14      canvas.delete(self.ball)
15      self.x = self.x + self.dx
16      self.y = self.y + self.dy
17      self.ball = canvas.create_oval(self.x - 20, self.y - 20,
18                         self.x + 20, self.y + 20, 
19                         fill=self.color, width=0)
20      if self.x >= canvas.winfo_width():
21        self.dx = -speed
22      if self.x < 0:
23        self.dx = +speed
24      if self.y >= canvas.winfo_height():
25        self.dy = -speed
26      if self.y < 0:
27        self.dy = +speed
28  
29  root = tk.Tk()
30  root.geometry("600x400")
31  
32  canvas = tk.Canvas(root, width=600, height=400, bg="white")
33  canvas.place(x=0, y=0)
34  
35  balls = [
36    Ball(100, 400, -10, 10, "red"),
37    Ball(200, 400, 10, -10, "green"),
38    Ball(300, 200, 10, 10, "blue")
39  ]
40  def loop():
41    for b in balls:
42      b.move(canvas)
43    root.after(10, loop)
44  
45  
46  root.after(10, loop)
47  root.mainloop()

さらに発展 たまたま^8

私のメモ:動画の作り方

  • Command - Shift - 4 space の後windowをクリック

  • Command - Shift - 5 で録画が起動

  • 画面の録画はできなくて,領域を選択,それがそのまま生きる

  • 収録ボタンでスタート

  • toolbarに停止の表示

  • 右下に出ているサムネールを右にスライドすると保存される.

  • その他の操作

  • ffmpeg -i click.mov click.gif


  • source ~/Desktop/lecture_23s/compA23/d7_12_python/c7_bouncing_ball.org
0

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