【Python/tkinter】当たり判定単体の動作確認アプリを作る

Python の tkinter を用いて「当たり判定単体の動作確認アプリ」を作ったのでその紹介をしていきます。

ちなみに「当たり判定方法」の解説ページではないので注意してください。

ご自身が実装された当たり判定の動作を「視覚的」に確認する際の参考情報を提供するページであり、アプリもご自身の行いたい当たり判定に応じて変更する必要があります。

当たり判定単体の動作確認アプリとは

正直たいしたものではなくて、「マウスカーソルの位置に応じて移動する矩形」と「他の矩形」が当たった時に矩形の色を変更するだけのアプリです。

当たり判定動作確認アプリの動作を示すアニメ

ちょっとしたゲームを作っていて当たり判定を実装した時に、「これ本当にうまく当たり判定できてるのか?」と不安だったので、tkinter を利用してこんな感じの当たり判定単体の動作確認アプリを作ってみました。

一方の矩形がマウスカーソルの位置に応じて移動するので、矩形をいろんな方向から当ててみたり、当たるか当たらないかのギリギリのところで上手く当たり判定が効いているかどうかを確認することができます。

また、マウスを動かすだけで当たり判定の動作確認ができるので確認も簡単に行えると思います。

今回は簡単な矩形同士の当たり判定のみしか行なっていませんが(一応円同士の当たり判定用のスクリプトも紹介します)、他の図形等でも応用すれば同様のことができると思います。考え方等も参考になる場合もあるかなぁと思って紹介させていただくことにしました。

当たり判定単体の動作確認アプリのスクリプト

ではアプリのスクリプトの紹介と簡単な解説を行なっていこうと思います。

スポンサーリンク

スクリプト

今回作成した当たり判定単体の動作確認アプリのスクリプトは下記のようになります。

矩形同士の当たり判定の動作確認
import tkinter


def isCollided(a_coords, b_coords):

	# 当たってるかどうかを判断する
	a_x1, a_y1, a_x2, a_y2 = a_coords
	b_x1, b_y1, b_x2, b_y2 = b_coords

	c_x1 = max(a_x1, b_x1)
	c_y1 = max(a_y1, b_y1)
	c_x2 = min(a_x2, b_x2)
	c_y2 = min(a_y2, b_y2)

	if c_x1 < c_x2 and c_y1 < c_y2:
		return True
	else:
		return False


def move(event):

	# マウスの位置からマウス用の矩形の座標計算
	x1 = event.x - mouse_rect_width / 2
	y1 = event.y - mouse_rect_height / 2
	x2 = event.x + mouse_rect_width / 2
	y2 = event.y + mouse_rect_height / 2

	mouse_coords = (x1, y1, x2, y2)

	# マウス用の矩形の座標を変更
	canvas.coords(mouse_rect, mouse_coords)

	if isCollided(mouse_coords, target_coords):
		# 当たってたら相手の矩形の色をオレンジにする
		canvas.itemconfig(target_figure, fill="orange")
	else:
		# 当たってなかったら相手の矩形の色を白に戻す
		canvas.itemconfig(target_figure, fill="white")


app = tkinter.Tk()

canvas = tkinter.Canvas(
	app,
	width=400,
	height=300,
	highlightthickness=0
)
canvas.pack()

# 矩形の座標を設定
target_coords = (95, 130, 250, 200)

# マウス用の矩形の幅と高さを設定
mouse_rect_width = 80
mouse_rect_height = 80

# 矩形を描画
target_figure = canvas.create_rectangle(
	target_coords,
	fill="white"
)

mouse_rect = canvas.create_rectangle(
	0, 0, 0, 0,  # move関数で正しく設定
	fill="white"
)

# マウスが動いたときにmoveを実行するように設定
app.bind("<Motion>", move)

app.mainloop()

スクリプトを起動してマウスカーソルを移動すれば、そのマウスカーソルに合わせて矩形が移動し、元々描画されていた矩形に当たった際に色が変化することが確認できると思います。

当たり判定動作確認アプリの動作を示すアニメ

このアプリは一言でいえば、上記のスクリプトにおける isCollided 関数で上手く当たり判定の処理が実装できているかどうかを視覚的に確認するアプリになります。

isCollided 関数が当たったと判定した場合(True を返却した場合)、一方の矩形の色がオレンジ色に変化し、それ以外の場合は矩形の色は白色に変化する(or 白色のままになる)ようになっています。

ですので、マウスカーソルの移動によって図形を移動させ、他の図形に当たったと判定されて欲しい時に色が変化するかどうかを確認することで、isCollided 関数が上手く動作しているかどうかを視覚的に確認することができます。

一応サンプルとして矩形を描画し、isCollided 関数で矩形同士の当たり判定を行うようにしていますが、ご自身が当たり判定を行いたい図形に合わせて描画する図形を変更したり、isCollided 関数の実装を行なっていただければと思います。

スクリプトの解説

ではスクリプトでどのようなことを行なっているのかについて簡単に解説しておきます。

スクリプト起動時の処理

スクリプト起動時には、まずメインウィンドウを tkinter.Canvas() で作成し、さらに tkinter.Canvas() でキャンバスを作成しています。

メインウィンドウとキャンバスを作成する様子

そしてその後、create_rectangle メソッドでキャンバス上に2つの矩形(長方形)を描画しています。

キャンバスに矩形を描画する様子

描画するのが2つとも矩形なのは今回当たり判定の動作確認する対象が矩形同士であるからであって、ここは当たり判定を行いたい図形等に応じて変更して貰えば良いと思います。

この図形の描画に関しては下記ページで解説していますので、詳しく知りたい方は読んでみていただけると幸いです。

tkinterキャンバスに図形を描画する方法解説ページのアイキャッチTkinterの使い方:Canvasクラスで図形を描画する

1つ目に描画する矩形の座標は target_coords で管理しています。ですので、この target_coords を変更すれば、1つ目に描画する矩形のサイズや位置を変更することができます。この1つ目の矩形に関しては描画後に移動は行いません。

その一方で、2つ目に描画する矩形はマウスカーソルに合わせて移動する矩形となります。そのため、スクリプト起動直後に描画する矩形の座標は全て 0 に設定し、後ほど説明するマウス移動時に実行される関数 move の方で座標を設定するようにしてます。

したがって、スクリプト起動時には矩形は描画されてはいるものの視覚的に確認できない状態になっています。ですが、マウスを移動すれば矩形の座標がちゃんと設定され、矩形が視覚的に確認できる状態なります。

あとは、bind メソッドを実行し、マウスが移動された際に move 関数が実行されるように設定しています。

bind メソッドについては下記ページで解説していますので、詳細を知りたい方はこちらのページを参照していただければと思います。

イベント処理解説ページのアイキャッチTkinterの使い方:イベント処理を行う

マウス移動時の処理

さらに、マウス移動時に実行される move 関数では、まずマウスの位置を中心とする矩形の座標の設定を行い、さらにキャンバスの coords メソッドを利用して描画済みの矩形の座標の変更を行なっています。

マウスの位置に応じて矩形の座標を変更する様子

これにより、マウスが移動された際に、マウスの移動先に矩形が移動するようになります。

マウスが移動すると矩形の位置も移動する様子

あとは isCollided 関数を実行し、描画されている矩形同士の当たり判定を行なっています。このアプリは前述の通り、この isCollided 関数の動作が正しいかどうかを確認するためのアプリになります。

今回は矩形同士の当たり判定を行うので、isCollided 関数はこの矩形同士の当たり判定に必要な情報を引数で受け取るようにしています。この辺りの引数や当たり判定の処理に関しても描画する図形に応じて変更すれば良いです。

isCollided 関数で True が返却された際には、move 関数の中でキャンバスの itemconfig メソッドにより1つ目の矩形の色をオレンジ色に変更するようにしています。その一方で、isCollided 関数で False が返却された際には1つ目の矩形の色を白色に変更するようにしています。

isCollidedの返却値に応じて矩形の色が変化する様子

したがって、マウスカーソルで矩形を移動させて矩形同士が当たったときにオレンジ色に矩形の色が変わったのであれば、上手く isCollided 関数で当たり判定できていると判断できますし、当たっていないのにオレンジ色に変化する、当たったのに白色のまま等の場合は isCollided 関数で上手く当たり判定ができていないと判断することができます。

上手く当たり判定できていない場合は、isCollided 関数の処理を見直して修正し、再度スクリプトを実行してまた色の変化を確認することで、isCollided 関数でうまく当たり判定できているかどうかの確認をすることができます。

ここで利用したキャンバスの coords メソッドや itemconfig メソッドをはじめとする、描画済みの図形に対して操作を行うメソッドに関しては下記ページで解説しておりますので、詳しく知りたい方はぜひ読んでみてください。

tkinterキャンバスの図形の操作方法解説ページのアイキャッチTkinterの使い方:Canvasクラスで描画した図形を操作する

円同士の当たり判定への変更例

一応前述で紹介したスクリプトを円同士の当たり判定を行うようにしたものも紹介しておきます。

円同士の当たり判定の動作確認
import tkinter
import math

def isCollided(a_coords, b_coords):

	# 当たってるかどうかを判断する
	a_x1, a_y1, a_x2, a_y2 = a_coords
	b_x1, b_y1, b_x2, b_y2 = b_coords

	a_center_x = a_x1 + mouse_radius
	a_center_y = a_y1 + mouse_radius

	b_center_x = b_x1 + target_radius
	b_center_y = b_y1 + target_radius
	
	distance = math.sqrt(pow(a_center_x - b_center_x, 2) + pow(a_center_y - b_center_y, 2))
	
	if distance <= mouse_radius + target_radius:
		return True

	return False

def move(event):

	# マウスの位置からマウス用の円の座標計算
	x1 = event.x - mouse_radius
	y1 = event.y - mouse_radius
	x2 = event.x + mouse_radius
	y2 = event.y + mouse_radius

	mouse_coords = (x1, y1, x2, y2)

	# マウス用の円の座標を変更
	canvas.coords(mouse_rect, mouse_coords)

	if isCollided(mouse_coords, target_coords):
		# 当たってたら相手の矩形の色をオレンジにする
		canvas.itemconfig(target_figure, fill="orange")
	else:
		# 当たってなかったら相手の矩形の色を白に戻す
		canvas.itemconfig(target_figure, fill="white")


app = tkinter.Tk()

canvas = tkinter.Canvas(
	app,
	width=400,
	height=300,
	highlightthickness=0
)
canvas.pack()

# 縁の半径を設定
mouse_radius = 20
target_radius = 50

# 1つ目の中心座標と円の左上・右下の座標を設定
target_center_x = 100
target_center_y = 100

x1 = target_center_x - target_radius
y1 = target_center_y - target_radius
x2 = target_center_x + target_radius
y2 = target_center_x + target_radius

target_coords = (x1, y1, x2, y2)

# 円を描画
target_figure = canvas.create_oval(
	target_coords,
	fill="white"
)

mouse_rect = canvas.create_oval(
	0, 0, 0, 0, # move関数で正しく設定
	fill="white"
)

# マウスが動いたときにmoveを実行するように設定
app.bind("<Motion>", move)

app.mainloop()

実行すれば円同士が当たっている時に一方の円の色がオレンジ色に変化します。

円同士の当たり判定動作確認アプリの動作を示すアニメ

前述で紹介した矩形同士のスクリプトから大きく変更しているように、ちょっとスクリプトを変更すれば他の図形の当たり判定が行えるというわけではないですが、どのあたりを変更すれば良いかのニュアンスは伝わるのではないかと思います。

スポンサーリンク

まとめ

このページでは、Python の tkinter を用いた「当たり判定単体の動作確認アプリ」の紹介を行いました。

動作確認アプリと言いつつ、当たり判定したい図形に応じて描画する図形や当たり判定の実装をご自身で変更する必要があります…。

ただ、視覚的に当たり判定が上手く動作しているかが確認できて分かりやすいと思いますので是非参考にしていただければと思います。

今回紹介したアプリのように、tkinter は簡単に GUI アプリを作成できるため、プログラムの動作を視覚的に確認したい際などにも便利だと思います。

今回は当たり判定処理を対象としましたが、いろんな処理で応用できる考え方だと思います。「この処理の動作を視覚的に確認してみたいなー」と思うことがあれば、是非動作確認用のアプリを作成してみてください!