自分向けGodot備忘録 #2
今回はボタン系です
2項目くらいごとが見やすいなと思いました
ボタン的な役割を持たせた画像
ボタンそのものは用意されていますが「画像の上にマウスオーバーさせたときに何かさせる」とかそういうのをやる場合はUnityの時もそうですが自前で作ってしまったものの方が扱いがしやすいというのがあります
ButtonNode
└Area2D
├CollisionShape2D
└ボタン用画像(Sprite2D)
このようなSceneがボタン用のNodeになります
CollisionShape2DはShapeをRectangleShape2Dにして、ボタン画像と同じサイズに変更してください
ボタン画像を「とりあえず四角の画像でいいや」でColorRectで作ったら動きませんでした
親NodeのButtonNodeに新規スクリプトをアタッチして、Area2Dのノートタブからinput_eventとmouse_enteredとmouse_exitedを接続してください
これでArea2Dからでるsignalが接続され、対応したコードが3つ追加されています
func _on_area_2d_input_event(viewport, event, shape_idx):
func _on_area_2d_mouse_entered():
func _on_area_2d_mouse_exited():
そこから必要なコードを書いてこうなります
signal BtnClick_R
signal BtnClick_L
signal BtnEnter
signal BtnExit
func _on_area_2d_input_event(viewport, event, shape_idx):
if event is InputEventMouseButton and event.pressed:
if event.button_index == MOUSE_BUTTON_RIGHT:
emit_signal("BtnClick_R")
if event.button_index == MOUSE_BUTTON_LEFT:
emit_signal("BtnClick_L")
func _on_area_2d_mouse_entered():
emit_signal("BtnEnter")
func _on_area_2d_mouse_exited():
emit_signal("BtnExit")
これでCollisionShape2Dの範囲内でマウスを操作するとButtonNodeからボタン信号をだす仕組みができます
func _on_area_2d_input_event内で右クリックと左クリックを検知して、検知したらBtnClick_RとBtnClick_Lを発信させます
_on_area_2d_mouse_enteredはマウスがCollisionShape2Dの範囲内に侵入したときに呼び出されるので、そのときにBtnEnterを発信させます
_on_area_2d_mouse_exitedはマウスがCollisionShape2Dの範囲内から出た時に呼び出されるので、そのときにBtnExitを発信させます
もしマウスオーバーでボタンの画像を変えたり、ボタンの一部を変えたい場合は、_on_area_2d_mouse_enteredと_on_area_2d_mouse_exitedにそのための処理を増やすだけになります
重なったカード画像の一番上を取得する方法
カードゲームの手札などでよくある重なった演出で使う、重なった画像の一番手前のものを取得する方法です
まずカード単体のSceneを上のボタン的なものと同じように作ります
CardNode
└Area2D
├CollisionShape2D
└カード画像(Sprite2D)
CardNodeにアタッチしたスクリプトもほぼ同じで
signal BtnEnter(card_no)
signal BtnExit(card_no)
var CardNo:int
func _on_area_2d_mouse_entered():
emit_signal("BtnEnter", CardNo)
func _on_area_2d_mouse_exited():
emit_signal("BtnExit", CardNo)
ここでの違いはsignalに引数を持たせることです
複数のカードにCardNoという変数を持たせることで、BtnEnterとBtnExitがどこから来た信号なのかをわかるようにします
そしてカードを選択するSceneとして
CardSelectNode
├CardNode_0
└CardNode_1
とします
新規Sceneを作り、その子Nodeとして上記で作ったCardNodeのSceneを入れただけです
CardSelectNodeに新規スクリプトをアタッチして、そこに
@export var CardNode:Array[Node2D]
func _ready():
for i in CardNode.size():
CardNode[i].CardNo = i
CardNode[i].BtnEnter.connect(_SelectAdd)
CardNode[i].BtnExit.connect(_SelectRemove)
func _SelectAdd(card_no):
pass
func _SelectRemove(card_no):
pass
と記述します
そしてエディタ上でCardNodeに子ノードのCardNodeをツリーの上から順に追加してください
これによって、このSceneが動いたら自動的に2つの子Nodeの信号をCardSelectNodeのスクリプトへ接続でき、子Nodeにはそれぞれカード番号が振られます
子Nodeのsignalはそれぞれ
・BtnEnterは_SelectAddに引数付き
・BtnExitは_SelectRemoveに引数付き
への接続となります
そしてここから接続先への処理を記述します
var _SelectCardArray:Array[int]
func _SelectAdd(card_no):
if not card_no in _SelectCardArray:
_SelectCardArray.appent(card_no)
func _SelectRemove(card_no):
if card_no in _SelectCardArray:
_SelectCardArray.erase(card_no)
これによりカードにマウスが乗った場合には「_SelectCardArrayにそのカード番号が無ければ追加」となり、カードからマウスが外れた場合には「_SelectCardArrayにそのカード番号があれば削除」という処理ができるようになりました
そして最後に
func _process(delta):
if _SelectCardArray.size() > 0:
_SelectCardArray.sort()
var _card_index = SelectCardArray.size() - 1
print(_SelectCardArray[_card_index])
とすると、カードにマウスが乗っている時に、マウス直下の一番上に表示されている(ツリーで一番下)のカード番号がデバッグログに表示され続けるようになります
これを_SelectCardArrayへのNodeの登録番号とカード番号を同じにすることで、いろいろな演出や操作ができるようになりました
カードのオブジェクトを動的生成とも相性がよかったです