「 👆 Label と RichTextLabel は見つかるが」
「 👆 フォント・サイズを いくつにするのが適切なのか 現代のディスプレイ事情では 分からんなあ」
「 👆 じゃあ 画面サイズを 1280 x 720 ピクセルに縛ろうぜ?」
「 👆 フォントを適当に設定して……、グリッドが無いと サイズ感をつかめないな」
📖 2D Grid
「 👆 Windows Paint で線を引き、 GIMP で背景色を抜いたぜ」
📖 参考画像
「 近所で入手しやすいアイテムだぜ。8の倍数にアレンジしたぜ」
「 Godot のデフォルトのフォントが クソ で嫌いだぜ。
他の日本人は 誰一人 疑問にも思わず 放置しているのか?」
📖 【Godot】日本語フォントの設定方法 (Godot3.4〜3.5)
「 フォント作成者のページを見にいったら フォント・ファイルをソースに同梱して配布するのをやめてくれといった趣旨が 書いてあった」
「 👇 この M PLUS 1 Code
フォントなら わたしの感覚に合うんだが、オープンソースのゲームに同梱していいんだろうか?」
「 👆 再配布可能なライセンスの フォント・ファイルをダウンロードしてきたぜ」
「 👆 フォント・ファイルを置いても 認識しないようなので、
リソースを新規作成するぜ」
「 👆 説明と画面が違うんで あとは勘で進むぜ。 FontFile
でどうか?」
「 👆 new_font_file.tres
というファイルを作った」
「 多分、 M Plus 1 Code
フォントの作者が 古臭い日本人なのでは?」
「 じゃあ 次は 昔ながらの 古臭いウィンドウを 作ってみましょう」
「 なんで わたしたちのやることは 昔とか、古臭いという 形容詞が付くんだぜ?」
「 あの メッセージ・ウィンドウ、現代では 何て呼ばれてるんだぜ?」
📖 Theme Variation with StyleBoxTexture returns wrong type #66850
「 👆 そんなときは Windows Paint で枠を描いて GIMP で透明度を抜けばいいんだぜ」
「 👆 1、2、3、 …… 全角で1行20文字、3段で
計 60文字でいいの?」
「 シナリオライターに 足らん と言われても ごめんなさい しようぜ」
「 バックが方眼紙だと 落ち着かないから 背景を付けましょう」
「 オープンソースで ばらまくのに ライセンスが適していないフリー素材が あるからな。
素材を揃えるのが 難しいぜ」
「 メッセージ・ウィンドウの最後で点滅してる アレの名前 何だぜ?
アレを作ろうぜ?」
「 アレは 文字だろ。 文字と同じように 輪郭を付けて、ドロップシャドウもしなければ
浮いてしまうだろ」
「 .otf
ファイルを使っているのに 外字が出てくるのか分からん」
「 👆 とりあえず Windows Paint と GIMP で それっぽいのを作って、画面に置いてみようぜ?」
「 スポイトで色を吸ってみたけど、白は (248, 248, 248) で同じなんだけど、
影の色が 違うのよね。影は 半透明にしなきゃ。
あと、フォントには アンチエイリアシングが かかってんのよ」
「 👆 ドロップシャドウも アンチエイリアシングも 見よう見まねで Windows Paint と GIMP で やってみようぜ?」
「 さっきよりは マシな気がするけど、 三角形が でかくて 主張が強い気がするのよねえ」
「 👆 参考に アンダースコアと 逆三角形の文字を横に並べたが、そんなに違うかだぜ?」
「 目の錯覚か 暗く見えるけど もう こんなもんで いいんじゃない?」
「 👇 タイマーを使わなくても、 _process()
を使えば点滅できるんじゃないか?」
extends Label
var count = 0
# サブツリーが全てインスタンス化されたときに呼び出される
# Called when the node enters the scene tree for the first time.
func _ready():
pass
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
count += delta
if 0.75 <= count:
visible = not visible
count -= 0.75
📺 動画
「 Label
コントロールには テキストを全文入れてるじゃないか。
あれを 空っぽにして、1文字ずつ 入れていくということかだぜ?」
「 そのテキストを、別のところに保存しておいて、
時間経過とともに ラベルに追加していけばいいのよ」
extends Label
var count = 0
var text_storage = """お父ん、なんで唐揚げを食べているんだぜ?
ダイエットはどうした?
野菜を TABERO だぜ!
"""
# Called when the node enters the scene tree for the first time.
func _ready():
self.text = ""
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
count += delta
if 0.05 <= count:
if 0 < self.text_storage.length():
self.text += text_storage.substr(0, 1)
text_storage = text_storage.substr(1, self.text_storage.length()-1)
count -= 0.05
📺 動画
「 👆 この動画に映ってるタイプライター風の文字列出力で 充分よ」
「 文字が出終わってから ブリンカーが出るように 合わせてくれだぜ」
「 👇 別のノードの変数を どうやって参照するのか……。調べるか」
📖 [Godot]$(ドルマーク)とget_node関数の違いについて
extends Label
# 点滅用
var is_blink_started = false
var count_of_blink = 0
# タイプライターの文字出力間隔
var count_of_typewriter = 0
# サブツリーが全てインスタンス化されたときに呼び出される
# Called when the node enters the scene tree for the first time.
func _ready():
# 最初は非表示
visible = false
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
# テキストを出し終えたか?
count_of_typewriter += delta
if not is_blink_started and 0.5 <= count_of_typewriter:
var message_window_text = $".."
if message_window_text.get("text_storage").length() < 1:
is_blink_started = true
visible = true
count_of_typewriter -= 0.5
# 点滅
if is_blink_started:
count_of_blink += delta
if 0.75 <= count_of_blink:
visible = not visible
count_of_blink -= 0.75
📺 動画
「 👆 この動画に映ってるメッセージ・ウィンドウで 充分よ」
「 何か どれでも キーを押したかどうかの判定って、どうやんの?」
📖 How to detect if any key is pressed
「 Godot では どんなコレクション・クラスを使えるんだぜ?」
📄 textend_blinker.gd
:
extends Label
# 点滅用
var is_blink_started = false
var count_of_blink = 0
# タイプライターの文字出力間隔
var count_of_typewriter = 0
# サブツリーが全てインスタンス化されたときに呼び出される
# Called when the node enters the scene tree for the first time.
func _ready():
# 最初は非表示
visible = false
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
# テキストを出し終えたか?
count_of_typewriter += delta
if not is_blink_started and 0.5 <= count_of_typewriter:
var message_window_text = $".."
if message_window_text.get("text_storage").length() < 1:
is_blink_started = true
visible = true
count_of_typewriter -= 0.5
# 点滅
if is_blink_started:
count_of_blink += delta
if 0.75 <= count_of_blink:
visible = not visible
count_of_blink -= 0.75
func reset():
self.visible = false
self.is_blink_started = false
self.count_of_blink = 0
self.count_of_typewriter = 0
📄 MessageWindowText.gd
:
extends Label
var count_of_typewriter = 0
var scenario_array = [
# 2345678901234567890
"""\
お父ん、知ってたら教えてくれだぜ。
エスフェン(SFEN)の 7g7f って何だぜ?
""",
"""\
あー。7筋の7段目の駒を
6段目に突くことだぜ。
分かったら もう寝ろ
""",
"""\
3c3d って何だぜ?
""",
"""\
角換わりだろ。
もう寝ろ
""",
"""\
お父ん、なんで唐揚げを食べているんだぜ?
ダイエットはどうした?
野菜を TABERO だぜ!
""",
# 2345678901234567890
"""\
元気になりたくて唐揚げを食べるんだぜ。
カロリー計算をしようと思ったときもあった
限界まで食べてしまうので止めた
""",
]
var text_storage = ""
# Called when the node enters the scene tree for the first time.
func _ready():
# 最初のテキスト
self.text = ""
if self.text_storage == "" and 0 < self.scenario_array.size():
self.text_storage = self.scenario_array.pop_front()
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
# タイプライター風出力
count_of_typewriter += delta
if 0.05 <= count_of_typewriter:
if 0 < self.text_storage.length():
self.text += text_storage.substr(0, 1)
text_storage = text_storage.substr(1, self.text_storage.length()-1)
count_of_typewriter -= 0.05
func _unhandled_key_input(event):
print("_unhandled_key_input")
# 何かキーを押したとき
if event.is_pressed():
print("_unhandled_key_input is_pressed")
# TODO ブリンカーを消す
$"BlinkerTriangle".reset()
$"BlinkerUnderscore".reset()
# メッセージ送り
if self.text_storage == "":
self.text = ""
if 0 < self.scenario_array.size():
self.text_storage = self.scenario_array.pop_front()
📺 動画
「 👆 この動画に映ってるメッセージ・ウィンドウで だいたい 充分よ」
「 出すメッセージが無いんだったら、メッセージ・ウィンドウを閉じてくれだぜ」
else:
# 出すメッセージが無ければ、メッセージ・ウィンドウを閉じる
$"..".visible = false
「 顔グラ(Face Graphic)を出すと 素材不足で 苦しむしな」
「 工夫で乗り切るか。
昔のゲームは ちからわざ が使えないときは ごめんなさい で通していたからな」
「 カギかっこ付けたから 1行に 19文字しか入らないぜ?」
「 どのボタンを押したら 早送りするんだぜ?
まだ キーボードで遊ぶのか、ゲームパッドで遊ぶのか、何も決まってないぜ?」
「 じゃあ スーパーファミコンの R
ボタンとか よく使ったから、キーボードの R
キーでいいか」
# 1文字 50ms でも、結構ゆっくり
var wait_time = 0.05
# メッセージの早送り
if Input.is_key_pressed(KEY_R):
print("[テキストブロック] メッセージの早送り")
wait_time = 0.01
if event.keycode == KEY_R:
print("[テキストブロック] Rキーは、メッセージの早送りに使うので、メッセージ送りしません")
return
# 選択肢モードの場合は、確定ボタン以外は無効
elif self.is_choice_mode and event is InputEventKey and event.pressed:
if event.keycode != KEY_ENTER:
print("[テキストブロック] 選択肢モードでは、エンターキー以外ではメッセージ送りしません")
return
else:
print("[テキストブロック] 選んだ選択肢行番号:" + str($"ChoiceCursor".selected_row_number))
pass
.
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント