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

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

ただいまの
回答率

90.86%

  • Python

    6291questions

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

迷路ゲームのアイテム取得時の挙動について

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 159

bemabema

score 9

はじめまして。プログラム初心者です。

「12歳から始めるゼロからのpythonゲームプログラミング教室」という初心者向けの本を読みながら勉強しています。
その中の迷路ゲーム製作中によくわからない点があったのお聞かせ願いたいです。

イメージ説明

カーソルをクリックして鍵を取りゴールへ向かうゲームです。支持に従い制作し、プログラム自体は全く問題ありませんでした。
ただその中で鍵に位置が重なると鍵のイメージが消える箇所について、本に以下の文章が書いてあったのですが、理解できませんでした。

鍵を描画するときにタグを付けておいて消す方法もいいのですが、今回はmap_dataを書き換えてからdraw_map関数を呼び出す方法で鍵を消します。
map_data[y][x]に0を代入し、次にdelete関数を使ってキャンバス上のすべての部品を消します。すべての部品を消したいときは"all"という特別なタグを指定します。あとはdraw_map関数を呼び出すだけです。

以下がその部分になります。(コード全文は一番最後に記載します)

# 移動先のチェック
def check_move (x, y):
    global brave_x, brave_y, flag_key
    if x>=0 and x<MAX_WIDTH and y>=0 and y<MAX_HEIGHT:
        p = map_data[y][x]
        if p == 1:
            return
        elif p == 3:
            flag_key = True
            map_data[y][x] = 0
            canvas.delete("all")
            draw_map()
        elif p == 2:
            if flag_key == True:
                ending()
            else:
                return
        brave_x = x
        brave_y = y
        canvas.coords("brave", brave_x*62+31, brave_y*62+31)

素人考えで描画のデータが3(鍵)から0(道)に変わったならそれで消えたことになるのではと思ったので、試しに①「canvas.delete("all") draw_map()」を削除したら鍵は消えませんでした。

次に②「canvas.delete("all")」だけ削除したら主人公がその場から動かなくなりました。

これについて質問です。

①の方は0を代入しても上書きされないものなのでしょうか。
②の方は一度消して再描画はちゃんと動くのにただの再描画では動かなくなるのはなぜなのでしょうか。

本の通り書いてちゃんと動いたのだからそれでいいのかもしれませんが、理解できないまま先に進むといつかぶつかりそうな気がしたので質問させていただきました。
あまりに稚拙な質問で申し訳ありません。どうぞ宜しくお願い致します。

※以下にコード全文を記載しておきます。(下記にエラーはなく問題なくendingを迎えられます)

import tkinter

# マップの描画
def draw_map():
    for y in range(0, MAX_HEIGHT):
        for x in range(0, MAX_WIDTH):
            p = map_data[y][x]
            canvas.create_image(x*62+31, y*62+31, image=images[p])
    # 主人公の表示
    canvas.create_image(brave_x*62+31, brave_y*62+31, image=images[4], tag="brave")

# 移動先のチェック
def check_move (x, y):
    global brave_x, brave_y, flag_key
    if x>=0 and x<MAX_WIDTH and y>=0 and y<MAX_HEIGHT:
        p = map_data[y][x]
        if p == 1:
            return
        elif p == 3:
            flag_key = True
            map_data[y][x] = 0
            canvas.delete("all")
            draw_map()
        elif p == 2:
            if flag_key == True:
                ending()
            else:
                return
        brave_x = x
        brave_y = y
        canvas.coords("brave", brave_x*62+31, brave_y*62+31)

# 上ボタンが押された
def click_button_up():
    check_move(brave_x, brave_y-1)
# 下ボタンが押された
def click_button_down():
    check_move(brave_x, brave_y+1)
# 左ボタンが押された
def click_button_left():
    check_move(brave_x-1, brave_y)
# 右ボタンが押された
def click_button_right():
    check_move(brave_x+1, brave_y)

# エンディング作成
def ending():
    canvas.delete("all")
    canvas.create_rectangle(0, 0, 620, 434, fill="black")
    canvas.create_text(300, 200, fill="white", font=("MS ゴシック", 15), text="""ゴールおめでとう。

    だが、君の戦いはまだ始まったばかりだ。

    ………つづく?""")

    # ボタンを無効化
    button_up["state"] = "disabled"
    button_down["state"] = "disabled"
    button_left["state"] = "disabled"
    button_right["state"] = "disabled"

# ウィンドウの作成
root = tkinter.Tk()
root.title("ダンジョン&パイソン")
root.minsize(840, 454)
root.option_add("*font", ["メイリオ", 14])

# ボタン配置
button_up = tkinter.Button(text="↑")
button_up.place(x=720,y=150)
button_up["command"] = click_button_up
button_down = tkinter.Button(text="↓")
button_down.place(x=720,y=210)
button_down["command"] = click_button_down
button_left = tkinter.Button(text="←")
button_left.place(x=660,y=180)
button_left["command"] = click_button_left
button_right = tkinter.Button(text="→")
button_right.place(x=780,y=180)
button_right["command"] = click_button_right

#キャンバス作成
canvas =tkinter.Canvas(width=620, height=434)
canvas.place(x=10, y=10)
canvas.create_rectangle(0, 0, 610, 434, fill="gray",tag="drawField")

# 画像データ読み込み
images = [tkinter.PhotoImage(file="img6/chap6-mapfield.png"),
          tkinter.PhotoImage(file="img6/chap6-mapwall.png"),
          tkinter.PhotoImage(file="img6/chap6-mapgoal.png"),
          tkinter.PhotoImage(file="img6/chap6-mapkey.png"),
          tkinter.PhotoImage(file="img6/chap6-mapman.png"),]

# マップデータ
MAX_WIDTH = 10
MAX_HEIGHT = 7
map_data = [[1, 0, 1, 1, 1, 1, 1, 1, 1, 1],
            [1, 0, 0, 1, 2, 0, 0, 1, 3, 1],
            [1, 1, 0, 1, 1, 1, 0, 1, 0, 1],
            [1, 0, 0, 0, 0, 0, 0, 1, 0, 1],
            [1, 0, 1, 1, 1, 1, 1, 1, 0, 1],
            [1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
            [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]

# 主人公の位置
brave_x = 1
brave_y = 0
flag_key = False


draw_map()
root.mainloop()
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • asahina1979

    2018/04/15 19:23

    ending をむかえたから動けないんじゃ?

    キャンセル

  • bemabema

    2018/04/15 21:57

    回答ありがとうございます。 書き忘れましたが、プログラム自体は全く問題なく、最期まで迎えられますが、なぜ一度消して再描画が必要なのがわからなかったので質問させてもらいました。 疑問の時点ではゴールのフラグが立っていないのでendingを迎えているわけではないようです。

    キャンセル

回答 1

checkベストアンサー

+2

回答します
ソースを読ませていただきました。

canvasの仕組みがわかりませんので
憶測で説明します。

たぶんですがアイテムや背景の画像データの”canvas”からの消去は

マップデータ配列にある画像データ(アイテムや背景)の更新
に加えて
「 canvas.create_image(x*62+31, y*62+31, image=images[p])」の実行が必要です。

実際、ソースのマップ作成メソッドでは

p = map_data[y][x]
canvas.create_image(x*62+31, y*62+31, image=images[p])

しています。

描画のデータが3(鍵)から0(道)に変わったならそれで消えたことになる

では

map_data[y][x] = p

を実行しただけでデータを上書きしただけす

これに加えて

canvas.create_image(x*62+31, y*62+31, image=images[0])


でpを0に指定しなおす処理までしないといけないと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/15 23:02

    回答ありがとうございます。
    なるほど、人間から見えれば更新で変わるものの、プログラム的に画像が更新されるということは内部で1.更新2.実行の過程が必要なのですね。
    プログラム勉強し始めで、こういうことまで頭が回らなかったです。今後勉強するにあたって非常に重要なことを聞けた気がします。
    ありがとうございました。

    キャンセル

  • 2018/04/15 23:15

    こちらこそお役に立ててよかったです。

    Tkinterのドキュメントを一度お読みになり
    さらにライブラリの.pyソースも目を通すと
    そちらの本よりも良いゲームが作れるかもしれませんね。

    一般のゲームプログラミング理論
    ・アイテムの描画、更新
    ・画面シーンの切り替え
    ・LOOPと割り込み処理、←マルチスレッド処理も関係?

    このあたりを知っていたら、PythonでもC#でも
    3Dライブラリ利用ソフトでも簡単にゲームが作れそうですね。

    Tkinterを使って2Dゲーム、ロールプレーイングを作る ですか
    この変わった利用方法? は自分には驚きでしたね。

    いずれにしてもいい意味で知識がつきました。

    キャンセル

  • 2018/04/15 23:29

    御返事ありがとうございます。
    tkinterを使ってゲームを作るのは変わった方法なのですね。私はまだ入門したてのため、それすら知りませんでした。もしかしたら正規の覚え方とか少し違うのかもしれませんね。現在はどこから勉強すれば良いのかも見えていないですし、せっかく始めたので進めてみたいと思います。
    その後、おすすめしてくださった辺りも含めて本格的に勉強してみたいと思います。その過程でつまづいたら、またどこかでお目にかかるかもしれません。その時お暇でしたらアドバイスいただけたら幸いです。
    ありがとうございました。

    キャンセル

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

  • ただいまの回答率 90.86%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Python

    6291questions

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