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

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

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

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

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

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

Q&A

解決済

1回答

2471閲覧

【python】pygameで構築した画面上でRGB判定がしたいです。

Syake.P

総合スコア17

Pygame

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

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

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

0グッド

0クリップ

投稿2021/05/04 08:43

前提・実現したいこと

python(pygame)を使って迷路を作っています。
現在、迷路のマップ表示、スタート・ゴールの表示、道と壁の表示、進んだ道(クリックされた場所)に印をつける機能ができました。
しかし、壁をクリックしても、道と同じように印がついてしまうという問題が発生しました。
そこで、クリックされた場所の色を判定して、その色が壁の色(黒)だったら、印をつけないというプログラムを実装しようとしましたがうまくいきませんでした。
お手数ですが、回答お願いします。

###現在のプログラム
長いプログラムなのでGithubにあげました。
demoがプログラム、imagesの中にプログラム中で使っている画像が入っています。
https://github.com/Syake-P/Syake.P-teratail.git

###理想のプログラム
理想のプログラムです。
RGB判定に必要な部分のみ抜粋しています。

python

1def game_loop(): 2 running = True 3 while running: 4 for event in pygame.event.get(): 5 if event.type == pygame.QUIT: 6 running = False 7 if event.type == MOUSEBUTTONDOWN: 8 mouse_x, mouse_y = event.pos #←マウスの座標取得 もし使うようでしたら参考にしてください 9 #RGB値を取得 10 if #RGB値が白(255,255,255)だったら: 11 print("white") 12 elif #RGB値が黒(0,0,0)だったら: 13 print("black") 14 elif #RGB値が黄色(255,255,0)だったら: 15 print("yellow")

###試したこと
https://techacademy.jp/magazine/51035
上記のサイトに載っているOpenCVによるRGB判定を参考にできないかと考え、まずはサイトに載っていたサンプルプログラムを画像の情報のみ変えて動かしてみたら、エラーが発生しました。
その時のコードです。

python

1import cv2 2 3img = cv2.imread('square.png', cv2.IMREAD_COLOR) 4window_name = 'img' 5 6def onMouse(event, x, y, flags, params): 7 if event == cv2.EVENT_LBUTTONDOWN: 8 crop_img = img[[y], [x]] 9 b_val = crop_img.T[0].flatten().mean() 10 g_val = crop_img.T[1].flatten().mean() 11 r_val = crop_img.T[2].flatten().mean() 12 print("R: {}, G: {}, B: {}".format(r_val, g_val, b_val)) 13 14cv2.imshow(window_name, img) 15cv2.setMouseCallback(window_name, onMouse) 16cv2.waitKey(0)

発生したエラーメッセージ

Traceback (most recent call last): File "c:/Users/○○/Desktop/python programs/images/demo.py", line 14, in <module> cv2.imshow(window_name, img) cv2.error: OpenCV(4.5.1) C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-xeqjxthj\opencv\modules\highgui\src\window.cpp:376: error: (-215:Assertion failed) size.width>0 && size.height>0 in function 'cv::imshow'

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

OpenCVでの判定について書きましたが、OpenCVにこだわりはありません。

python3.8.2,pygame2.0.1を使用。
PCのOSはWindows,VScodeを使用。

###最後に
僕は壁の判定を色によって行うことを思いつきましたが、ほかにもクリックされた画像によって判断する方法などがあると思います。ほかの方法で回答していただいても構いません。
どうぞ、よろしくお願いします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

pygameで構築した画面上でRGB判定

Surface.get_at で指定位置の色情報を得られます。

python

1 2r, g, b, _ = display.get_at((mouse_x, mouse_y)) 3

ですが、"S", "G" 位置での判定が別に必要だったり、
壁の色を変更した際は、コードも変更が必要になったりするので、
マップデータ map_information を参照して壁かどうかを判定した方が良いです。


オフトピックですが、気付いた点

関数内のrunning 変数は、ローカル変数(その関数内でのみ有効)になっているので
global 宣言しないと、意図通りに動きません。
(gameExit() を呼び出しても、game_loop() 内の running の値は変わらない)

投稿2021/05/04 09:21

teamikl

総合スコア8760

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

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

Syake.P

2021/05/05 09:15

丁寧なご回答ありがとうございました。とても助かりました。 "S","G"の判定はできるようになっています。mouse_click(),column_judgment()の中に入っています。 runningの件、おっしゃる通りです。というかどちらにしろquit()するので、running = False は必要ありませんね。 後学のために一つ教えていただきたいです。 r, g, b, _ = display.get_at((mouse_x, mouse_y))のr, g, b, _ の部分についてです。 最後の"_"の部分には、黒でも白でも常に255が返ってきます。この値は何でしょう?
teamikl

2021/05/05 10:19

RGBA 形式の 透明度を現すAlphaチャンネルの値 で、 不透明の場合 255 になります。 http://westplain.sakuraweb.com/translate/pygame/Surface.cgi#Surface.get_at > running = False は必要ありませんね 逆で、ここは running フラグを変化させて イベントループを抜けて終了という手順を取った方が良いです。 (イベントループの終了running = False と、 リソース解放 pygame.quit() は別の処理に別ける) 理由: 現状では不要かもしれませんが、 リソースの解放をアプリケーション終了時に行う場合、 ウィンドウが一時的に止まったりする要因になったりします。 イベントループ内で quit() を呼び出すのは、 イベント処理を強制終了することになるので、 イベントループは中断されたままの状態=応答なしになります。 リソースの解放が一瞬で終わるうちは、直ぐに終了するので 気にならない程度の遅延かもしれませんが、 終了時に操作不可能なウィンドウが長く残るような状況になれば、 この辺りを疑ってみてください。
teamikl

2021/05/05 10:25

>逆で、ここは running フラグを変化させて >イベントループを抜けて終了という手順を取った方が良いです。 訂正。質問のコードでは running = False で終了になってましたね。 github のコードが if event.type == pygame.QUIT: gameExit()#終了処理 とイベントループ内で呼び出す形になっていたので、そちらに対してのコメントでした。 質問のコード通りなら、running は、ローカル変数で問題ありません。 gameExit() に running = False は必要ない で正しいです。
Syake.P

2021/05/05 12:22

毎回丁寧にコメントしてくださり、とても分かりやすく、助かります。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問