前提・実現したいこと
小林 郁夫・佐々木 晃共著の「Pythonによるプログラミング」p160の練習問題6.4に取り組んでいます。最終的にボールがブロックで跳ね返りブロックが消えるアニメーションを作成したいです。しかし、check_blocksのblockが正しく反映されません。自分でも挑戦してみましたが、上手くいきません。ご教授願います。
発生している問題・エラーメッセージ
Traceback (most recent call last):
File "C:\Users\user\Desktop\python\ex06-block.py", line 182, in <module>
box.animate()
File "C:\Users\user\Desktop\python\ex06-block.py", line 162, in animate
self.check_blocks(self.ball,self.block)
File "C:\Users\user\Desktop\python\ex06-block.py", line 145, in check_blocks
if(block.y<ball.y+ball.d/2<block.y+block.h
AttributeError: 'NoneType' object has no attribute 'y'
該当のソースコード
from tkinter import * from dataclasses import dataclass,field import time @dataclass class Ball: id:int x:int y:int d:int vx:int vy:int c:str="black" 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,self.y, self.x+d,self.y+d) @dataclass class Paddle: id:int x:int y:int w:int h:int vy:int = field(init=False,default=0) c:str="green" def move(self): self.y=self.y+self.vy def redraw(self): canvas.coords(self.id,self.x,self.y, self.x+self.w,self.y+self.h) def set_v(self,v): self.vy=v def stop(self): self.vy=0 @dataclass class Block: id:int x:int y:int w:int h:int c:str def redraw(self): canvas.coords(self.id,self.x,self.y, self.x+self.w,self.y+self.h) def delete(self): canvas.delete(self.id) @dataclass class Box: id:int west:int north:int east:int south:int ball:Ball paddle:Paddle block:Block paddle_v:int duration:float def __init__(self,x,y,w,h,duration): self.west,self.north=(x,y) self.east,self.south=(x+w,y+h) self.ball=None self.paddle=None self.block=None self.blocks=[] self.duration=duration self.paddle_v=5 def make_ball(self,x,y,d,vx,vy): id=canvas.create_oval(x,y,x+d,y+d, fill="black",outline="black") return Ball(id,x,y,d,vx,vy) def make_walls(self): canvas.create_rectangle(self.west,self.north,self.east,self.south) def check_wall(self,ball): if ball.x+ball.vx<=self.west or ball.x+ball.d+ball.vx>=self.east: ball.vx=-ball.vx if ball.y+ball.vy<=self.north or ball.y+ball.d+ball.vy>=self.south: ball.vy=-ball.vy def set_ball(self): self.ball=self.make_ball(self.west+10,self.north+10,10,4,2) def make_paddle(self,x,y,w,h,c): id=canvas.create_rectangle(x,y,x+w,y+h, fill=c,outline=c) return Paddle(id,x,y,w,h) def check_paddle(self,ball,paddle): if(ball.y+ball.d/2>=paddle.y and paddle.x<=ball.x+ball.d and ball.y+ball.d/2<=paddle.y+paddle.h): ball.vx=-ball.vx def set_paddle(self): self.paddle=self.make_paddle(self.east-20,(self.north+self.south)/2-10, 10,20, "green") def up_paddle(self,event): self.paddle.set_v(-self.paddle_v) def down_paddle(self,event): self.paddle.set_v(self.paddle_v) def stop_paddle(self,event): self.paddle.stop() def make_block(self,x,y,w,h,c): id=canvas.create_rectangle(x,y,x+w,y+h, fill=c,outline=c) return Block(id,x,y,w,h,c) def set_blocks(self,n,s): for x in range(n): block=self.make_block(self.west+10*x,self.south-30, 5,20,"red") for x in range(s): block=self.make_block(self.west+10*x,self.south-60, 5,20,"blue") self.blocks.append(block) def check_blocks(self,ball,block): if(block.y<ball.y+ball.d/2<block.y+block.h and(block.x<=ball.x<=block.x+block.w or block.x<=ball.x+ball.d<=block.x+block.w)): ball.vx=-ball.vx self.block.delete() self.blocks.remove() def animate(self): while True: self.ball.move() self.paddle.move() self.check_wall(self.ball) self.check_paddle(self.ball,self.paddle) self.ball.redraw() self.paddle.redraw() for block in self.blocks: self.check_blocks(self.ball,self.block) self.block.redraw() time.sleep(self.duration) tk.update() tk=Tk() canvas=Canvas(tk,width=800,height=800,bd=0) canvas.pack() box=Box(100,100,300,200,0.05) box.make_walls() canvas.bind_all("<KeyPress-Up>",box.up_paddle) canvas.bind_all("<KeyPress-Down>",box.down_paddle) canvas.bind_all("<KeyRelease-Up>",box.stop_paddle) canvas.bind_all("<KeyRelease-Down>",box.stop_paddle) box.set_ball() box.set_paddle() box.set_blocks(4,4) box.animate()
試したこと
補足情報(FW/ツールのバージョンなど)
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/05/20 03:17 編集
2020/05/20 12:51