質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

3149閲覧

ボールが壁で跳ね返るアニメーションを作成したい

ramurezun

総合スコア5

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/05/15 16:09

前提・実現したいこと

小林 郁夫・佐々木 晃共著の「Pythonによるプログラミング」p133~135の練習問題5.3、5.4に取り組んでいます。最終的にBallクラスを使った複数のボールが壁で跳ね返るアニメーションを作成したいです。自分でも挑戦してみましたが、上手くいきません。ご教授願います。

発生している問題・エラーメッセージ

 下記のプログラムを実行すると、このようなエラーメッセージが出て、ボールがずっと停止したままになります。
Traceback (most recent call last):
File "C:/Users/user/Desktop/python/ex05-bounce.py", line 70, in <module>
tk.update()
File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\tkinter_init_.py", line 1305, in update
self.tk.call('update')
_tkinter.TclError: can't invoke "update" command: application has been destroyed

該当のソースコード

 以下、自分で作成したプログラムです。
from tkinter import *
import time

DURATION=0.001

class Ball:
def init(self,id,x,y,d,vx,vy,c):
self.id=id
self.x=x
self.y=y
self.d=d
self.vx=vx
self.vy=vy
self.c=c

def move(self): self.x=self.x+self.vx self.y=self.y+self.vy def redraw(self): d=self.d canvas.coords(self.id,self.x-d,self.y-d, self.x+d,self.y+d)

class Border:
def init(self,l,r,t,b):
self.l=l
self.r=r
self.t=t
self.b=b

def draw(self): canvas.create_rectangle(self.l,self.t,self.r-self.l,self.b-self.t)

def make_ball(x,y,d,vx,vy,c):
id=canvas.create_rectangle(x,y,x+d,y+d,
fill=c,outline=c)
ball=Ball(id,x,y,d,vx,vy,c)
return ball

tk=Tk()
canvas=Canvas(tk,width=800,height=600,bd=0)
canvas.pack()

border=Border(100,700,100,500)
border.draw

balls=[
make_ball(150,150,20,2,3,"darkblue"),
make_ball(200,250,25,-4,-3,"orange"),
make_ball(300,350,10,-2,6,"green"),
make_ball(400,450,5,10,-6,"darkgreen")
]

while True:
for ball in balls:
ball.move
if (ball.x-ball.d<border.l):
ball.vx=-ball.vx
if(ball.y-ball.d<border.t):
ball.vy=-ball.vy
if(ball.x+ball.d>=border.r):
ball.vx=-ball.vx
if(ball.y+ball.d>=border.b):
ball.vy=-ball.vy
ball.redraw
tk.update()
time.sleep(DURATION)

試したこと

補足情報(FW/ツールのバージョンなど)

該当するページを掲載しておきます。
https://books.google.co.jp/books?id=sOKxDwAAQBAJ&pg=PA133&lpg=PA133&dq=python%E3%81%AB%E3%82%88%E3%82%8B%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%80%80%E3%83%9C%E3%83%BC%E3%83%AB%E3%82%AF%E3%83%A9%E3%82%B9&source=bl&ots=nzXmy_GSp5&sig=ACfU3U16Go3D-FJeM1qhuC-F0B4K8NE6CQ&hl=ja&sa=X&ved=2ahUKEwicx7eMoLbpAhWOFIgKHcvzCV4Q6AEwAHoECAoQAQ#v=onepage&q=python%E3%81%AB%E3%82%88%E3%82%8B%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%80%80%E3%83%9C%E3%83%BC%E3%83%AB%E3%82%AF%E3%83%A9%E3%82%B9&f=false

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

関数呼び出し ball.redraw() とするところが、ball.redraw となっていたり、おかしな箇所がいくつかあります。教科書にコードが載っているのであれば、写し間違いがないか確認してみてください。

修正した箇所

diff

1- border.draw 2+ border.draw()

diff

1- border.move 2+ border.move()

diff

1- ball.redraw 2+ ball.redraw()

create_rectangle() の指定は x, y, w, h ではなく、x1, y1, x2, y2

diff

1- canvas.create_rectangle(self.l,self.t,self.r-self.l,self.b-self.t) 2+ canvas.create_rectangle(self.l, self.t, self.r, self.b)

修正後のコード

diff

1import time 2from tkinter import * 3 4DURATION = 0.03 5 6 7class Ball: 8 def __init__(self, id, x, y, d, vx, vy, c): 9 self.id = id 10 self.x = x 11 self.y = y 12 self.d = d 13 self.vx = vx 14 self.vy = vy 15 self.c = c 16 17 def move(self): 18 self.x = self.x + self.vx 19 self.y = self.y + self.vy 20 21 def redraw(self): 22 d = self.d 23 canvas.coords(self.id, self.x - d, self.y - d, self.x + d, self.y + d) 24 25 26class Border: 27 def __init__(self, l, r, t, b): 28 self.l = l 29 self.r = r 30 self.t = t 31 self.b = b 32 33 def draw(self): 34 canvas.create_rectangle(self.l, self.t, self.r, self.b) 35 36 37def make_ball(x, y, d, vx, vy, c): 38 id = canvas.create_rectangle(x, y, x + d, y + d, fill=c, outline=c) 39 ball = Ball(id, x, y, d, vx, vy, c) 40 return ball 41 42 43tk = Tk() 44canvas = Canvas(tk, width=800, height=800, bd=0) 45canvas.pack() 46 47border = Border(100, 700, 100, 500) 48border.draw() 49 50balls = [ 51 make_ball(150, 150, 20, 2, 3, "darkblue"), 52 make_ball(200, 250, 25, -4, -3, "orange"), 53 make_ball(300, 350, 10, -2, 6, "green"), 54 make_ball(400, 450, 5, 10, -6, "darkgreen"), 55] 56 57while True: 58 for ball in balls: 59 ball.move() 60 if ball.x - ball.d < border.l: 61 ball.vx = -ball.vx 62 if ball.y - ball.d < border.t: 63 ball.vy = -ball.vy 64 if ball.x + ball.d >= border.r: 65 ball.vx = -ball.vx 66 if ball.y + ball.d >= border.b: 67 ball.vy = -ball.vy 68 ball.redraw() 69 tk.update() 70 time.sleep(DURATION) 71

投稿2020/05/15 16:30

tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ramurezun

2020/05/17 12:16

回答ありがとうございます。  正常に作動しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問