目次
- 問題パネル
- 描画処理
- プロパティ設定関数
- クリック処理
問題パネル
■描画処理
問題パネルにはサムネイル、難易度、タイトルなどが表示され、押下することでその問題を解くことができる。 QuestPanel はそのためのシーンだ。
ノードツリーは下図のようになっている。

QuestPanel のクラスは ReferenceRect
アプリ実行時のパネル外観は下図のようになっており、これは _draw() をオーバライドすることで実現している。

func _draw():
# 外枠
var style_box = StyleBoxFlat.new()
style_box.set_corner_radius_all(RADIUS)
style_box.bg_color = Color.darkslategray if !mouse_pushed else Color.gray
style_box.border_color = Color.green if !mouse_pushed else Color.darkslategray
style_box.set_border_width_all(2)
style_box.shadow_offset = Vector2(4, 4) if !mouse_pushed else Vector2(0, 0)
style_box.shadow_size = 8 # if !mouse_pushed else 4
draw_style_box(style_box, Rect2(POSITION, SIZE))
StyleBoxFlat クラスを使って、影・枠付きラウンド矩形を描画している。 その方法は簡単で、上記のようにインスタンスを生成し、各種パラメータを設定し、draw_style_box() をコールするだけだ。
問題サムネイルの表示部分のコードを下記に示す。
func _draw():
.....
# サムネイル
var col = Color.lightgray if ans_iamge.empty() else Color("#ffffef") if time >= 0 else Color("#ffffc0") #.lightyellow
draw_rect(Rect2(THUMBNAIL_X-2, THUMBNAIL_POS-2, THUMBNAIL_WIDTH+4, THUMBNAIL_WIDTH+4), col)
if !ans_iamge.empty():
for y in range(IMG_HEIGHT):
var py = y * TNCELLWD + THUMBNAIL_POS
var mask = 1 << IMG_WIDTH
for x in range(IMG_WIDTH):
mask >>= 1
if (ans_iamge[y] & mask) != 0:
var px = x * TNCELLWD + THUMBNAIL_X
draw_rect(Rect2(px, py, TNCELLWD, TNCELLWD), Color.black)
問題がクリア済みかどうか、途中経過かどうかで背景色を決め、draw_rect() でサムネイル領域を塗りつぶしている。
次に、問題がクリア済みの場合は、サムネイル表示を行っている。 解答のイメージは ans_iamge[] にビットマップとして格納されているので、 ビットマスクをシフトしながら当該ビットが1かどうかをチェックして、1であれば draw_rect() でその部分のドットを描画している。
■プロパティ設定関数
問題パネルは、問題番号、難易度などのプロパティを持ち、それを設定する関数を用意している。
それらの実装を下記に示す。
var number :int = 0
func set_number(n : int):
number = n
$number.text = "#%d" % n
func set_difficulty(n : int):
$difficulty.text = "Difficulty: %d" % n
$jDiffi.text = "難易度 %d" % n
内容は簡単で、引数で渡されたものをメンバ変数に保存し、ラベルテキストを変更するだけだ。
■クリック処理
ボタンクリック処理のコードを下記に示す。
signal pressed(num)
func _input(event):
if event is InputEventMouseButton:
if event.is_action_pressed("click"): # left mouse button
if get_global_rect().has_point(event.position): #
mouse_pushed = true;
saved_pos = get_global_rect()
update()
elif event.is_action_released("click") && mouse_pushed:
if get_global_rect() == saved_pos:
if get_global_rect().has_point(event.position): #
print("pressed: ", $number.text)
emit_signal("pressed", number) # pressed シグナル発行
mouse_pushed = false;
update()
elif event is InputEventMouseMotion && mouse_pushed: # mouse Moved
if get_global_rect() != saved_pos || !get_global_rect().has_point(event.position): #
mouse_pushed = false;
update()
問題パネル上にマウスカーソルがあるときにマウスボタンが押下されると、_event() がコールされる。 ので、その中で押下アクションかどうかを判定し、押下されたことを記録しておく。
そしてリリースアクションの場合は、マウスカーソルが押下されたパネル上でリリースされた場合は、 クリックされたとみなし、pressed() シグナルを発行している。
押下状態でマウスが移動され、押下されたボタンから外れた場合は mouse_pushed フラグをオフにし、 update() を呼ぶことで再描画を行う。
TechProjin Godot入門 関連連載リンク
Godotで学ぶゲーム制作
さくさく理解するGodot入門 連載目次
標準C++ライブラリの活用でコーディング力UP!
「競技プログラミング風」標準C++ライブラリ 連載目次