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

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

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

Pygameは、ビデオゲームの製作用に設計されたクロスプラットフォームのPythonモジュールセットです。Pythonでコンピューターグラフィックスと音声を扱うためのライブラリが含まれています。

Tkinter

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

Python

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

Q&A

1回答

2086閲覧

pythonのtkinterでafter_cancelメソッドの使い方がわかりません

tsuyuni

総合スコア13

Pygame

Pygameは、ビデオゲームの製作用に設計されたクロスプラットフォームのPythonモジュールセットです。Pythonでコンピューターグラフィックスと音声を扱うためのライブラリが含まれています。

Tkinter

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

Python

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

0グッド

0クリップ

投稿2021/07/01 10:34

Pythonでtkinterを使い縦スクロールゲームを作っています。
プレイヤーの操作する車が障害物に当たるとゲームの画面が停止するようにしたいのですが、after_cancelメソッドを使ってみても画面が動き続けてしまいます。どのようにしたらいいのでしょうか。

Python

1import tkinter 2import numpy as np 3 4px = 150 5py = 550 6bgy = 0 7ox_arg = np.random.randint(0,5) 8ox = 60 * ox_arg + 30 9oy = 0 10ot = 0 11bx_arg = np.random.randint(0,4) 12bx = 60 * bx_arg + 60 13by = -300 14bt = -60 15s = 5 16key = "" 17 18def key_down(e): 19 global key 20 key = e.keysym 21 22def key_up(e): 23 global key 24 key = "" 25 26def main(): 27 global key,roop_id 28 scroll() 29 obstacle() 30 barricade() 31 move() 32 animation() 33 col_detection() 34 roop_id = root.after(50, main) 35 36def animation(): 37 global px,py 38 canvas.create_image(px, py, image = player, tag = "PLAYER") 39 40def move(): 41 global px,py,key 42 canvas.delete("PLAYER") 43 if key == "Left" and px > 30: 44 45 px = px - 10 46 47 if key == "Right" and px < 270: 48 49 px = px + 10 50 51def scroll(): 52 global bgy,s 53 bgy = (bgy + s) % 600 54 55 canvas.delete("BGIMAGE") 56 canvas.create_image(150, bgy + 300, image = bg, tag = "BGIMAGE") 57 canvas.create_image(150, bgy - 300, image = bg, tag = "BGIMAGE") 58 59def obstacle(): 60 global ox,oy,ot,s 61 oy = oy + s 62 ot = ot + 1 63 s = s + 0.01 64 if ot > 600 / s + 10: 65 def_ox() 66 ot = 0 67 oy = 0 68 else: 69 canvas.delete("OBSTACLE") 70 canvas.create_image(ox, oy, image = obs, tag = "OBSTACLE") 71 72def barricade(): 73 global bx,by,bt,s 74 by = by + s 75 bt = bt + 1 76 if bt > 600 / s + 10: 77 def_bx() 78 bt = 0 79 by = 0 80 else: 81 canvas.delete("BARRICADE") 82 canvas.create_image(bx, by,image = bar, tag = "BARRICADE") 83 84def def_ox(): 85 global ox_arg,ox 86 ox_arg = np.random.randint(0,5) 87 ox = 60 * ox_arg + 30 88 89def def_bx(): 90 global bx_arg,bx 91 bx_arg = np.random.randint(0,4) 92 bx = 60 * bx_arg +60 93 94def col_detection(): 95 if abs(ox - px) < 45 and abs(oy - py) < 58: 96 gameover() 97 elif abs(bx - px) < 75 and abs(by - py) <60: 98 gameover() 99 else: 100 pass 101 102def gameover(): 103 global roop_id 104 root.after_cancel(roop_id) 105 106 107root = tkinter.Tk() 108root.title("") 109root.bind("<KeyPress>",key_down) 110root.bind("<KeyRelease>",key_up) 111canvas = tkinter.Canvas(width=300,height=600) 112canvas.pack() 113bg = tkinter.PhotoImage(file="road.png") 114player = tkinter.PhotoImage(file="car1.png") 115obs = tkinter.PhotoImage(file="rock.png") 116bar = tkinter.PhotoImage(file="barricade.png") 117main() 118root.mainloop()

開発環境:Python 3.9.5 pygame 2.0.1

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

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

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

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

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

teamikl

2021/07/01 20:03

タグの pygame は使われてないので外しましょう。
guest

回答1

0

画像ファイルがないので実行はできませんが、

after_cancelメソッドを使ってみても画面が動き続けてしまいます。

after_cancel / gameover関数自体は、正常に動作します。

検証用コード

python

1main() 2root.after(1000, gameover) # 1秒後に gameover 関数を呼び出し 3root.mainloop()

障害物に当たるとゲームの画面が停止するようにしたい

gameover() が呼ばれてないのではないでしょうか。 訂正: 呼ばれてました
変数の内容を画面に表示する等して、衝突の判定以前を見直してみて下さい。

python

1def col_detection(): 2 canvas.delete("TEXT") 3 canvas.create_text( 4 (0,0), 5 text=f"{[px, py], [int(ox), int(oy)], [int(bx), int(by)]}" 6 f"O: {abs(int(ox - px)), abs(int(oy - py))}" 7 f"B: {abs(int(bx - px)), abs(int(by - py))}", 8 tag="TEXT", anchor="nw") 9 10 # 略

予測ですが、問題点は

python

1# main関数内 2 3 col_detection() # <-- 関数内で gameover/after_cancel が呼ばれる 4 roop_id = root.after(150, main) # <-- cancel 後に再度タイマーが開始する 5

解決策(案のみ)
col_detection() で戻り値を返して、衝突時は root.after を呼ばないようにする。

更にいうと、この場合は after_cancel も不要で、
衝突時に root.after を呼ばなくするだけでも画面の停止になります。

投稿2021/07/01 19:43

編集2021/07/01 19:45
teamikl

総合スコア8760

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問