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

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

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

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

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

Q&A

解決済

1回答

780閲覧

AttributeError: 'DoorSprite' object has no attribute 'game'

tom_honmono

総合スコア22

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

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

0グッド

0クリップ

投稿2020/04/13 20:49

pythonで始めよう!で学習を進めています。ゲームを作っているのですが、どうしてもエラーメッセージが出てしまいます。
自分のコードを回答と比較し何回も見直しましたが何が違うのかわかりません。この本が正しいのであれば、このコードに大きく間違っている部分はないと思います。どこか小さなミスをしているのか、解決方法がわかりません。

python

1from tkinter import* 2import random 3import time 4 5class Game: 6 def __init__(self): 7 self.tk=Tk() 8 self.tk.title("ミスタースティックマンの脱出") 9 self.tk.resizable(0,0) 10 self.canvas=Canvas(self.tk,width=500,height=500,highlightthickness=0) 11 self.tk.wm_attributes("-topmost",1) 12 self.canvas.pack() 13 self.tk.update() 14 self.canvas_height=500 15 self.canvas_width=500 16 17 self.bg=PhotoImage(file="haikei.gif") 18 w=self.bg.width() 19 h=self.bg.height() 20 for x in range(0,5): 21 for y in range(0,5): 22 self.canvas.create_image(x*w,y*h,image=self.bg,anchor='nw') 23 self.sprites=[] 24 self.running=True 25 26 #upok 27 28 def mainloop(self): 29 while 1: 30 if self.running==True: 31 for sprite in self.sprites: 32 sprite.move() 33 self.tk.update_idletasks() 34 self.tk.update() 35 time.sleep(0.01) 36 37 #up1missindent 38class Coords: 39 def __init__(self,x1=0,y1=0,x2=0,y2=0): 40 self.x1=x1 41 self.y1=y1 42 self.x2=x2 43 self.y2=y2 44 45def within_x(co1,co2): 46 if(co1.x1>co2.x1 and co1.x1<co2.x2)or(co1.x2>co2.x1 and co1.x2<co2.x2)or(co2.x1>co1.x1 and co2.x1<co1.x2)or(co2.x2>co1.x1 and co2.x2<co1.x2): 47 return True 48 else: 49 return False 50 51def within_y(co1,co2): 52 if(co1.y1>co2.y1 and co1.y1<co2.y2)or(co1.y2>co2.y1 and co1.y2<co2.y2)or(co2.y1>co1.y1 and co2.y1<co1.y2)or(co2.y2>co1.y1 and co2.y2<co1.y2): 53 return True 54 else: 55 return False 56 57#upok 58 59def collided_left(co1,co2): 60 if within_y(co1,co2): 61 if co1.x1<=co2.x2 and co1.x1>=co2.x1: 62 return True 63 return False 64 65def collided_right(co1,co2): 66 if within_y(co1,co2): 67 if co1.x2>=co2.x1 and co1.x2<=co2.x2: 68 return True 69 return False 70 71def collided_top(co1,co2): 72 if within_x(co1,co2): 73 if co1.y1<=co2.y2 and co1.y1>=co2.y1: 74 return True 75 return False 76 77def callided_bottom(y,co1,co2): 78 if within_x(co1,co2): 79 y_calc=co1.y2+y 80 if y_calc>=co2.y1 and y_calc<=co2.y2: 81 return True 82 return False 83#upok 84 85class Sprite: 86 def __init__(self,game): 87 self.game=game 88 self.endgame=False 89 self.coodinates=None 90 91 def move(self): 92 pass 93 94 def coords(self): 95 return self.coordinates 96 97#upok 98 99class PlatformSprite(Sprite): 100 def __init__(self,game,photo_image,x,y,width,height): 101 Sprite.__init__(self,game) 102 103 self.photo_image=photo_image 104 self.image=game.canvas.create_image(x,y,image=self.photo_image,anchor="nw") 105 self.coordinates=Coords(x,y,x + width,y + height) 106 107#upok 108 109class StickFigureSprite(Sprite): 110 def __init__(self,game): 111 Sprite.__init__(self,game) 112 113 self.images_left=[ 114 PhotoImage(file="stickman2a.gif"), 115 PhotoImage(file="stickman2b.gif"), 116 PhotoImage(file="stickman2c.gif") 117 ] 118 self.images_right=[ 119 PhotoImage(file="stickman1a.gif"), 120 PhotoImage(file="stickman1b.gif"), 121 PhotoImage(file="stickman1c.gif") 122 ] 123 self.image=game.canvas.create_image(200,470,image=self.images_left[0],anchor='nw') 124 125 self.x=-2 126 self.y=0 127 self.current_image=0 128 self.current_image_add=1 129 self.jump_count=0 130 self.last_time=time.time() 131 self.coordinates=Coords() 132 133 game.canvas.bind_all('<KeyPress-Left>',self.turn_left) 134 game.canvas.bind_all('<KeyPress-Right>',self.turn_right) 135 game.canvas.bind_all('<space>',self.jump) 136#upok 137 def turn_left(self,evt): 138 if self.y==0: 139 self.x=-2 140 141 def turn_right(self,evt): 142 if self.y==0: 143 self.x=2 144 145 def jump(self,evt): 146 if self.y==0: 147 self.y=-4 148 self.jump_count=0 149 150 def animate(self): 151 if self.x !=0 and self.y==0: 152 if time.time()-self.last_time>0.1: 153 self.last_time=time.time() 154 self.current_image+=self.current_image_add 155 if self.current_image>=2: 156 self.current_image_add=-1 157 if self.current_image<=0: 158 self.current_image_add=1 159 160 if self.x<0: 161 if self.y !=0: 162 self.game.canvas.itemconfig(self.image,image=self.images_left[2]) 163 else: 164 self.game.canvas.itemconfig(self.image,image=self.images_left[self.current_image]) 165 166 elif self.x>0: 167 if self.y !=0: 168 self.game.canvas.itemconfig(self.image,image=self.images_right[2]) 169 else: 170 self.game.canvas.itemconfig(self.image,image=self.images_right[self.current_image]) 171#up ok 172 def coords(self): 173 xy=self.game.canvas.coords(self.image) 174 self.coordinates.x1=xy[0] 175 self.coordinates.y1=xy[1] 176 self.coordinates.x2=xy[0]+27 177 self.coordinates.y2=xy[1]+30 178 return self.coordinates 179 180 def move(self): 181 self.animate() 182 if self.y<0: 183 self.jump_count+=1 184 if self.jump_count>20: 185 self.y=4 186 if self.y>0: 187 self.jump_count-=1 188 189 co=self.coords() 190 left=True 191 right=True 192 top=True 193 bottom=True 194 falling=True 195#upok 196 if self.y>0 and co.y2>=self.game.canvas_height: 197 self.y=0 198 bottom=False 199 elif self.y<0 and co.y1<=0: 200 self.y=0 201 top=False 202 203 if self.x>0 and co.x2>=self.game.canvas_width: 204 self.x=0 205 right=False 206 elif self.x<0 and co.x1<=0: 207 self.x=0 208 left=False 209 210 for sprite in self.game.sprites: 211 if sprite==self: 212 continue 213 sprite_co=sprite.coords() 214 if top and self.y<0 and collided_top(co,sprite_co): 215 self.y=-self.y 216 top=False 217 218 if bottom and self.y>0 and collided_bottom(self.y,co,sprite_co): 219 self.y=sprite_co.y1-co.y2 220 if self.y<0: 221 self.y=0 222 bottom=False 223 top=False 224 225 if bottom and falling and self.y==0 and co.y2<self.game.canvas_height and collided_bottom(1,co,sprite_co): 226 falling=False 227 228 if left and self.x<0 and collided_left(co,sprite_co): 229 self.x=0 230 left=False 231 if sprite.endgame: 232 self.game.running=False 233 234 if right and self.x>0 and collided_right(co,sprite_co): 235 self.x=0 236 right=False 237 if sprite.endgame: 238 self.game.running=False 239 if falling and bottom and self.y==0 and co.y2<self.game.canvas_height: 240 self.y=4 241 self.game.canvas.move(self.image,self.x,self.y) 242#upok 243class DoorSprite(Sprite): 244 def __init__(self,game,photo_image,x,y,width,height): 245 Sprite.__init__(self.game) 246 self.photo_image=photo_image 247 self.image=game.canvas.create_image(x,y,image=self.photo_image,anchor='nw') 248 self.coordinates=Coords(x,y,x+(width/2),y+height) 249 self.endgame=True 250#up1missanchor 251g=Game() 252platform1=PlatformSprite(g,PhotoImage(file="yuka-1.gif"),0,480,100,10) 253platform2=PlatformSprite(g,PhotoImage(file="yuka-1.gif"),150,440,100,10) 254platform3=PlatformSprite(g,PhotoImage(file="yuka-1.gif"),300,400,100,10) 255platform4=PlatformSprite(g,PhotoImage(file="yuka-1.gif"),300,160,100,10) 256platform5=PlatformSprite(g,PhotoImage(file="yuka-2.gif"),175,350,66,10) 257platform6=PlatformSprite(g,PhotoImage(file="yuka-2.gif"),50,300,66,10) 258platform7=PlatformSprite(g,PhotoImage(file="yuka-2.gif"),170,120,66,10) 259platform8=PlatformSprite(g,PhotoImage(file="yuka-2.gif"),45,60,66,10) 260platform9=PlatformSprite(g,PhotoImage(file="yuka-3.gif"),170,250,32,10) 261platform10=PlatformSprite(g,PhotoImage(file="yuka-3.gif"),230,200,32,10) 262 263g.sprites.append(platform1) 264g.sprites.append(platform2) 265g.sprites.append(platform3) 266g.sprites.append(platform4) 267g.sprites.append(platform5) 268g.sprites.append(platform6) 269g.sprites.append(platform7) 270g.sprites.append(platform8) 271g.sprites.append(platform9) 272g.sprites.append(platform10) 273 274door=DoorSprite(g,PhotoImage(file="door-1.gif"),45,30,40,35)#294 275g.sprites.append(door) 276 277sf=StickFigureSprite(g) 278g.sprites.append(sf) 279g.mainloop() 280

エラー全文

Traceback (most recent call last):
File "C:/Users/55555/OneDrive/デスクトップ/MRstickman_game.py", line 275, in <module>
door=DoorSprite(g,PhotoImage(file="door-1.gif"),45,30,40,35)#294
File "C:/Users/55555/OneDrive/デスクトップ/MRstickman_game.py", line 246, in init
Sprite.init(self.game)
AttributeError: 'DoorSprite' object has no attribute 'game'

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

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

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

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

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

guest

回答1

0

ベストアンサー

問題の原因

diff

1- Sprite.__init__(self.game) 2+ Sprite.__init__(self, game)

カンマとドット が違います

追記、他のエラー: 関数名typo: callided_bottom -> collided_bottom


問題の探し方(1)

エラーログを下から辿っていきます。
(ライブラリ内の深い場所で出たエラーの場合は、自分の書いたコードまで遡る)

AttributeError: 'DoorSprite' object has no attribute 'game'

エラーの内容は、DoorSpriteオブジェクトは game 属性がないと言われてます。

MRstickman_game.py", line 246, in init

Sprite.__init__(self.game)

Spriteクラスのコンストラクタを呼んでいるので、
クラスが定義されてる箇所を探します。

python

1class Sprite: 2 def __init__(self,game): 3 self.game=game

Sprite.__init__ が要求する引数は self と game ですが、
Sprite.__init__(self.game)self.game を引数に渡そうとしています。
.gameSprite.__init__ の中で設定されるので、
DoorSprite の時点では参照できない為エラーとなります。

コードを見ただけでは解り難いかもしれませんが、
この部分だけでも読みやすく整形してみると良いです。

対策としては、コーディングスタイルで
ドットの場合はくっつける。カンマの場合は1文字離す、
とすると区別しやすくなります。(自動で整形してくれるツール等もあります)

python

1class Sprite: 2 def __init__(self, game): 3 self.game = game

探し方(2)

ソースコード等のデータが提供されてることがあるので、
書籍の公式サイトを探します。原書がある場合はその情報を探します。

Code Snippets from the Book](http://jasonrbriggs.com/python-for-kids/code.html)
例題のコード、ゲームですぐ使えるGIF画像などが、原著者によるサポートページ(英語)からダウンロードできます。

chapter15-17 辺りが該当のコードです。
完成形だと思われるコード stickmangame7.py と、比較してみます。
比較には「diff」と呼ばれるツールを用います。(結果の一部を抜粋)

イメージ説明

専用のプログラムだったり、エディターの機能にあったりするので調べてみてください。
2つのファイルを与えると、差分(記述が異なる部分)のみを取り出しレポートしてくれます。

ブラウザ上で験せるサイトもありますが、頻繁にチェックする場合は、
エディタから確認できるものが便利です。

投稿2020/04/13 21:48

編集2020/04/13 23:00
teamikl

総合スコア8664

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

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

tom_honmono

2020/04/13 23:36

見落としていました、ありがとうございます。diffというツールも探してこれから使ってみたいと思います。いつも丁寧にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問