mieki256's diary



2020/11/01() [n年前の日記]

#1 [godot] Godot Engineで林檎を取った時のエフェクトを追加

Godot Enigne 3.2.3 x64 の勉強を兼ねて、Apple Catcher っぽいゲームを作成中。環境は Windows10 x64 2004。

見た目だけでは林檎を取ったかどうかがちょっと分かりづらいので、今回は林檎を取った時に「+10」という数字がゆっくり上がっていくエフェクト(?)をつけてみたい。

シーンとノードを新規作成。 :

エフェクト用のシーンを新規作成。シーン → 新規シーンを選択。

godot_tuto20_add_effects_ss01.png


Node2D をルートノードにしたいので、「2Dシーン」を選択。

godot_tuto20_add_effects_ss02.png


Node2Dノードが登録されたので、子ノードを追加していく。左上のノード追加ボタンをクリック。

godot_tuto20_add_effects_ss03.png


以下のような構成でノードを用意する。
Node2D
  │  
  ├─ Node2D
  │     │
  │     └─ Label
  │
  └─ AnimationPlayer

godot_tuto20_add_effects_ss04.png


ルートノードを「GetItemEffect」にリネーム。

godot_tuto20_add_effects_ss05.png

Labelを設定。 :

Labelノードを使って「+10」と表示したい。Labelノードを選択。

godot_tuto20_add_effects_ss06.png


Textプロパティに「+10」と入力。Align と Valign を Center にしておく。

godot_tuto20_add_effects_ss07.png


フォントを指定。Custom Fonts の Font に、「新規DynamicFont」を作って、DynamicFont をクリックして色々設定していく。
  • フォントサイズ(Size)は32に。
  • Use Filter を有効化。
  • Font Data には res://resources/Aileron-Black.otf を指定した。
  • Custom Colors → Font Color Shadow を有効化。
  • Custom Constants → Shadow Offset x,y を (4,4)に。

godot_tuto20_add_effects_ss08.png


Labelの位置を調整。「レイアウト」をクリックして、「中央下」を選択。これで基準点が最下部になってるような位置で表示された。

godot_tuto20_add_effects_ss09.png

アニメを作成。 :

AnimationPlayerノードを使って、座標が変化していくアニメや、透明度が変化するアニメをつけていく。AnimationPlayerノードを選択。

godot_tuto20_add_effects_ss10.png


Godot Engineエディタ画面の下のほうにアニメーションを設定するウインドウが開くので、「アニメーション」をクリック。

godot_tuto20_add_effects_ss11.png


「新規」を選択。

godot_tuto20_add_effects_ss12.png


アニメの種類名として「move」を入力して「OK」。

godot_tuto20_add_effects_ss13.png


キーフレームと座標を設定していく。Node2Dノードを選択して、Transform → Position x,y が (0, 0) の状態で、右の鍵(Key)アイコンをクリック。

godot_tuto20_add_effects_ss14.png


Positionプロパティ用のトラックを作成してよいかと尋ねてくるので「作成」。

godot_tuto20_add_effects_ss15.png


0秒目の位置に、Position = (0, 0) が記録された。

godot_tuto20_add_effects_ss16.png


現在フレーム(?)を1秒目の位置にする。

godot_tuto20_add_effects_ss17.png


Node2Dノードの Transform → Position y を -100 にして、右の鍵アイコンをクリック。

godot_tuto20_add_effects_ss18.png

これで、0秒目と1秒目にキーフレームが設定された。1秒かけて100ドットほど上に移動していくアニメをつけられた。

座標だけではなく、色(今回は透明度)も変化していくアニメをつける。

現在フレーム(?)を0秒目の位置にしてから、Node2Dノードの CanvasItem → Visibility → Modulate の右の鍵アイコンをクリック。

godot_tuto20_add_effects_ss19.png


modulateプロパティ用のトラックを作成してよいかと尋ねてくるので「作成」。0秒目にキーフレームが登録される。

godot_tuto20_add_effects_ss20.png


0.7秒目の位置でも、鍵アイコンをクリックしてキーフレームを作成。

godot_tuto20_add_effects_ss21.png


1秒目の位置で、白い色の部分をクリックして、透明度(RGBAのA)を0にして、鍵アイコンをクリック。

godot_tuto20_add_effects_ss22.png

これで、0秒目から0.7秒目までは不透明なままで、0.7秒目から1秒目までは不透明から透明に変化するアニメをつけられた。

アニメ種類名の右にある「読込み後、自動再生」のアイコンをクリックして有効化。

godot_tuto20_add_effects_ss23.png


再生ボタンをクリックして動作を確認してみる。それらしいアニメをつけることができた。

godot_tuto20_add_effects_ss24.gif

シーンを保存。 :

シーンを保存。シーン → 名前を付けてシーンを保存、を選択。

godot_tuto20_add_effects_ss25.png


res://assets/ 以下に GetItemEffect.tscn として保存。

godot_tuto20_add_effects_ss26.png

スクリプトファイルを追加。 :

GetItemEffectノードを選択して、スクリプトをアタッチ。

godot_tuto20_add_effects_ss27.png


res://scripts/ 以下に GetItemEffect.gd としてスクリプトファイルを作成。

godot_tuto20_add_effects_ss28.png


スクリプトファイルが作成されて、エディタウインドウが開いた。

godot_tuto20_add_effects_ss29.png

自動で自分を消去するように指定。 :

この GetItemEffectノードは、アニメの再生が終わったタイミングで自分自身を消去してもらいたい。

Timerノードを用意して、1秒経過したら消えるようにしようかとも思ったけれど、AnimationPlayerノードのシグナルを眺めてみたら animation_finished(anim_name: String) なるシグナルが目に入った。名前からしてアニメ再生が終わったタイミングで発行されるシグナルではあるまいか。これを利用してみることにする。

AnimationPlayerノードを選択。

godot_tuto20_add_effects_ss30.png


ノードタブをクリックして、animation_finished(anim_name: String) を選択、右クリックして「接続」。

godot_tuto20_add_effects_ss31.png


「メソッドにシグナルを接続」ウインドウが表示されるので、GetItemEffect を選択して「接続」。

godot_tuto20_add_effects_ss32.png


スクリプトファイル GetItemEffect.gd 内に、_on_AnimationPlayer_animation_finished(anim_name) メソッドが追加された。メソッド内で、自分を消去するためのメソッド queue_free() を呼ぶように修正。

godot_tuto20_add_effects_ss33.png


これで、アニメ再生が終わると自動で自分を消去するようになった。

プレイヤーシーンに発生処理を追加。 :

プレイヤーシーンに発生処理を追加していく。メインシーン Main.tscn を開いて、Playerノードの横にあるスクリプトアイコンをクリック。

godot_tuto20_add_effects_ss34.png


スクリプトファイル Player.gd の最初のあたりに以下を追加。

godot_tuto20_add_effects_ss35.png

export (PackedScene) var getitemeffect
この変数に先ほど作った GetItemEffectシーンをGUIで登録しておく予定。

林檎を取った時の処理に以下を追加。

godot_tuto20_add_effects_ss36.png

        var effect = getitemeffect.instance()
        effect.position = body.position
        get_node("/root/Main").add_child(effect)
GetItemEffectのインスタンスを作って、座標を林檎の座標で設定して、Mainノードに子ノードとして追加している。

現状の Player.gd の内容は以下。

_Player.gd

先ほど用意した変数にGUIで GetItemEffectシーンを登録。Playerノードを選択。

godot_tuto20_add_effects_ss37.png


Getitemeffect の右の「空」をクリックして「読込み」。

godot_tuto20_add_effects_ss38.png


res://assets/ 以下の GetItemEffect.tscn を選んで「開く」。

godot_tuto20_add_effects_ss39.png


getitemeffect に GetItemEffectシーンが登録できた。

godot_tuto20_add_effects_ss40.png

動作確認。 :

Main.tscn を開いた状態でF6キーを押して動作確認してみる。



林檎を取ると「+10」が発生して、上に移動して消えていく。ちゃんと動いてる模様。

次回は、プレイヤーに爆弾が当たった時に、林檎や爆弾をその場で停止させる仕様を追加したい。Godot Engine で用意されてるポーズ機能相当を利用する予定。

2020/11/02(月) [n年前の日記]

#1 [godot] Godot Engineで林檎や爆弾の動きを止める処理を追加

Godot Enigne 3.2.3 x64 の勉強を兼ねて、Apple Catcher っぽいゲームを作成中。環境は Windows10 x64 2004。

プレイヤーに爆弾が当たった時に林檎や爆弾の動きを止めたい。Godot Engineにはポーズをかけてゲーム進行を一時停止する機能があるので、今回はお試し(?)でその機能を利用してみる。

各ノードのPause Modeを設定。 :

Godot Engine の各ノードは、ポーズ(Pause)が有効になった時にどう反応するかを決めるModeプロパティを持っている。指定できる種類は以下。
  • Inherit : 上位ノードの設定を継承する。
  • Stop : ポーズ有効時に自身の処理を止める。
  • Process : ポーズ有効時も自身の処理を続行する。

_ゲームの一時停止 - Godot Engine (stable)の日本語のドキュメント

例えば、ポーズ有効になった際、ポーズ解除処理を担当するノードまで止まってしまったらゲームを再開できないので、そんな時はポーズ解除処理担当ノードに「Process」を指定しておいて、ポーズ状態でもそのノードだけは処理を続行させたりする。

各ノードのModeを設定していく。Main.tscn を開いて、Mainノードを選択。Pause → Mode を「Process」に変更。Ctrl + Sキーを押して保存。

godot_tuto21_add_pause_ss01.png


Player.tscn を開いて、Playerノードを選択。Pause → Mode を「Process」に変更。Ctrl + Sキーを押して保存。

godot_tuto21_add_pause_ss02.png


Apple.tscn を開いて、Appleノードを選択。Pause → Mode を「Stop」に変更。Ctrl + Sキーを押して保存。

godot_tuto21_add_pause_ss03.png


他のシーンも同様に設定していく。
  • Mainノード : Mode = Process
  • Playerノード : Mode = Process
  • Appleノード : Mode = Stop
  • Bombノード : Mode = Stop
  • ItemGeneratorノード : Mode = Stop
  • GetItemEffectノード : Mode = Stop

スクリプトでポーズを有効化する。 :

メインシーンのスクリプト Main.gd 内に、ポーズ有効化/解除の処理を追加する。
  • ゲームオーバーになったタイミングでポーズ有効化。get_tree().paused = true を記述。
  • ゲームタイトルを表示し直すタイミングでポーズ解除。get_tree().paused = false を記述。

godot_tuto21_add_pause_ss04.png

F6キーを押して動作確認してみる。



プレイヤーに爆弾が当たったタイミングで、林檎や爆弾の動きが止まってくれた。

しかし、プレイヤーの死亡アニメが終了して、プレイヤーのアタリ判定処理が有効になった途端に、そこに居続ける爆弾にまた当たってその場でたちまちゲームオーバーが繰り返されてしまう。このバグを修正しないと…。

グループ名をつける。 :

プレイヤーの死亡アニメが終わるタイミングで、画面上に出ている林檎や爆弾を全消去してやる必要がある。その処理をグループ機能を使って行ってみる。

各ノードにはグループ名をつけることができる。グループ名を使えば、「このグループにこういう処理をせよ」と、複数のオブジェクトに対して一気にまとめて処理を指定することができる。

グループ名をつけていく。Apple.tscn を開いて、Appleノードを選択。ノードタブをクリック → グループをクリック → 「apples」と入力して「追加」。Appleノードに「apples」というグループ名をつけることができた。Ctrl + Sキーを押してシーンを上書き保存。

godot_tuto21_add_pause_ss06.png


Bomb.tscn を開いて、Bombノードを選択。ノードタブをクリック → グループをクリック → 「bombs」と入力して「追加」。Ctrl + Sキーを押してシーンを上書き保存。

godot_tuto21_add_pause_ss07.png


GetItemEffect.tscn を開いて、GetItemEffectノードを選択。ノードタブをクリック → グループをクリック → 「effects」と入力して「追加」。Ctrl + Sキーを押してシーンを上書き保存。

godot_tuto21_add_pause_ss08.png

スクリプトでグループに対して全消去。 :

メインシーンのスクリプト Main.gd に、グループに対して全消去する処理を追加。

godot_tuto21_add_pause_ss09.png

ポーズを解除する直前に、林檎、爆弾、エフェクトを全消去するメソッドを追加。
kill_all_items()

全消去するメソッドを追加。
func kill_all_items():
    get_tree().call_group("apples", "queue_free")
    get_tree().call_group("bombs", "queue_free")
    get_tree().call_group("effects", "queue_free")
get_tree().call_group("グループ名", "メソッド名") と書けば、そのグループ名を持ってるオブジェクト全てに対して指定したメソッドを実行することができる。

ここでは、apples(林檎)、bombs(爆弾)、effects(「+10」表示) に対して queue_free() を呼んでノード消去を指示している。

Main.gd の内容は以下。

_Main.gd

F6キーを押して動作確認。



プレイヤーの死亡アニメが終わるタイミングで林檎や爆弾が全消去できている。それらしく動いてくれた。

これで一通りゲームっぽい感じになったかなと…。次回はexeファイルやHTML5でエクスポートして、Godot Engine をインストールしてない環境でも動かせるようにしたい。

#2 [godot] Godot Engineでプロジェクトをエクスポート

Godot Enigne 3.2.3 x64 の勉強を兼ねて、Apple Catcher っぽいゲームを作成中。環境は Windows10 x64 2004。

今回はプロジェクトをexeファイル化したりHTML5でエクスポートしてみたい。エクスポートすれば Godot Engine をインストールしてない環境でもそのゲームを動かせるようになる。

手順については公式サイトのドキュメントでも解説されているので参考に。

_エクスポート - Godot Engine (stable)の日本語のドキュメント
_Webのエクスポート - Godot Engine (stable)の日本語のドキュメント
_プロジェクトのエクスポート - Godot Engine (stable)の日本語のドキュメント

エクスポートテンプレートファイルを入手。 :

Godot Engine でプロジェクトをエクスポートする前に、エクスポートテンプレートファイルなるものを入手しないといけないらしい。

今回は Godot Engine 3.2.3 を使っているので、同じバージョンの Godot_v3.2.3-stable_export_templates.tpz を公式サイトのダウンロードページから入手。

_Godot Engine - Download | Windows

エクスポートテンプレートファイルを読み込む。 :

Godot Engine のエディタ画面でエクスポートテンプレートファイルを読み込ませる。エディタ → エクスポートテンプレートファイルの管理、を選択。

godot_tuto22_export_project_ss01.png


以下は既に読み込んだ後のスクリーンショットだけど、「ファイルからインストール」を選べば読み込ませることができたような気がする。

godot_tuto22_export_project_ss02.png

エクスポートできる種類を設定。 :

エクスポートする種類を指定。プロジェクト → エクスポート、を選択。

godot_tuto22_export_project_ss03.png


「追加」をクリック。今回は、「Windows Desktop」と「HTML5」を選んで追加してみた。

godot_tuto22_export_project_ss04.png

exeファイルをエクスポート。 :

Windows上で動くexeファイルを作ってみる。「Windows Desktop (実行可能)」を選んで、「プロジェクトのエクスポート」。

godot_tuto22_export_project_ss05.png


ファイルの保存場所を尋ねられるので、フォルダを指定して、ファイル名「newtototone.exe」を入力。「デバッグ付きエクスポート」のチェックを外して「保存」。

godot_tuto22_export_project_ss06.png


exeファイル「newtototone.exe」と、おそらくはデータファイルであろう「newtototone.pck」が生成された。

godot_tuto22_export_project_ss07.png


ダブルクリックして実行してみる。



実行された。exeファイルのエクスポートは成功した。

HTML5でエクスポート。 :

Webブラウザ上で動作するHTML5ファイルの形式でエクスポートしてみる。「HTML5 (実行可能)」を選んで「プロジェクトのエクスポート」。

godot_tuto22_export_project_ss09.png


ファイルの保存場所を尋ねられるので、フォルダを指定して、ファイル名「newtototone.html」を入力して「保存」。

godot_tuto22_export_project_ss10.png


htmlファイルやその他のファイルが生成された。

godot_tuto22_export_project_ss11.png

HTML5の動作確認。 :

生成されたHTML5ファイル群がWebブラウザ上で動作するのか確認したいのだけど、一般的に今時のWebブラウザは、セキュリティの問題でローカル保存されたこの手のファイルをそのまま開いて実行することはできないらしい。

幸い、Pythonがインストールされている環境ならPythonを使ってローカルなWebサーバを起動することができるので、ソレを使って動作確認する。ちなみに自分の環境は Python 3.8.6 x64 をインストールしてある。
> python --version
Python 3.8.6

> python -VV
Python 3.8.6 (tags/v3.8.6:db45529, Sep 23 2020, 15:52:53) [MSC v.1927 64 bit (AMD64)]

DOS窓(cmd.exe)を開いて、今回生成したファイル群が入ってる場所をカレントフォルダにする。 *1 *2

Python 3.x の場合は以下を打つ。
python -m http.server

Python 2.x の場合は以下を打つ。
python -m SimpleHTTPServer

これでローカルWebサーバが起動した。Webブラウザで、 _http://localhost:8000/ にアクセスすればフォルダの中身が見える。

godot_tuto22_export_project_ss12.png


「newtototone.html」をクリックして開いてみる。

godot_tuto22_export_project_ss13.png


Webブラウザ上でゲーム画面が表示された。動作成功。

Python で立ち上げたローカルWebサーバを終了するには、DOS窓で Ctrl + C を押せばいい。たぶん。ちょっと自信無し。他に止め方があるのかもしれないが、よく知らない。

試しにWebサーバ上にも置いてみる。実行できるだろうか…?

_newtototone.html

これでゲームの実行ファイルを生成することができたので、Godot Engine を使って簡単な2Dゲームを作る流れについては一通り説明できたはず…。

まあ、以下のページのほうが参考になりそうな気もしますが…。

_最初のゲーム - Godot Engine (latest)の日本語のドキュメント

余談。 :

Webサーバ Apache2で公開してるディレクトリに Godot Engine からエクスポートした HTML5ファイル群を置くためには、.pck と .wasm の MIME とやらを指定しないといけないのかもしれない。

とりあえず、各ディレクトリに公開設定を追加してくれるファイル ―― .htaccess に対して以下を追加してみたら、Webブラウザが読み込める状態になった。とメモ。
AddType application/octet-stream pck
AddType application/wasm wasm

*1: Win + Rキーを押して「cmd」と入力してEnterを叩けばDOS窓が開くので、「cd フォルダパス」を打ち込めばカレントフォルダを変更できる。
*2: あるいは昨今のWindows10なら、エクスプローラでフォルダパスが表示されてる欄に「cmd」と打ち込んでEnterを叩けば、そのフォルダをカレントフォルダにしたDOS窓を開いてくれる。

2020/11/03(火) [n年前の日記]

#1 [godot] Godot EngineでApple Catcherゲームを作る手順のまとめ

Godot Enigne 3.2.3 x64 で Apple Catcher っぽいゲームを作成する手順をメモしてきたけど、一応各記事(?)へのリンクを並べておく。OS環境は Windows10 x64 2004。

_プレイヤーキャラ用のシーンを作成
_プレイヤーシーンにスクリプトを追加
_上から落ちてくる林檎キャラを作成
_林檎と爆弾をたくさん生成
_ゲームのメインシーンを作成
_HUDシーンを作成
_HUDシーンにスクリプトを追加
_メインシーンとHUDシーンを合体
_サウンドを追加
_BGを追加
_TileMapを使ってBGを追加
_ボタンショートカットやStretchを設定
_林檎を取った時のエフェクトを追加
_林檎や爆弾の動きを止める処理を追加
_プロジェクトをエクスポート

完成品は以下でプレイできる。

_newtototone.html

#2 [zatta] 日記をアップロード

気づいたら2020/08/08を最後に日記をアップロードしてなかったのでアップロード。ローカルに溜め込み過ぎ…。

2020/11/04(水) [n年前の日記]

#1 [zatta] LED電球を購入

ドラッグストア カワチで、夜食を買うついでにLED電球を購入。
店頭で税抜き価格を見て随分安いなと驚いて購入してみたけれど、税込み価格で比較したらヨドバシカメラの価格とさほど変わらなかった…。それでもケーズデンキで買うよりはるかに安いけど。以前ケーズデンキの店頭で同等製品を物色したら千円を超えてたから…。

ひとまず、PCデスクの真上に設置していた電球型蛍光灯 TOSHIBA EFA15D/11-Z (60W相当, 11W, 680lm)を外して、Panasonic製LED電球 LDA7D-G/E/W に交換した。

電球型蛍光灯は電源を入れたばかりだと暗くて、数分経つと期待していた明るさになっていく感じだったけど、LED電球は電源を入れた途端に明るく光るので少しだけ便利になったような気もする。

また、スペック上はLED電球のほうがルーメン値が大きいけれど、光らせてみた感じではたしかに若干明るくなってくれたような気もする。もっとも、あくまで体感(?)なので実際のところは分からんけど。

余談。 :

オーム電機製LED電球は、店頭では税抜き価格で300円台だったのでついつい買ってしまったけれど。オーム電機のLED電球は、たしかスペック値を盛っていて消費者庁から注意されてた時期があった記憶が。ググってみたら2012年の話らしいけど。

_消費者庁、LED電球の明るさを誇大表示した12社に再発防止命令 - 家電 Watch
今回措置命令を受けたのは、アガスタ、エコリカ、エディオン、オーム電機、グリーンハウス、恵安、光波、コーナン商事、スリー・アールシステム、セントレードM.E.、タキオン、リーダーメディアテクノ。この12社は、消費者に販売するLED電球において、商品パッケージに「白熱電球60W形相当の明るさ」など、白熱電球と比較した明るさを表示していたが、実際には白熱電球と同等の明るさは得られなかったという。

消費者庁、LED電球の明るさを誇大表示した12社に再発防止命令 - 家電 Watch より


いくらなんでもさすがに今は改善してるのではないかと淡い期待をしつつも、万が一暗かったら、やっぱりなー、オーム電機だからなー、道理で安かったわけだわー、という感じで受け止めようかと。とりあえず、玄関奥の電球型蛍光灯と交換してみる予定。

たしかLED電球のスペック詐欺云々の話が出た時に、どこかのメーカが「それは測定の仕方がおかしい。ウチはちゃんとした製品を販売してる」と反論してた記憶もあるのだけど…。ググっても出てこない。偽記憶だろうか。それとも自分は別の家電製品の話と混同してるのだろうか。大半のメーカが素直に(?)謝罪してたのに一社だけ反論していて随分強気だなと思った記憶もあるのだけど…。アレは何の話だったかなあ…。

2020/11/05(木) [n年前の日記]

#1 [windows] SyncToyの設定を増やした

SSD突然死によりSSD交換とOS再インストールをしてから、バックアップ用ツール SyncToy 2.1 の設定作業を放置してたのだけど、そろそろ設定しないといかんなと思い立ち作業開始。

十数フォルダ分の設定を追加して、まずは Echo で左から右にファイルの上書きや追加をしてから、設定を変更して Synchromize で同期。ただ、結構な数のファイルが書き戻されてしまう感じで…。本体PC内のHDD側で、ファイルやフォルダのリネームや移動をし過ぎた…。どのファイルが必要でどのファイルが不要かを目視で確認するのが面倒臭いけど、やるしかないわな…。

#2 [zatta] 玄関近辺の照明器具をLED電球と交換

玄関奥側の電球型蛍光灯を、オーム電機製LED電球60W相当と交換してみた。結構明るくなった。オーム電機製だからスペックを盛っていて実際に使うと暗いのではと心配してたけど、全然そんなことはなかった。今時の製品はちゃんと明るいらしい。

今まで使ってた電球型蛍光灯を眺めてみたら、あちこちが割れていてゾッとした。どうも誰かが落として割ってしまったけどボンドの類で無理矢理修理して誤魔化していたっぽい。これまでも点いていたから使えなくはないのだろうけど…。親父さんに渡したら、見た目からして使うのは怖い、という話になって廃棄することに。なんでもかんでももったいないと言い出す親父さんですら使用を諦めるほどに悲惨な見た目、ということかな…。

トイレの電球も、東芝製LED電球(100W相当、昼光色)と交換してみた。今まで使ってたのもLED電球だったけど、電球色から昼光色に、40〜60Wから100Wになったので、かなり明るい感じになった。トイレのような狭い空間でそこまで明るい照明が必要なのかという気もするけれど、親父さんが歳なものだから色々汚す場面が増えてきて、しかし電球色だから汚れが見えにくく掃除がしにくかったりもしたので、これでそのあたりが多少は改善できたらいいなと。まあ、明る過ぎて家族から苦情が出るようなら、玄関奥側の60W相当LED電球と入れ替えることにしよう…。

2020/11/06(金) [n年前の日記]

#1 [godot] Godot Engineで3D表示の簡単なシューティングゲームを作成中

せっかく Godot Engine を触り始めたことだし、3D表示の簡単なシューティングゲームを作成してみようかと。以前もある程度は作ったのだけど、復習を兼ねて、同じ作業をしながら作業画面をキャプチャしているところ。

2020/11/07() [n年前の日記]

#1 [blender] blenderで飛行機モデル作成中

Godot Engine を使って3D表示の簡単なシューティングゲームをそこそこ作れたけれど、表示しているモデルが箱や丸なので見た目が非常にダサい。ここはもうちょっとそれらしいモデルを表示したい。

ということで、表示するための飛行機の3Dモデルを blender 2.83.8 LTS x64 を使って作成中。

以前も飛行機モデルは一応作成したのだけど、当時はいきあたりばったりで作ったものだから形やテクスチャに満足できてなくて。今回は、大昔に描いたドット絵を blender の画面内に配置しながら、トレースしていく感じでモデリングしているところ。ちなみに、blender で画像を読み込むだけなら、ファイル → インポート → Images as Planes を呼び出すと楽。もしかするとアドオンを有効にしないと項目が出てこないかもしれない。

もっとも、ドット絵は上から見た際の形状しか描いてないわけで。3Dにして前や斜めから見るとコレジャナイ感が強い…。正方形の画像の中にみっちりと入るようにドットを打っていたものだから、3Dにするとずんぐりむっくり…。もっとすらりとしたイメージだったのだけどな…。でもまあ、ゲームの中で使う時はアタリ範囲その他の関係でずんぐりむっくりしているほうが使いやすいかもしれないか…。

2020/11/08() [n年前の日記]

#1 [blender][godot] blenderで飛行機モデルをまだ作成中

blender 2.83.8 x64 LTS を使って飛行機モデルを作成中。形状はできたので、テクスチャ画像その他を適用するためにUVの設定をしていく。
  1. UVを設定。UV Editing レイアウトにして作業。
  2. UV配置画像をpngとして保存。UV → UV配置をエクスポート。出力画像サイズは 1024 x 1024 にした。
  3. Inkscape 1.0.1 x64 を起動してノーマルマップ画像を作成する。キャンバスを 1024 x 1024 px に設定。ファイル → ドキュメントのプロパティ。Shift + Ctrl + D でもいいし、ツールバー上のアイコンをクリックしてもいい。
  4. UV配置画像をインポート。ファイル → インポート。あるいは、キャンバス上に画像をドラッグアンドドロップ。
  5. ノーマルマップにするための線を引く。
  6. png でエクスポート。ファイル → PNG画像にエクスポート。Shift + Ctrl + E でもいい。
  7. GIMP 2.10.22 Portable x64 samj版で画像を開いて、法線マップに変換。フィルター → 汎用 → 法線マップ。変換結果をpng でエクスポート。
  8. blender で読み込んでノーマルマップ適用。Shadingレイアウトにして作業。マテリアル設定ウインドウ内で、追加 → テクスチャ → 画像テクスチャ。追加 → ベクトル → ノーマルマップ。プリンシバルBSDFのノーマルに接続。
  9. GIMP でテクスチャ画像を作成。
  10. blender でテクスチャ画像を適用。プリンシバルBSDFのベースカラーに画像テクスチャを接続。

Godot Engine で読み込むために、glTF 2.0形式でエクスポートする。今回はアニメーション設定等はしてなくて、単に形状やテクスチャを利用できればそれで済むので glTF を選んだ。ファイル → エクスポート → glTF 2.0 (.glb/.gltf)。ゲームで使うことが前提なので、バイナリファイルらしい .glb でエクスポートした。どうやらこの .glb の中にテクスチャ画像やノーマルマップ画像も含まれている模様。

アニメーション設定も利用したいときは、 .escn でエクスポートしたほうが良いかもしれない。

Godot Engine で開く。 :

Godot Engine のプロジェクトフォルダ内に .glb をコピーしておけば、Godot Engine を起動してプロジェクトを開いた際に自動でインポートしてくれる。.glb をダブルクリックすれば開くことができる。

.glb を開く際に新規の継承がどうとか尋ねてくるけど、継承したほうがいいのか、無理矢理開いたほうがいいのか、どちらがいいのかはまだ分かってない。何がどう違うのだろう?

2020/11/09(月) [n年前の日記]

#1 [pc] 無線LANルータの設定登録数を超えてしまった

妹が新しいスマホを購入したとのことで、無線LANルータ NEC Aterm WR8300N のMACアドレスフィルタリングにスマホのMACアドレスを追加登録しようとしたのだけど、「最大登録件数を超えました」とメッセージが表示されてしまった。

32件以上は登録できないのか…。ていうかウチの中にはそんなにも無線LAN付き機器・無線LAN子機が存在しちゃってるのか。コレはちょっと多過ぎるのでは。

メモしておいた登録機器の一覧を眺めて、初期不良交換前の個体が1つ登録されているのを発見。その個体を登録から削除することで今回のスマホはどうにか追加登録できた。しかし、この状況はマズイ。登録数が多過ぎる。

普段常用していない無線LAN子機も結構登録されているのでそのあたりを削っていけば空きを捻出できなくもないけれど…。本体にLANケーブルを常時接続しておくほどではないけれど、たまに電源を入れてメンテナンスしそうなPC達も居るので、そういったPCに無線LAN子機を差して登録してあるわけで。どうしたものか。LANハブを1つ新規購入して常用しない機器はそちらにまとめて接続しておくほうがいいのかな…。

とりあえず、今回のスマホの型番はGRPでメモした、とメモ。

ベンダーが分からない。 :

製品型番不明のMACアドレスが多数登録されているあたりも気になる。少し調べ直して2個ほど型番は分かったけれど、まだ4個ほど正体不明機が居る…。コイツラ一体何者なんだ。必要なのか。

MACアドレスからベンダーを調べることができるらしいけど、以下のサービスを使わせてもらっても、2個が不明で。

_MACアドレス検索 - UIC

あるいは、http://standards-oui.ieee.org/oui.txt にベンダーの一覧が載ってるらしいのだけど、DLして検索しても出てこない。

以下の2つが分からない。一体どこのメーカの製品なんだろう。
3c:f8:19
dc:04:00

#2 [blender][godot] blenderで背景モデルを作成中

blender 2.83.8 LTS x64 を使って Godot Engine 3.2.3 x64 で表示する背景モデルを作成中。近未来SFモノのどこかの街っぽい感じがするモデルにしたいなと。

作ってはみたものの、Godot Engine で表示してみるとスクロールがガクガクしてしまう。Cube を多数並べてるのがいかんのだろうか。blender上で全て結合して1つのモデルにしてから Godot で再インポートしてみたけれど更に動きがガクガク状態になった。

おそらくだけど、オブジェクト単位で描画すべきかしなくてもいいかを判定して処理してそうな気がする…。画面に出現する可能性があるオブジェクトだけを対象にして描画処理をしてるのではないか。であれば、そこそこ大まかに分割してモデルを作ってあるほうが、処理時間は短くて済むのだろうか…。

2020/11/10(火) [n年前の日記]

#1 [blender][godot] blenderで背景モデルを修正中

blender 2.83.8 LTS x64 で背景モデルを修正中。底面に置いてあった大きな Plane を適度なサイズで分割してそれぞれ別オブジェクトにしてみたり、多数の箱の親子関係をクリアして基準点が各オブジェクトの中央にくるようにしてみたり、そんな感じの修正をチマチマとしているところ。

#2 [zatta] LEDライトと犬の餌入れを購入

犬の散歩のついでにSeriaに寄って、犬の餌入れとLEDライトを購入。

今まで使っていた犬の餌入れはお袋さんが車で踏んづけて割ってしまったので、ここ最近代わりになりそうなものを探していたのだけど、ダイソー、ホームセンターサンデー、ホームセンターホーマック、Seriaを回ってみたけれど見つからない。アレは一体どこで購入したんだろう…。仕方ないので、違う形状のものをSeriaで試しに1つ購入。高さがある容器で、これなら犬も食べやすいはず、とシール(?)には書いてあった。

LEDライトは、12SMD & 1LEDと書かれている製品。以前も1つ購入して玄関に置いてあるけど、部屋にも1つ欲しくなったので…。単三電池 x 3を使用。グリーンオーナメントが販売。1LEDのライトと12SMDのランタン状態を切り替えられる。フックをスライドしてどこかに引っ掛けることも可能。おそらくだけど以下で紹介されてる製品と同じではないかと。

_【ダイソー】これは強力に明るい!12SMD & 1LED ランタン | モノトーンな日々 新館
_【100均検証】1ミリも期待しないで『12 SMD&1 LEDランタン』なるライトをセリアで買ったら予想以上の光量で狂喜乱舞! たぶん100均史上最強の爆光!! | ロケットニュース24

記事中でも書かれているけど、たしかに12SMD側はかなり明るい。「爆光」との評にも納得。

2020/11/11(水) [n年前の日記]

#1 [blender][godot] Godot Engine に3Dモデルをインポートする実験をしていたり

blender 2.83.8 LTS x64 でエクスポートした背景モデルを Godot Engine 3.2.3 x64 でインポートして内容を確認中。

glTFでエクスポート。 :

glTF 2.0 (.glb)でエクスポートしたモデルデータを Godot Engine でインポートした際、blender上でリンク複製したオブジェクトはどういう扱いになるのか疑問が湧いて確認してみたけれど、一応 Mesh は同じものが使われているっぽい。各ノードの名前は違っているけれど、Meshプロパティに表示されているモデルのサムネイル画像をクリックして内容を確認したところ、それぞれ同名の Mesh が使われているように見えた。ちゃんと使い回しをしてくれているっぽいなと。

ちなみに、テクスチャもちゃんと反映されてる。.glb でエクスポートすれば、1ファイルの中に画像ファイルも含まれる模様。

ESCNでエクスポート。 :

ESCN (.escn) でエクスポート・インポートも試してみた。blender 2.83 にアドオンを追加、かつ、有効化する必要がある。

_godotengine/godot-blender-exporter: Addon for Blender to directly export to a Godot Scene

io_scene_godotフォルダを、blender 2.83 のユーザフォルダに ―― Windowsの場合は以下の場所にコピーする。
C:\Users\<USERNAME>\AppData\Roaming\Blender Foundation\Blender\2.83\scripts\addons\
コピーしたら blender を起動して、編集 → プリファレンス → アドオン → 検索欄に「godot」と打ち込んで絞り込み検索。「Import-Export: Godot Engine Exporter」にチェックを入れて有効化。

使う時は、ファイル → エクスポート → 「Godot Engine (.escn)」を選択。

初回操作時はGodot Engine上でテクスチャが反映されなかった…。エクスポート時の設定で以下をアレコレ試してみたら、何かの拍子にテクスチャ画像(hoge.png.001.png)もコピーされて Godot Engine上でもテクスチャが表示される状態になった。
  • Material Mode を「Script Shader Material」にしたり。
  • Generate External Material のチェックを入れたり入れなかったり。
  • Material Search Paths を「Project Directory」にし直したり。
ただ、これだとテクスチャを使っていない Material の色合いが奇妙な感じに…。

しかし Material Mode を「Spatial Material」にすると今度はテクスチャが表示されない。

以前試した際はアニメーションについてはイイ感じにインポートできていたのだけど、その時はテクスチャを使ってなかったから不備(?)に気づかなかったのだな…。

COLLADAでエクスポート。 :

COLLADA (.dae) でエクスポート・インポートを試してみた。

blender の標準アドオンは不具合が出るという話を見かけたので、以下のアドオンを利用した…と思ったけれど、どれだったかな…。おそらく、2.83にも対応と書いてあった sburris0版を使ったような気がする。io_scene_dae/ と godot_export_manager.py を blender 2.83 のユーザフォルダにコピーして使う。

_sburris0/collada-exporter-2.8: "Better" Collada exporter for Blender, orignally developed by the Godot Engine community UPDATED FOR 2.83+
_HungryProton/collada-exporter-2.8: "Better" Collada exporter for Blender, orignally developed by the Godot Engine community
_artellblender/collada-exporter-2.8: "Better" Collada exporter for Blender, orignally developed by the Godot Engine community

blender 2.7x用は以下。

_godotengine/collada-exporter: "Better" Collada exporter for Blender, orignally developed by the Godot Engine community

blender を起動して、編集 → プリファレンス → アドオン → 「godot」で検索して、「Import-Export: Godot Export Manager」にチェックを入れて有効化。

使う時は、ファイル → エクスポート → 「Better Collada (.dae)」を選択。ちなみに標準アドオン版は「Collada (デフォルト) (.dae)」と表示されてる。

とりあえず、glTF 2.0 と同様にテクスチャは反映された。また、リンク複製したオブジェクトについても Mesh の使い回しをしてくれていた。

ただ、テクスチャ画像ファイルも Godot Engine プロジェクトフォルダ内に別途コピーしてやらないといけないので、形状を取り込みたいだけなら glTF 2.0 (.glb) を使ったほうが1ファイルで済む分楽かもしれない。

何にせよ、blender上でリンク複製したオブジェクトまで個別の Mesh に逐一変換されているわけではなさそうだなと。最悪の場合 Godot Engine上でノードの複製と再配置をやり直さないとダメかなと不安だったけど杞憂に終わった。リンク複製については安心して使えそう。

#2 [anime][neta] 話題のあの作品の実写版について妄想

「鬼滅の刃」劇場版アニメが大ヒット云々のニュースを見ているうちに、ふとなんとなく妄想してしまったり。ここまでくると、これってたぶん、きっとどこかで実写版の企画が動いちゃってるのではないかしらん。みたいな。

おそらくは原作を1ページも読んでないしアニメ版も見ていないスーツ姿のお爺さん達が企画書の前で妙にニコニコしていたり。あちこちのタレント事務所がウチのタレントをなんとしても捻じ込むぞと目をギラギラさせて聞き耳立ててそういう話が出てくるのを虎視眈々と狙っていたり。そして結局は皆が首を傾げてしまうキャスティングが発表されてしまうのだろうなあ…。ああ、またか。何度もそんな光景を目にしてきた気がするなあ。

てな感じで偏見たっぷりの妄想をしてたのだけど、気になってググってみたら…。既にそういう予測はあちらこちらで出ていて話題になってたりするのだなと。皆、考えることは同じなのね…。芸能人が時々コスプレしてるのもそういう企画が出てきたら是非私にも何か一つ、という営業活動の一環では、みたいな話も見かけてなるほどなあ、と。

それはさておき。もし山崎貴監督が担当するとしたら「SWORD 鬼滅の刃」だの「KATANA 鬼滅の刃」みたいなタイトルになるのだろうなと予想するのでした。あの監督さんはどうしていつも英単語をつけるんだろう。何か理由があるんだろうけど。

考えてみたら、あの作品を実写映像化するとなったらVFXが大変なことになりそうだなと…。白組あたりにお願いしないと無理なのでは…。水のエフェクトとか火のエフェクトとかどうするんだろう。そもそもリアル調にするのか、あるいは、例えばだけど浮世絵っぽい表現 ―― NPR(Non-Photorealistic Rendering、非写実的レンダリング、非写実表現)にしていくのか。方向性を決めるだけでも悩んでしまいそう。でもないか。フツーに考えたらリアル調にするわな。

そういえば平成ライダーや戦隊シリーズでも水や火のエフェクトは出まくってるから、ひょっとするとあんな感じになるのかもしれない。なんとかなりそうな気がしてきた。いっそ平成ライダーのスタッフがTVドラマ版として実写化しないかなー。無理か。スタッフの人数が足りない予感。じゃあNHKが実写ドラマ化するのはどうだろう。「精霊の守り人」実写版みたいな感じで、って言うと「やめろぉ!」と言われちゃいそうだけど、アレって本編の脚本や演出はちょっとアレなんだけどアクションはなかなかだったしVFXもNHKパワーで凄いことになってたんでそういう面については十分期待できそうなのですが。OP映像の中で槍を振り回す綾瀬はるかさんを日本刀を振り回す炭治郎に置き換えて妄想してみるとあのOP曲の雰囲気と相俟って結構グッと来ませんか。かなりそれっぽいというか結構合ってる気がするのですけど。

ところで。山崎監督作品のタイトルのアレについて気になってググってみたら、監督ではなくてプロデューサーの意向でそういうタイトルになってるらしい。監督は被害者も同然で、これは冤罪(?)だったのですね…。

_山崎貴監督について語るなら「アルキメデスの大戦」を見てからにして欲しい | みる兄さん | 街角のクリエイティブ

2020/11/12(木) [n年前の日記]

#1 [digital] スマホを貰った

妹が新しいスマホを購入して古いスマホが用済みになったとのことで、その古いスマホを貰うことになった。

機種名は HUAWEI P9 lite。色は Gold。ROM16GB, RAM2GB。元々は Android 6.0 がインストールされていたはずの機種だけど、Android 7.0 にアップデートしてあるらしい。

一応ググって、スペックをメモ。
HUAWEI製品はアメリカから制裁(?)を受けていてGoogleのサービスが今後は使えないという話もあったような気がするけれど、以前発売されて当時はフツーにサービスを使えていた機種については今も使える状態ではあるらしい。まあ、今後どうなるかは分からんけど…。

PC側にファイルを転送したい。 :

スマホのカメラで撮影して得られた画像ファイルをPC側に持っていきたい。どんな方法があるのだろう。

ググってみたら以下のページが参考になった。色々な方法があるのだな。

_AndroidスマホからWindowsにファイルを転送する4つの方法 用途別に紹介|TIME&SPACE by KDDI

Wi-Fi(無線LAN)とアプリを使って転送する方法があるらしいので試してみたり。Cx File Explorer なるアプリがイイ感じらしい。Google Play 経由でインストール。

_Android端末でのファイル操作におすすめのファイルマネージャー「Cx File Explorer」 - 4thsight.xyz

Cx File Explorerを起動して、ネットワーク → PCから接続、を選ぶとランダムなポートでFTPサーバが立ち上がる。PC側からは、ftp://スマホのIPアドレス:ポート番号/ というURLでアクセスできるようになる模様。実際に、Windows10 x62 2004 + Firefox 82.0.3 からアクセスしてファイルをダウンロードすることができた。

PC側のブラウザはFTPが使えなくなる予定。 :

たしかPC側のブラウザは、ftp:// を削除・廃止する方向で動いてた記憶があるけれど…。

_Google Chrome、FTPサポートを削除する計画 | スラド セキュリティ
_Google ChromeがFTPの廃止に向け、機能をフェードアウト - PC Watch
_さよならFTP 〜「Google Chrome 80」でFTP接続は非推奨に - 窓の杜
_Mozilla、2021年のFirefox 82からFTPサポートを廃止 | マイナビニュース

記憶違いではなかった。Google Chrome も Firefox も将来的には ftp:// が使えなくなる模様。つまり、そのうち Cx File Explorer 経由でスマホにアクセスしようとしても、Webブラウザから気軽にアクセス、というわけにはいかなくなるはず。

GUIで操作するFTPクライアントの類は、ポート番号がコロコロ変わることなんか全く想定してないので、アドレスとポート番号を毎回設定し直すのが面倒なんだけどなあ…。

2020/11/13(金) [n年前の日記]

#1 [godot] Godot Engineで3D表示の簡単なシューティングゲームっぽいものを作ってみる

せっかく Godot Engine 3.2.3 x64 を触っていることだし、3D表示の簡単なシューティングゲームっぽいものを作ってみようかなと。手順をメモ。

プロジェクトを新規作成。 :

まずはプロジェクトを新規作成。Godot Engine を起動するとプロジェクトマネージャーが開くので、「新規プロジェクト」をクリック。

3d_tuto01_create_project_ss01.png


プロジェクト名や保存場所を指定。今回はWebブラウザ上でも動かせるものを作りたいので、「OpenGL ES 2.0」のほうを選ぶ。

3d_tuto01_create_project_ss02.png


プロジェクトが作成されて、Godot Engine のエディタ画面が表示された。

3d_tuto01_create_project_ss03.png


プロジェクト設定を変更しておく。プロジェクト → プロジェクト設定。

3d_tuto01_create_project_ss04.png


ゲームウインドウのサイズを 1280x 720 にしたい。Window → Width, Height を、1280, 720 にする。

3d_tuto01_create_project_ss05.png


ウインドウの最大化ボタンを押した際に、それらしく表示されるように設定したい。Window → Stretch → Mode を viewport に、Aspect を keep に変更。

3d_tuto01_create_project_ss06.png


これで「閉じる」を押せば設定完了。

外部で作ったファイルをインポートするためのフォルダを作成しておく。ファイル一覧ウインドウ内の「res://」を右クリックして「新規フォルダ」を選択。

3d_tuto01_create_project_ss07.png


今回は「imports」というフォルダを作成してみた。後々、このフォルダの中に、3Dモデルデータ、フォントファイル、サウンドファイル等を入れていく。

3d_tuto01_create_project_ss08.png


引き続き、プレイヤーキャラのシーンを作ってみる。

#2 [godot] Godot Engineでプレイヤーキャラシーンを作成

Godot Engine 3.2.3 x64 を使って3D表示の簡単なシューティングゲームっぽいものを作る。

今回はプレイヤーキャラのシーンを作成する。

ノードを構成。 :

プレイヤーキャラのルートノードは KinematicBody にしてみる。KinematicBody は、アタリ範囲と表示モデルを持って、かつ、物理法則に従わないで動く物体に使うノードらしい。

「その他のノード」を選択。

3d_tuto02_create_player_ss01.png


「KinematicBody」を選んで「作成」。

3d_tuto02_create_player_ss02.png


KinematicBody がルートノードとして登録された。KinematicBodyを選択した状態で、左上のプラスアイコンをクリックしてノードを追加していく。

3d_tuto02_create_player_ss03.png


表示モデルを担当する MeshInstanceノードと、アタリ範囲を担当する CollisionShapeノードを追加した。

3d_tuto02_create_player_ss04.png

KinematicBody
  │
  ├─ MeshInstance
  │
  └─ CollisopnShape

簡易表示モデルを用意する。 :

簡単な表示モデルを用意する。MeshInstanceを選択。

3d_tuto02_create_player_ss05.png


Meshプロパティの右の「空」をクリック。

3d_tuto02_create_player_ss06.png


Godot Engine にはあらかじめ簡単な3Dモデル形状が何種類か用意されている。カプセル形状、円筒、球などが用意されているが、今回は箱の形をしたモデル、「新規CubeMesh」を選択。

3d_tuto02_create_player_ss07.png


CubeMesh が作成されて、3Dウインドウ内にも箱が表示された。Meshの横のサムネイル画像をクリックして設定を変更していく。

3d_tuto02_create_player_ss08.png


x,y,z の値を弄って箱の形を変更する。

3d_tuto02_create_player_ss09.png

マテリアルを設定。 :

Material を作成して箱に色を付ける。Materialプロパティの横の「空」をクリックして、「新規SpatialMaterial」を選択。

3d_tuto02_create_player_ss10.png


Materialが作成された。サムネイル画像をクリックして設定していく。

3d_tuto02_create_player_ss11.png


基本色は Albedoプロパティで設定できる。Albedo → Color をクリック。

3d_tuto02_create_player_ss12.png


色選択ウインドウが開く。今回は水色を選んでみた。色選択ウインドウの外をクリックすれば色選択ウインドウは閉じられる。

3d_tuto02_create_player_ss13.png


箱の色が水色になった。

3d_tuto02_create_player_ss14.png


Materialプロパティウインドウから抜ける場合は、右上にある左向きの記号を ―― 「戻る」ボタンをクリックする。

3d_tuto02_create_player_ss15.png


MeshInstanceのプロパティウインドウに戻ってきた。

3d_tuto02_create_player_ss16.png

メッシュを追加して位置調整。 :

MeshInstance は、Transform 以下のプロパティを変更することで、移動(Translation)、回転(Rotation)、拡大縮小(Scale)もできる。

3d_tuto02_create_player_ss17.png


水色の箱と同様に、黄色の箱も追加した。水色部分を本体、黄色部分をコクピット(?)として扱う予定。

3d_tuto02_create_player_ss18.png


Spatialノードを追加して、2つのMeshInstanceをSpatialノードの下にドラッグアンドドロップで移動した。

3d_tuto02_create_player_ss19.png

Spatialノードというのは…座標系だけを担当するノード、フォルダみたいなものとでも言えばいいのか…。Spatialノードを移動・回転・拡大縮小すれば、Spatialノードの下にぶら下がってる各ノードもその影響を受ける。

アタリ範囲を作成して調整。 :

アタリ範囲を作成する。CollisionShape を選択。

3d_tuto02_create_player_ss20.png


Shapeプロパティの横の「空」をクリック。今回は箱の形をしたアタリ範囲、「新規BoxShape」を選ぶ。

3d_tuto02_create_player_ss21.png


アタリ範囲が作成された。小さい赤丸をドラッグしてアタリ範囲の大きさを調整する。

3d_tuto02_create_player_ss22.png


コクピット(?)部分の合うようにアタリ範囲を設定した。

3d_tuto02_create_player_ss23.png

透視投影と平行投影を切り替え。 :

アタリ範囲を設定する際、透視投影より平行投影にしたほうが楽かもしれない。切り替え方は、左上にある「透視投影」をクリックしてメニューを表示。

3d_tuto02_create_player_ss24.png


「平行投影」を選択。

3d_tuto02_create_player_ss25.png


表示が切り替わった。

3d_tuto02_create_player_ss26.png


ちなみに、blender の操作方法と同様に、テンキーの5キーを押すことでも透視投影と平行投影を切り替えることができる。

ノード名を変更。 :

各ノード名を変更。

3d_tuto02_create_player_ss27.png

3d_tuto02_create_player_ss28.png

Player (KinematicBody)
  │
  ├─ PlayerModel (MeshInstance)
  │     │
  │     ├─ MeshInstance
  │     │
  │     └─ MeshInstance
  │
  └─ CollisopnShape

シーンを保存。 :

シーンを保存する。シーン → 名前を付けてシーンを保存。

3d_tuto02_create_player_ss29.png


res:// の下に assetsフォルダを新規作成。

3d_tuto02_create_player_ss30.png


Player.tscn として保存。

3d_tuto02_create_player_ss31.png

スクリプトファイルをアタッチ。 :

Playerシーンのスクリプトファイルをアタッチする。Playerノードを選択して、右上のスクリプトアタッチアイコンをクリック。

3d_tuto02_create_player_ss32.png


res:// の下に scriptsフォルダを新規作成。

3d_tuto02_create_player_ss33.png


res://scripts/Player.gd として指定。

3d_tuto02_create_player_ss34.png


スクリプトファイルを用意できた。

3d_tuto02_create_player_ss35.png


次回はメインシーンを用意して、今回作成したプレイヤーキャラをゲームウインドウに表示してみたい。

#3 [nitijyou] 歯医者に行ってきた

近所のS歯科まで電動自転車で。PM02:10-PM02:15まで治療というかメンテナンス。

帰りにケーズデンキに寄ってプリンタのインクを購入。

2020/11/14() [n年前の日記]

#1 [godot] Godot Engineでメインシーンを作成

Godot Engine 3.2.3 x64 を使って3D表示の簡単なシューティングゲームっぽいものを作る。

今回はメインシーンを作成して、ゲームウインドウにプレイヤーキャラを表示してみたい。

シーンを新規作成。 :

「シーン」→「新規シーン」を選択。

3d_tuto03_create_main_ss01.png


「その他のノード」を選択。

3d_tuto03_create_main_ss02.png


Nodeノードを選択して作成。

3d_tuto03_create_main_ss03.png

プレイヤーキャラのシーンを追加。 :

上のほうにあるインスタンス追加ボタンをクリック。

3d_tuto03_create_main_ss04.png


プレイヤーキャラのシーン assets/Player.tscn を選択。

3d_tuto03_create_main_ss05.png


Nodeの下に Player が追加されて、3Dウインドウ内にプレイヤーキャラが表示された。

3d_tuto03_create_main_ss06.png

ノード名を変更してシーンを保存。 :

ノード名を変更。ルートノードの Node を Main に変更。

3d_tuto03_create_main_ss07.png


res:// の下に Main.tscn としてシーンを保存。

3d_tuto03_create_main_ss08.png

実行してみる。 :

F6キーを押してシーンを実行してみる。あるいは右上の再生ボタンをクリック。

3d_tuto03_create_main_ss09.png


ゲームウインドウが表示される。が、何も表示されない…。

3d_tuto03_create_main_ss10.png

カメラを追加。 :

ゲームウインドウに何も表示されなかったのは、カメラ(Cameraノード)が存在してなかったから。Godot Engine で3Dゲームを作る際、Camera が無いと何も表示されないらしい。

Cameraノードを追加する。Mainノードを選択して、左上のプラスアイコンをクリック。

3d_tuto03_create_main_ss11.png


Camera を選択して「作成」。

3d_tuto03_create_main_ss12.png


Camera が追加された。Camera を選択。

3d_tuto03_create_main_ss13.png


カメラの位置、角度を調整する。

3d_tuto03_create_main_ss14.png


F6キーを押してシーンを実行してみる。プレイヤーキャラが表示された。

3d_tuto03_create_main_ss15.png


次回はプレイヤーのスクリプトを書いてプレイヤーキャラをカーソルキーで移動させたい。

#2 [godot] Godot Engineでプレイヤーをカーソルキーで動かす

Godot Engine 3.2.3 x64 を使って3D表示の簡単なシューティングゲームっぽいものを作る。

今回はプレイヤーのスクリプトを書いて、プレイヤーキャラをカーソルキーで動かしてみる。

スクリプトファイルを編集。 :

Playerシーンを開いて、Playerノード名の横のスクリプトアイコンをクリック。これでスクリプトエディタが開かれて編集できるようになる。

3d_tuto04_move_player_ss01.png


以下の内容を記述。

_Player.gd
extends KinematicBody

const SPEED = 32
var velocity = Vector3()

func _ready():
    pass # Replace with function body.

#func _process(delta):
#   pass

func _physics_process(delta):
    # move
    velocity = Vector3()
    if Input.is_action_pressed("ui_right"):
        velocity.x = 1
    elif Input.is_action_pressed("ui_left"):
        velocity.x = -1
    if Input.is_action_pressed("ui_down"):
        velocity.z = 1
    elif Input.is_action_pressed("ui_up"):
        velocity.z = -1
    
    # Do not multiply by delta when using move_and_slide()
    velocity = velocity.normalized() * SPEED
    move_and_slide(velocity)

簡単に説明すると…。
  • KinematicBodyノードを使ってる場合は、_process(delta) ではなく _physics_process(delta) の中に移動処理等を書く。
  • Input.is_action_pressed("ui_right") で、カーソルキーの右キーが押されているか判別できる。
  • move_and_slide(velocity) で velocity の方向に移動する。delta は掛けなくてよい。

Mainシーンを開いて実行してみる。



カーソルキーを押して前後左右に動かせるようになった。ただ、画面の端を超えてしまってもそのまま動き続けてしまう…。そのあたりの補正処理は後で入れることにする。

次回は背景に相当するシーンを作ってみたい。

#3 [godot] Godot Engineで背景シーンを作成

Godot Engine 3.2.3 x64 を使って3D表示の簡単なシューティングゲームっぽいものを作る。

今回は背景(BG)に相当するシーンを仮で作って表示してみる。

BGシーンを作成。 :

以下のようなシーンを作って、res://assets/ 以下に Bg.tscn として保存する。

3d_tuto05_add_bg_ss01.png

ルートノードとして Spatialノードを置いて、その下に Spatialノード(BgModelというノード名に変更)や MeshInstance ノードを追加して作成。あくまで仮なので、形状や配置はテキトーでいい。

ただ、スクロールモドキの処理を入れたいので…。
  • ルートノード(Bg)の下に BgModel という名前の Spatial を作成して、その中に全体を入れておく。
  • z軸方向にパターン(?)が繰り返すような形にしておく。
Bg (Spatial)
│
└─ BgModel (Spatial)
       │
       ├─ Spatial1
       ├─ Spatial2 (Spatial1 を複製)
       └─ Spatial3 (Spatial1 を複製)

Spatial1 の下に MeshInstance を置きまくって、ある程度それらしい形になったら、その Spatial1 を右クリック → 複製して、複製後の Spatial のz値だけをずらしてやれば、パターンを繰り返しているような見た目にできる。

Mainシーンを開いて、Bgシーンのインスタンスを追加。

3d_tuto05_add_bg_ss02.png


Bg の位置を調整。テンキーの5キーを押すと平行投影と透視投影の切り替え、テンキーの3キーを押すと右側面表示になるので、側面を表示しながら調整すれば作業がしやすい。あるいは、右上の「x」と書かれた赤丸をクリックしても側面図になる。

3d_tuto05_add_bg_ss03.png


スクリプトファイル res://scripts/Bg.gd を追加してスクリプトを記述。

3d_tuto05_add_bg_ss04.png

スクリプトの内容は以下。

_Bg.gd
extends Spatial

export var scroll_speed = 30
export var limit_z = 40
export var add_z = -40

func _ready():
    pass # Replace with function body.

func _process(delta):
    $BgModel.translation.z += scroll_speed * delta
    if $BgModel.translation.z >= limit_z:
        $BgModel.translation.z += add_z

_process(delta) が呼ばれるたびに、BgModel のz座標を変化させて、ある程度変化したら座標を巻き戻す(?)ようにしている。

Mainシーンを開いて、F6キーを押して動作確認。



スクロールしているような感じで動いてくれた。

カメラからの見た目を確認。 :

Godot Engine では、画面左上の「プレビュー」という項目にチェックを入れると、カメラからの見え方を確認できる。

Camera ノードを選択。画面左上に「プレビュー」という項目が表示されるのでチェックを入れる。

3d_tuto05_add_bg_ss06.png


3Dウインドウ上の見た目が、カメラからの見た目になった。

3d_tuto05_add_bg_ss07.png

この状態で、カメラの位置や角度、Bgの位置を調整すれば作業が楽。

次回はプレイヤーキャラから弾を撃ってみる。

#4 [godot] Godot Engineでプレイヤーの弾を撃つ

Godot Engine 3.2.3 x64 を使って3D表示の簡単なシューティングゲームっぽいものを作る。

今回はプレイヤーの弾を撃ってみる。

プレイヤーの弾のシーンを作成。 :

プレイヤーの弾のシーン res://asets/PlayerBullet.tscn を作成する。

ルートノードに Area、その下に表示モデルを担当する Spatial、MeshInstance と、アタリ範囲を担当する CollisionShape を追加する。

3d_tuto06_create_player_bullet_ss01.png

Area
  ├─ Spatial
  │     ├─ MeshInstance
  │     └─ MeshInstance
  └─ CollisionShape

Areaノードは、表示モデルとアタリ範囲を持って、かつ、物理法則に従わない動きをする物体に使うノードらしい。

MeshInstance の Mesh に割り当てた Material で、Emission(発光)を有効にしておく。これで、画面に表示されたときに光ってる感じになって少しは目立つはず。

3d_tuto06_create_player_bullet_ss02.png


ルートノードを PlayerBullet にリネーム。

3d_tuto06_create_player_bullet_ss03.png


res://assets/ の下に PlayerBullet.tscn として保存。

3d_tuto06_create_player_bullet_ss04.png

スクリプトファイルを追加。 :

スクリプトファイル、res://scripts/PlayerBullet.gd を追加。PlayerBullet を選択して、右上のスクリプトアタッチアイコンをクリック。

3d_tuto06_create_player_bullet_ss05.png

タイマーノードを追加。 :

本来なら、弾が画面外に出たら自分を消去する処理を作りたいけれど、画面外かどうかを判別する方法が分からない…。

とりあえずの簡易処理として、弾が出現して一定時間が経過したら自分自身を消去するようにしてみる。そのために Timerノードを追加。

3d_tuto06_create_player_bullet_ss06.png


Timerノードのプロパティを設定。
  • Wait Time を 2 に。
  • One Shot にチェックを入れて有効化。
  • Autostart にチェックを入れて有効化。

3d_tuto06_create_player_bullet_ss07.png


Timerノードの timeoutシグナルにメソッドを接続。ノードタブをクリック → timeout を選択して右クリック → 「接続」。

3d_tuto06_create_player_bullet_ss08.png


PlayerBullet を選択して「接続」。

3d_tuto06_create_player_bullet_ss09.png


スクリプトファイル PlayerBullet.gd に、_on_Timer_timeout() が追加された。自分自身を消去するメソッド、queue_free() を追記する。

3d_tuto06_create_player_bullet_ss10.png

これで、PlayerBullet が画面に出現すると Timer が自動実行されて、指定時間が来たら自分を消去、という処理になる。

弾の移動処理を追加。 :

プレイヤーの弾のスクリプトファイル res://scripts/PlayerBullet.gd に、弾の移動処理を追加する。以下を記述。

_PlayerBullet.gd
extends Area

var velocity = Vector3()
var speed = 90

func _ready():
    velocity = Vector3(0, 0, -1)

#func _process(delta):
#   pass

func _physics_process(delta):
    translate(velocity * speed * delta)

func _on_Timer_timeout():
    queue_free()

translate(velocity * speed * delta) で、現在座標を (velocity * speed * delta) 分変化させている。

プレイヤーの弾を登録するノードを用意。 :

Mainシーンに、発生させたプレイヤーの弾を登録していくためのノード、PlayerBullets を用意する。

Mainシーンを開いて Spatial ノードを追加。

3d_tuto06_create_player_bullet_ss11.png


PlayerBullets にリネーム。

3d_tuto06_create_player_bullet_ss12.png

プレイヤーから弾を発生させる。 :

プレイヤーキャラから弾を発生させる。今回はショットボタンを押さなくても自動・一定間隔で弾を次々に発射するようにしてみる。

プレイヤーのシーン、Player.tscn を開いて、Timerノードを追加。ShotTimer にリネーム。このタイマーを使って弾の発生処理をさせる。

3d_tuto06_create_player_bullet_ss13.png


ShotTimerのプロパティを設定。
  • Wait Time は 0.065 に。高橋名人が1秒間に16連射していたらしいので、それに近い値を指定してみたつもり。
  • Autostart にチェックを入れて有効化。

3d_tuto06_create_player_bullet_ss14.png


timeoutシグナルにメソッドを接続。ノードタブをクリック → timeout を選択して右クリック → 「接続」。

3d_tuto06_create_player_bullet_ss15.png


Player を選択して「接続」。

3d_tuto06_create_player_bullet_ss16.png


Playerのスクリプトファイル、res://scripts/Player.gd に、_on_ShotTimer_timeout() というメソッドが追加された。ShotTimer で設定した時間間隔で、このメソッドが呼び出される。

Player.gd に以下を記述。

_Player.gd
extends KinematicBody

export (PackedScene) var PlayerBullet

const SPEED = 32
var velocity = Vector3()

func _ready():
    pass # Replace with function body.

#func _process(delta):
#   pass

func _physics_process(delta):
    # move
    velocity = Vector3()
    if Input.is_action_pressed("ui_right"):
        velocity.x = 1
    elif Input.is_action_pressed("ui_left"):
        velocity.x = -1
    if Input.is_action_pressed("ui_down"):
        velocity.z = 1
    elif Input.is_action_pressed("ui_up"):
        velocity.z = -1
    
    # Do not multiply by delta when using move_and_slide()
    velocity = velocity.normalized() * SPEED
    move_and_slide(velocity)

func _on_ShotTimer_timeout():
    var bullet = PlayerBullet.instance()
    bullet.translation = Vector3(translation.x, translation.y, translation.z - 1.0)
    get_tree().root.get_node("Main/PlayerBullets").add_child(bullet)

  • 最初のほうで、export (PackedScene) var PlayerBullet を書いて、PlayerBulletシーンを入れておく変数 PlayerBullet を用意する。
  • _on_ShotTimer_timeout() の中でプレイヤーの弾の発生処理をする。PlayerBullet のインスタンスを生成、座標を Player のちょっと前に設定してから、Mainシーンの PlayerBulletsノードに登録している。

Playerシーンのプロパティ Player Bullet に、PlayerBulletシーンを設定する。Playerノードを選択して、Player Bullet の横の「空」をクリックして「読込み」。

3d_tuto06_create_player_bullet_ss17.png


res://assets/PlayerBullet.tscn を選択して「開く」。これで、Player Bullet にプレイヤーの弾のシーンを設定できた。

3d_tuto06_create_player_bullet_ss18.png

動作確認。 :

Mainシーンを開いてF6キーを押して動作確認。



それっぽい感じで弾を撃ってくれるようになった。

次回は敵を作ってみる。

#5 [godot] Godot Engineで敵のシーンを作成

Godot Engine 3.2.3 x64 を使って3D表示の簡単なシューティングゲームっぽいものを作る。

今回は敵のシーンを作ってみる。

ノード構成を作成。 :

ルートノードを Area にして、以下のノード構成でシーンを作成。

3d_tuto07_create_enemy_ss01.png


ノードをリネーム。

3d_tuto07_create_enemy_ss02.png

EnemyZako (Area)
  │
  ├─ EnemyZakoModel (Spatial)
  │     │
  │     └─ MeshInstance
  │
  ├─ CollisionShape
  │
  └─ ShotTimer (Timer)


MeshInstance の Meshプロパティで、新規 CapsuleMesh を作成。色は黄色にしてみた。

3d_tuto07_create_enemy_ss03.png

3d_tuto07_create_enemy_ss04.png

3d_tuto07_create_enemy_ss05.png


アタリ範囲を設定。CollisonShape を選択して、Shape に箱型のアタリ、BoxShape を新規作成。

3d_tuto07_create_enemy_ss06.png


res://assets/ 以下に、EnemyZako.tscn としてシーンを保存。

3d_tuto07_create_enemy_ss07.png

スクリプトを追加。 :

EnemyZako にスクリプト res://scripts/EnemyZako.gd をアタッチ。

3d_tuto07_create_enemy_ss08.png

EnemyZako.gd の内容を以下にする。

_EnemyZako.gd
extends Area

export (PackedScene) var enemybullet

var base_pos = Vector3()
var angle = 0
export var move_w = 22
export var move_h = 12

func _ready():
    base_pos = translation
    angle = 0

#func _process(delta):
#   pass

func _physics_process(delta):
    move(delta)
    
func move(delta):
    angle += delta
    translation.x = base_pos.x + move_w * cos(deg2rad(angle * 90))
    translation.z = base_pos.z + move_h * sin(deg2rad(angle * 70))

translation.x と translation.z に sin値、cos値を入れて画面の中をふらふらと動くようにしている。

Mainシーンに追加。 :

Mainシーンに、EnemyZakoシーンをインスタンスとして追加する。初期位置は適当に調整。

3d_tuto07_create_enemy_ss09.png

平行光源を追加。 :

作業をしていてなんだか画面が暗いような気がしてきたので、Mainシーンに、平行光源の DirectionalLightノードを追加して光を当ててみる。

3d_tuto07_create_enemy_ss10.png


Shadow の Enabled にチェックを入れて有効にすれば、画面の中で影も描画されるようになる。

3d_tuto07_create_enemy_ss11.png

動作確認。 :

Mainシーンを開いて、F6キーを押して動作確認。



敵に相当するシーンが画面の中でふわふわと動いてくれた。

次回は敵に弾を撃たせてみる。

#6 [godot] Godot Engineで敵から弾を撃たせる

Godot Engine 3.2.3 x64 を使って3D表示の簡単なシューティングゲームっぽいものを作る。

今回は敵から弾を撃たせてみる。

敵弾シーンを作成。 :

敵弾用のシーン EnemyBullet.tscn を作成していく。「シーン」 → 「新規シーン」を選択。

3d_tuto08_create_enemy_bullet_ss01.png


ルートノードとしてAreaノードを登録して、その下に以下のノードを追加。

3d_tuto08_create_enemy_bullet_ss02.png


ルートノードをEnemyBulletにリネーム。Timer を KillTimer にリネーム。

3d_tuto08_create_enemy_bullet_ss03.png

EnemyBullet (Area)
  │
  ├─ MeshInstance
  │
  ├─ CollisonShape
  │
  └─ KillTimer (Timer)


MeshInstance の Meshプロパティで、新規 SphereMesh を選んで、球の形をしたモデルを設定。

3d_tuto08_create_enemy_bullet_ss04.png


Material で Emission を有効にして発光するようにした。

3d_tuto08_create_enemy_bullet_ss05.png


アタリ範囲(CollisionShapeが担当)は、Shape で SphereShape を指定。球の形でアタリ範囲を指定できる。

3d_tuto08_create_enemy_bullet_ss06.png


res://assets/EnemyBullet.tscn としてシーンを保存した。

スクリプトを追加。 :

EnemyBulletノードを選択してスクリプトファイルをアタッチ。res://scripts/EnemyBullet.gd として保存した。

タイマーを設定。 :

本来なら、敵弾が画面外に出たかどうかを判別して、出ていたら自分(= 敵弾)を消去する、という処理をしたいけれど…。今回も、とりあえずの簡易処理として、一定時間が経過したら自分を消去、という処理にして誤魔化しておく。

KillTimer を設定。
  • Wait Time を 3 に。
  • Autostart を有効化。

3d_tuto08_create_enemy_bullet_ss07.png


timeoutシグナルにメソッドを接続する。ノードタブをクリック → timeout を選択して右クリック → 「接続」。

3d_tuto08_create_enemy_bullet_ss08.png


EnemyBullet を選択して「接続」すれば、EnemyBullet.gd に _on_KillTimer_timeout() というメソッドが追加される。自分を消去する queue_free() を追記。

3d_tuto08_create_enemy_bullet_ss09.png

移動処理を書く。 :

res://scripts/EnemyBullet.gd に移動処理を書く。内容は以下。

_EnemyBullet.gd
extends Area

var velocity = Vector3()
var direction = 0
var speed = 3

func _ready():
    pass # Replace with function body.

#func _process(delta):
#   pass

func _physics_process(delta):
    translate(velocity * speed * 60 * delta)

func set_dir_and_speed(angle, spd):
    direction = angle
    speed = spd
    var x = cos(deg2rad(angle))
    var z = sin(deg2rad(angle))
    velocity = Vector3(x, 0, z)
    
func _on_KillTimer_timeout():
    queue_free()

set_dir_and_speed(角度、速度)を呼ぶことで、敵弾が飛んでいく方向と移動速度について初期設定ができるようにした。

敵に敵弾の発生処理を追加。 :

敵に、敵弾の発生処理を追加していく。EnemyZako.tscn を開いて、以下を行う。

  • Timerノードを追加して、ShotTimer にリネーム。
  • スクリプトファイル EnemyZako.gd の最初のあたりに、export (PackedScene) var enemybullet を追記。


変数 enemybullet に、GUI操作で、敵弾シーン EnemyBullet.tscn を指定しておく。Enemybulletプロパティの横の「空」をクリックして「読込み」。

3d_tuto08_create_enemy_bullet_ss10.png


res://assets/EnemyBullet.tscn を選択して「開く」。

3d_tuto08_create_enemy_bullet_ss11.png


敵弾を発生させるタイマー、ShotTimer を設定。
  • Wait Time を 1 に。1秒毎に敵弾を発生させる。
  • Autostart を有効化。

3d_tuto08_create_enemy_bullet_ss12.png


timeoutシグナルにメソッドを接続。EnemyZako を選んで「接続」。

3d_tuto08_create_enemy_bullet_ss13.png


res://scripts/EnemyZako.gd の最後に、_on_ShotTimer_timeout() メソッドが追記される。この中に敵弾の発生処理を書いていけばいい。

3d_tuto08_create_enemy_bullet_ss14.png


EnemyZako.gd に、敵弾の発射処理を追加。以下の内容になる。ここでは敵弾を扇状に発射する処理を追加してる。

_EnemyZako.gd
extends Area

export (PackedScene) var enemybullet

var base_pos = Vector3()
var angle = 0
export var move_w = 22
export var move_h = 12
var bullets

func _ready():
    base_pos = translation
    angle = 0
    bullets = get_tree().root.get_node("Main/EnemyBullets")

#func _process(delta):
#   pass

func _physics_process(delta):
    move(delta)
    
func move(delta):
    angle += delta
    translation.x = base_pos.x + move_w * cos(deg2rad(angle * 90))
    translation.z = base_pos.z + move_h * sin(deg2rad(angle * 70))
    
func _on_ShotTimer_timeout():
    var angle_add = 12
    var angle = 90 - angle_add * 3
    var spd = 0.2
    for i in range(7):
        _shot(translation, angle, spd)
        _shot(translation, angle, spd * 0.8)
        angle += angle_add
    
func _shot(pos, angle, spd):
    var bullet = enemybullet.instance()
    bullet.translation = pos
    bullet.set_dir_and_speed(angle, spd)
    bullets.add_child(bullet)

Mainシーンに敵弾用のノードを追加。 :

Mainシーンに、敵弾を登録していくためのノードを追加する。Main.tscn を開いて、Mainノードの下に Spatialノードを追加。

3d_tuto08_create_enemy_bullet_ss15.png


EnemyBullets にリネーム。

3d_tuto08_create_enemy_bullet_ss16.png

動作確認。 :

Mainシーンを開いた状態でF6キーを押して動作確認。

3d_tuto08_create_enemy_bullet_ss17.png


1秒毎に、扇状に敵弾が発射される状態になった。しかし、敵弾が大き過ぎた…。調整しないといけない。

敵弾のサイズその他を調整。 :

考えてみたら、敵弾如きに奇麗で滑らかな球の3Dモデルは要らないなと思えてきた。サイズを調整するついでにポリゴン数をグンと減らして、ガクガクした感じの球のモデル(Mesh)にしてみた。どうせ小さく表示されるのだから分からないだろう…。
  • Radius で、球のモデルの半径を指定。
  • Height で、球のモデルの高さを指定。
  • Radial Segments と Rings で、球のモデルにどのくらいポリゴン数を使うかを指定。多ければ滑らかな球になるし、少なくすればガクガクした球になる。

3d_tuto08_create_enemy_bullet_ss18.png


また、敵弾が自分で消滅するまでの時間が短すぎた気がする。まだ画面の中に表示されているのにどんどん消えていくので不自然極まりない。時間を長目に調整。EnemyBullet の KillTimer の Wait Time を5に変更。

3d_tuto08_create_enemy_bullet_ss19.png


動作確認。Mainシーンを開いてF6キーを押す。



それっぽく表示された。

次回は各オブジェクトのアタリ属性を設定していきたい。

#7 [pc] メインPCの画面表示がおかしくなって焦った

メインPC(Windows10 x64 2004 + GeForce GTX 1060)をスリープ解除したら、画面がグチャグチャになっていて、かなり焦った…。目視で操作できないぐらいにおかしな表示だったので、Win + X → U → R を押して再起動してみたけれど症状は改善せず。BIOSが表示するスプラッシュ画面からして表示が崩れまくり。

PCを再起動しても改善しないということは、もしかしてビデオカードではなくてディスプレイ側がおかしいのでは。試しに液晶ディスプレイの電源を落としてから入れ直してみたら、表示が正常になった。

怖いな…。そろそろディスプレイが壊れ始めているのだろうか…。今ではもう入手できない偏光フィルタ方式の3D表示ディスプレイだから壊れると困る…。

いやまあ、最近は全く3D表示してないからアレだけど…。してないというか、できないんだけど。NVIDIAのドライバは立体視機能が削られたし、TriDef 3Dの販売会社も倒産してアクティベーションができないからソフトウェア的にもはや立体視をする方法が無いんだけど。酷い話。

一応、型番をメモ。

2020/11/15() [n年前の日記]

#1 [godot] Godot Engineでアタリ属性を設定

Godot Engine 3.2.3 x64 を使って3D表示の簡単なシューティングゲームっぽいものを作る。

今回は各オブジェクトでアタリ判定をするためにアタリ属性を設定してみる。

レイヤーとマスクの名前を付ける。 :

Godot Engine は各種アタリ判定(衝突判定)をする際に、レイヤー(Layer)とマスク(Mask)というものを利用して、衝突するものとしないものの関係を設定することができる。

まずは分かりやすくするために、各レイヤーにレイヤー名を設定しておく。

レイヤー名の設定はプロジェクト設定で行える。「プロジェクト」 → 「プロジェクト設定」を選択。

3d_tuto09_set_collison_mask_ss01.png


「Layer Names」 → 「3D Physics」を選択。右側に「Layer 1」「Layer 2」と一覧が並んでる。ここでレイヤー名を設定できる。

3d_tuto09_set_collison_mask_ss02.png


Layer 1 から順々に、必要になりそうなレイヤー名を入力していく。今回は以下の4つが必要になる。
  • player (プレイヤー)
  • playerbullets (プレイヤーの弾)
  • enemy (敵)
  • enemybullets (敵弾)

3d_tuto09_set_collison_mask_ss03.png


ついでに、3D Render にもレイヤー名をつけておく。将来的に使うかどうかわからないけど…。

3d_tuto09_set_collison_mask_ss04.png

各シーンのレイヤーとマスクを設定。 :

各シーンのレイヤーとマスクを設定していく。

まずはプレイヤーキャラ。res://assets/Player.tscn を開く。Collision の欄に「Layer」と「Mask」があるので、クリックして有効無効を切り替える。

  • プレイヤーキャラなので、Layer は一番左の player を有効化。
  • Mask でアタリ判定(衝突判定)をする対象を選ぶ。プレイヤーキャラは、「自分には当たらない」「自分の弾にも当たらない」「敵とは当たる」「敵弾にも当たる」ので、左から3番目の enemy と、左から4番目の enemybullets を有効化。

3d_tuto09_set_collison_mask_ss05.png


プレイヤーの弾を設定する。res://assets/PlayerBullet.tscn を開く。

  • プレイヤーの弾なので、Layer は左から2番目の playerbullets を有効化。
  • Mask は、「プレイヤーには当たらない」「自分(達)にも当たらない」「敵には当たる」「敵弾とは当たらない」ので、左から3番目の enemy だけを有効化。

3d_tuto09_set_collison_mask_ss06.png


敵を設定する。res://assets/EnemyZako.tscn を開く。

  • 敵なので、Layer は左から3番目の enemy を有効化。
  • Mask は、「プレイヤーには当たる」「プレイヤーの弾にも当たる」「自分には当たらない」「自分の弾にも当たらない」ので、一番左の player と、左から2番目の playerbullets を有効化。

3d_tuto09_set_collison_mask_ss07.png


敵弾を設定する。res://assets/EnemyBullet.tscn を開く。

  • 敵弾なので、Layer は左から4番目の enemybullets を有効化。
  • Mask は、「プレイヤーには当たる」「プレイヤーの弾には当たらない」「敵には当たらない」「自分(達)にも当たらない」ので、一番左の player だけを有効化。

3d_tuto09_set_collison_mask_ss08.png

グループ名を指定。 :

後々、何かと何かが当たった(衝突した)際に、一体何に当たったのかを調べる必要が出てくるかもしれない。その判別をするために、各シーンに「グループ名」をつけておくことにする。

例えば、プレイヤーと、プレイヤーの弾に異なるグループ名をつけておけば、敵が何かに当たった際にグループ名を調べて、それがプレイヤーなのか、プレイヤーの弾なのかを判別することができたりする。

プレイヤーキャラのシーン、Player.tscn を開いて、ノードタブをクリック → グループをクリック。「player」と入力して「追加」。これで、プレイヤーに「player」というグループ名をつけられる。

3d_tuto09_set_collison_mask_ss09.png


プレイヤーの弾、PlayerBullet.tscn を開いて、「playerbullets」というグループ名を設定。

3d_tuto09_set_collison_mask_ss10.png


敵のシーン、EnemyZako.tscn を開いて、「enemys」というグループ名を設定。

3d_tuto09_set_collison_mask_ss11.png


敵弾シーン、EnemyBullet.tscn を開いて、「enemybullets」というグループ名を設定。

3d_tuto09_set_collison_mask_ss12.png


これで、アタリ属性を設定できた。

次回はアタリ判定処理を作る。

#2 [godot] Godot Engineでアタリ判定処理を書く

Godot Engine 3.2.3 x64 を使って3D表示の簡単なシューティングゲームっぽいものを作る。

今回は各オブジェクトのアタリ判定処理を作っていく。

プレイヤーの弾にアタリ判定処理を追加。 :

プレイヤーの弾にアタリ判定処理を追加する。

プレイヤーの弾は、敵(EnemyZako)とだけ衝突するように Layer と Mask を使って設定してあるけれど、敵は Areaノードをルートノードとして作ってあるので…。

プレイヤーの弾と敵が衝突した際、プレイヤーの弾は「Areaとぶつかったよ」と、area_entered(area:Area) というシグナルを発行してくれる。そのシグナルにメソッドを接続してやれば、プレイヤーの弾と敵が当たった時にそのメソッドが呼ばれるので、そのメソッドの中に敵と当たった時の処理を書いておけばいい。

プレイヤーの弾のシーン、res://assets/PlayerBullet.tscn を開いて、シグナルにメソッドを接続する。ノードタブをクリック → シグナルをクリック。「area_entered(area:Area)」を選択して右クリックして「接続」。

3d_tuto10_collison_ss01.png


PlayerBullet を選択して「接続」。

3d_tuto10_collison_ss02.png


スクリプトファイル PlayerBullet.gd の最後に、_on_PlayerBullet_area_entered(area) というメソッドが追記されたので、敵と当たった時の処理を書く。

3d_tuto10_collison_ss03.png

記述内容は以下になる。

_PlayerBullet.gd
extends Area

var velocity = Vector3()
var speed = 90

func _ready():
    velocity = Vector3(0, 0, -1)

#func _process(delta):
#   pass

func _physics_process(delta):
    translate(velocity * speed * delta)

func _on_Timer_timeout():
    queue_free()

func _on_PlayerBullet_area_entered(area):
    if is_queued_for_deletion():
        return
    print("PlayerBullet Hit!")
    queue_free()

  • とりあえず仮の処理として、print() を呼んで当たったことを示すメッセージを出力してみる。
  • プレイヤーの弾が敵に当たったら、その場でプレイヤーの弾は消滅してほしいので、自分を消去する queue_free() を呼んでおく。
  • is_queued_for_deletion() は、自分に消去処理が要求されているかを調べることができる。もし自分が消去予定になっていたら、何も処理をせずにメソッドを抜けるようにしてある。

動作確認してみる。 :

Mainシーンを開いてF6キーを押して動作確認してみる。

プレイヤーの弾と敵が当たった時に「PlayerBullet Hit!」というメッセージが出力ウインドウに出力された。ちゃんと当たってることが判別できた。

3d_tuto10_collison_ss04.png


画面内でも、プレイヤーの弾が敵に当たった時に、プレイヤーの弾がその場で消滅している様子が見て取れる。

3d_tuto10_collison_ss05.png

動作確認できたので、メッセージを出力する print() は、頭に「# 」を追加してコメントアウトしておく。

    # print("PlayerBullet Hit!")

敵弾にアタリ判定処理を追加。 :

敵弾シーン EnemyBullet.tscn にもアタリ判定処理を追加していく。

敵弾は Layer と Mask を使ってプレイヤーとだけ当たるように設定してある。そしてプレイヤーキャラは KinematicBody をルートノードにして作ってあるので…。

敵弾 EnemyBullet (Area) は、プレイヤー Player (KinematicBody) と当たった際に、body_entered(body: Node) というシグナルを発行する。(area_entered()ではなくて、body_entered()。相手が Area ではなくて KinematicBody なので。)

このシグナルにメソッドを接続してやれば、敵弾がプレイヤーと当たった時にそのメソッドが呼ばれるので、そのメソッドの中にプレイヤーと当たった時の処理を書いておけばいい。

敵弾のシーン、res://assets/EnemyBullet.tscn を開いて、シグナルにメソッドを接続する。ノードタブをクリック → シグナルをクリック。「body_entered(body: Node) を選択して右クリックして「接続」。EnemyBullet を選択して「接続」。

3d_tuto10_collison_ss06.png


スクリプトファイル EnemyBullet.gd の最後に、_on_EnemyBullet_body_entered(body) というメソッドが追加された。このメソッドにプレイヤーと当たった時の処理を書く。

3d_tuto10_collison_ss07.png

内容は以下。

_EnemyBullet.gd
extends Area

var velocity = Vector3()
var direction = 0
var speed = 3

func _ready():
    pass # Replace with function body.

#func _process(delta):
#   pass

func _physics_process(delta):
    translate(velocity * speed * 60 * delta)

func set_dir_and_speed(angle, spd):
    direction = angle
    speed = spd
    var x = cos(deg2rad(angle))
    var z = sin(deg2rad(angle))
    velocity = Vector3(x, 0, z)
    
func _on_KillTimer_timeout():
    queue_free()

func _on_EnemyBullet_body_entered(body):
    if is_queued_for_deletion():
        return
    print("EnemyBullet Hit!")
    queue_free()

PlayerBullet とほとんど同じ処理になっている。

動作確認。Mainシーンを開いてF6キーを押す。敵弾がプレイヤーと当たるたびに、出力ウインドウにメッセージが表示された。ちゃんとアタリ判定ができている。

3d_tuto10_collison_ss08.png

動作確認できたので、print() をコメントアウト。

    # print("EnemyBullet Hit!")

敵にアタリ判定処理を追加。 :

敵にアタリ判定処理を追加していく。

敵は、Layer と Mask を使って、プレイヤー、及び、プレイヤーの弾と当たるように設定されている。そして、プレイヤーは KinematicBody、プレイヤーの弾は Area をルートノードにして作ってあるので…。
  • body_entered(body: Node) シグナルにメソッドを接続すれば、そのメソッドにプレイヤーと当たった時の処理を書ける。
  • area_entered(area: Area) シグナルにメソッドを接続すれば、そのメソッドにプレイヤーの弾と当たった時の処理を書ける。

敵のシーン、res://assets/EnemyZako.tscn を開いて、area_entered() シグナルと、body_entered() シグナルにメソッドを接続してやる。ノードタブをクリック → シグナルをクリック。それぞれのシグナルを右クリックして「接続」。EnemyZako を選択して「接続」。

3d_tuto10_collison_ss09.png

3d_tuto10_collison_ss10.png

3d_tuto10_collison_ss11.png

3d_tuto10_collison_ss12.png

スクリプトファイル EnemyZako.gd に、_on_EnemyZako_area_entered(area) と、_on_EnemyZako_body_entered(body) が追記された。

それぞれのメソッドに処理を書く。

3d_tuto10_collison_ss13.png

内容は以下。

_EnemyZako.gd
extends Area

export (PackedScene) var enemybullet

var base_pos = Vector3()
var angle = 0
export var move_w = 22
export var move_h = 12
var bullets

func _ready():
    base_pos = translation
    angle = 0
    bullets = get_tree().root.get_node("Main/EnemyBullets")

#func _process(delta):
#   pass

func _physics_process(delta):
    move(delta)
    
func move(delta):
    angle += delta
    translation.x = base_pos.x + move_w * cos(deg2rad(angle * 90))
    translation.z = base_pos.z + move_h * sin(deg2rad(angle * 70))
    
func _on_ShotTimer_timeout():
    var angle_add = 12
    var angle = 90 - angle_add * 3
    var spd = 0.2
    for i in range(7):
        _shot(translation, angle, spd)
        _shot(translation, angle, spd * 0.8)
        angle += angle_add
    
func _shot(pos, angle, spd):
    var bullet = enemybullet.instance()
    bullet.translation = pos
    bullet.set_dir_and_speed(angle, spd)
    bullets.add_child(bullet)

func _on_EnemyZako_area_entered(area):
    if is_queued_for_deletion():
        return
    print("playerbullet hit the enemy")

func _on_EnemyZako_body_entered(body):
    if is_queued_for_deletion():
        return
    print("player hit the enemy")


動作確認してみる。Mainシーンを開いてF6キーを押す。

プレイヤーを操作して敵と当ててみたり、プレイヤーの弾を敵に当ててみたりする。出力ウインドウに、当たってる旨を伝えるメッセージが出力された。

3d_tuto10_collison_ss14.png

これで一応、アタリ判定はできた。

さて、プレイヤーに敵弾が当たったらプレイヤーのHP(体力?)を減らしたり、敵にプレイヤーの弾が当たったら敵のHPを減らしたりしたい。次回は各HPを画面に表示するために、HUD(Head-Up Display)シーンを作成する。

2020/11/16(月) [n年前の日記]

#1 [godot] Godot EngineでHUDシーンを作成

Godot Engine 3.2.3 x64 を使って3D表示の簡単なシューティングゲームっぽいものを作る。

今回はプレイヤーや敵のHPを表示するためのHUDシーンを作成する。そのついでに、プレイヤーや敵に弾が当たったらHPが減るような処理も追加する。

フォントファイルをインポート。 :

画面に文字情報を表示するためには何かしらのフォントファイルが必要になる。Godot Engine はフォントファイルとして ttf や otf が使えるので、それらファイルをプロジェクトフォルダにインポートしてやればフォントが使えるようになる。

今回は、ドットコロンさん(?)がCC0で公開している Vegurフォント Version 0.701 を利用させてもらうことにした。ありがたや。

_Vegur | ドットコロン

vegur_0701.zip をDLして解凍すると、Vegur-Bold.otf, Vegur-Light.otf, Vegur-Regular.otf の3ファイルが得られる。太字の Vegur-Bold.otf を使うことにする。

ファイル一覧ウインドウに、Vegur-Bold.otf をドラッグアンドドロップ。これでファイルがコピーされてインポートされる。

3d_tuto11_create_hud_ss01.png


件のフォントファイルを res://imports/ 以下に置くことにした。違う場所にコピーされてしまった時は、ファイル一覧ウインドウ内でファイルをドラッグすれば置き場所を変更できる。

3d_tuto11_create_hud_ss02.png

HUD用のシーンを作成。 :

シーンを新規作成して以下のような構成でノードを追加。HUDのようなものは、ルートノードを Control にしておけばいいのだろうか。ちょっと自信無し。

3d_tuto11_create_hud_ss03.png


ノードをリネーム。

3d_tuto11_create_hud_ss04.png

Hud (Control)
  │
  ├─ PlayerHp (Label)
  │
  └─ EnemyHp (Label)

Labelのプロパティを変更していく。 :

Labelノードを設定して文字表示をする。PlayerHp (Label) を選択して、Textプロパティに「Player: 50/50」を入力。これは画面の左上に表示する予定。

3d_tuto11_create_hud_ss05.png


EnemyHp (Label) を選択して、Textプロパティに「Enemy: 990/990」を入力。これは画面の右上に表示したいので、Align を Right にしておく。これで右詰め表示されるはず。

3d_tuto11_create_hud_ss06.png


フォントを設定する。Custom Fonts → Font の横の「空」をクリックして「新規 DynamicFont」を選択。「DynamicFont」をクリックすればプロパティが表示されるので、Font Data に Vegur-Bold.otf を指定すれば Vegurフォントが使われるようになる。
  • Size で文字サイズを指定。
  • Use Filter を有効にすれば文字が少し滑らかになって表示される。
  • Font Color Shadow を有効にすれば文字に影がつく。
  • Shadow Offset X, Y で影のオフセット位置を変更できる。

3d_tuto11_create_hud_ss07.png


表示位置を調整。それらしい感じになった。

3d_tuto11_create_hud_ss08.png

Hudシーンを保存。 :

res://assets/ の下に Hud.tscn としてシーンを保存。

3d_tuto11_create_hud_ss09.png

スクリプトを書く。 :

Hudに、スクリプトファイルもアタッチする。res://scripts/ の下に Hud.gd として保存。

3d_tuto11_create_hud_ss10.png


Hud.gd にスクリプトを記述していく。

3d_tuto11_create_hud_ss11.png

スクリプトの内容は以下。とりあえず、PlayerHp、EnemyHp の表示を更新するためのメソッドだけ用意しておく。

_Hud.gd
extends Control

func _ready():
    pass # Replace with function body.

#func _process(delta):
#   pass

func update_player_hp(hp, hpmax):
    $PlayerHp.text = "Player: %d/%d" % [hp, hpmax]
    
func update_enemy_hp(hp, hpmax):
    $EnemyHp.text = "Enemy: %d/%d" % [hp, hpmax]

MainシーンにHudシーンを追加。 :

MainシーンにHudシーンのインスタンスを追加する。Main.tscn を開いて、Mainノードを選択。上のほうにあるインスタンス追加ボタンをクリックして、res://assets/Hud.tscn を選べば Hud が追加される。

3d_tuto11_create_hud_ss12.png

Mainシーンにスクリプトを用意。 :

Mainシーンにもスクリプトファイルを用意する。Mainを選んでスクリプトをアタッチ。res://scripts/Main.gd として保存した。

3d_tuto11_create_hud_ss13.png


スクリプトを記述する。

3d_tuto11_create_hud_ss14.png

内容は以下。

_Main.gd
extends Node

var player_hp_max = 0
var enemy_hp_max = 0

func _ready():
    player_hp_max = $Player.hp
    enemy_hp_max = $EnemyZako.hp

#func _process(delta):
#   pass

func damage_player():
    var hp = $Player.hp
    $Hud.update_player_hp(hp, player_hp_max)

func damage_enemy():
    var hp = $EnemyZako.hp
    $Hud.update_enemy_hp(hp, enemy_hp_max)

  • 初期化時に Player や Enemy のHPを取得して変数に記録。
  • Player 又は Enemy がダメージを受けた際、現在のHPを使ってHP表示を更新するメソッドを用意。

プレイヤーのスクリプトを修正。 :

Mainシーンのスクリプト内で、Player や Enemy は HP を持っていることを前提にした記述を追加したけれど、まだ Player側ではそんな変数を持たせてないのでそのあたりを追加する。

プレイヤーのスクリプトファイル、res://scripts/Player.gd を編集。内容は以下。

_Player.gd
extends KinematicBody

signal player_damaged
signal player_died

# export (PackedScene) var PlayerBullet
var PlayerBullet = preload("res://assets/PlayerBullet.tscn")

const SPEED = 32
var velocity = Vector3()
var bullets

var hp = 50
var damage = 0

func _ready():
    hp = 50
    # bullets = get_tree().root.get_node("Main/PlayerBullets")
    bullets = $"/root/Main/PlayerBullets"

#func _process(delta):
#   pass

func _physics_process(delta):
    # move
    velocity = Vector3()
    if Input.is_action_pressed("ui_right"):
        velocity.x = 1
    elif Input.is_action_pressed("ui_left"):
        velocity.x = -1
    if Input.is_action_pressed("ui_down"):
        velocity.z = 1
    elif Input.is_action_pressed("ui_up"):
        velocity.z = -1
    
    # Do not multiply by delta when using move_and_slide()
    velocity = velocity.normalized() * SPEED
    move_and_slide(velocity)
    
    if damage > 0:
        hp -= damage
        damage = 0
        if hp <= 0:
            hp = 0
            emit_signal("player_died")
        emit_signal("player_damaged")

func _on_ShotTimer_timeout():
    var bullet = PlayerBullet.instance()
    var pos = Vector3(translation.x, translation.y, translation.z - 1.5)
    bullet.translation = pos
    bullets.add_child(bullet)

  • 最初のあたりで、カスタムシグナルとして signal player_damaged と signal player_died を用意した。
  • hp という変数を用意した。
  • damage という変数を用意した。
  • 別の何かが damage に 0以外の値を入れたら、自分はその分ダメージを受けたのだ、ということにする。
  • hp から damage 分を引いて、hp が 0 になってなければ自分はまだ生きてる。0なら死んでる。
  • ダメージを受けた時は emit_signal("player_damaged") を呼んで player_damaged シグナルを発行する。
  • 死んだ時は emit_signal("player_died") を呼んで player_died シグナルを発行する。

プレイヤーがダメージを受けた時に発行されるカスタムシグナル、player_damaged にメソッドを接続する。Player を選択して、ノードタブをクリック → シグナルをクリック → player_damaged() を右クリックして「接続」。

3d_tuto11_create_hud_ss15.png


Main を選択して、メソッド名の欄に「damage_player」と入力して「接続」。メソッド名に括弧はつけなくていい。

3d_tuto11_create_hud_ss16.png

これで、プレイヤーがダメージを受けると Main.gd の damage_player() が呼ばれる状態になった。

敵のスクリプトを修正。 :

敵シーンにもプレイヤーシーンと同様の修正を施していく。

res://scripts/EnemyZako.gd を開いて修正。内容は以下。

_EnemyZako.gd
extends Area

signal enemy_damaged
signal enemy_died

export (PackedScene) var enemybullet

var base_pos = Vector3()
var angle = 0
export var move_w = 22
export var move_h = 12
var bullets

var hp = 990
var damage = 0
var attack_point = 10

func _ready():
    base_pos = translation
    angle = 0
    bullets = get_tree().root.get_node("Main/EnemyBullets")

#func _process(delta):
#   pass

func _physics_process(delta):
    move(delta)
    
func move(delta):
    angle += delta
    translation.x = base_pos.x + move_w * cos(deg2rad(angle * 90))
    translation.z = base_pos.z + move_h * sin(deg2rad(angle * 70))
    
func _on_ShotTimer_timeout():
    var angle_add = 12
    var angle = 90 - angle_add * 3
    var spd = 0.2
    for i in range(7):
        _shot(translation, angle, spd)
        _shot(translation, angle, spd * 0.8)
        angle += angle_add
    
func _shot(pos, angle, spd):
    var bullet = enemybullet.instance()
    bullet.translation = pos
    bullet.set_dir_and_speed(angle, spd)
    bullets.add_child(bullet)

func _on_EnemyZako_area_entered(area):
    if is_queued_for_deletion():
        return
    # print("playerbullet hit the enemy")
    if area.is_in_group("playerbullets"):
        hp -= area.attack_point
        if hp <= 0:
            hp = 0
            emit_signal("enemy_died")
        emit_signal("enemy_damaged")

func _on_EnemyZako_body_entered(body):
    if is_queued_for_deletion():
        return
    # print("player hit the enemy")
    if body.is_in_group("player"):
        body.damage = attack_point

修正内容は、Player.gd に対して行ったこととほとんど同じで、カスタムシグナル名が違う程度。

ただ、Enemy は自分でプレイヤーの弾(Areaノード)と当たったかどうかを調べるので、プレイヤーの弾が attack_point という変数を持っていることを前提にして、その値で hp を減らす処理をしている。

敵がダメージを受けた時に発行されるカスタムシグナル、enemy_damaged にメソッドを接続する。EnemyZako を選択して、ノードタブをクリック → シグナルをクリック → enemy_damaged() を右クリックして「接続」。

3d_tuto11_create_hud_ss17.png


Main を選択して、メソッド名の入力欄に「damage_enemy」と入力して「接続」。

3d_tuto11_create_hud_ss18.png

これで、敵がダメージを受けると Main.gd の damage_enemy() が呼ばれる状態になった。

敵弾のスクリプトを修正。 :

敵弾のスクリプト res://scripts/EnemyBullet.gd を修正する。内容は以下。

_EnemyBullet.gd
extends Area

var velocity = Vector3()
var direction = 0
var speed = 3
var attack_point = 10

func _ready():
    pass # Replace with function body.

#func _process(delta):
#   pass

func _physics_process(delta):
    translate(velocity * speed * 60 * delta)

func set_dir_and_speed(angle, spd):
    direction = angle
    speed = spd
    var x = cos(deg2rad(angle))
    var z = sin(deg2rad(angle))
    velocity = Vector3(x, 0, z)
    
func _on_KillTimer_timeout():
    queue_free()

func _on_EnemyBullet_body_entered(body):
    if is_queued_for_deletion():
        return
    # print("EnemyBullet Hit!")
    if body.is_in_group("player"):
        body.damage = attack_point
    queue_free()

  • 変数 attack_point を追加して、プレイヤーへの攻撃力を入れておく。
  • プレイヤーと当たった時は、プレイヤーが変数 damage を持っているはずだから、damage に自分の攻撃力を入れてやる。
  • プレイヤー側は、damage が0以外なら何かが当たってダメージを受けたという処理をする。

プレイヤーの弾のスクリプトを修正。 :

プレイヤーの弾のスクリプト res://scripts/PlayerBullet.gd を修正する。内容は以下。

_PlayerBullet.gd
extends Area

var velocity = Vector3()
var speed = 90

var attack_point = 10

func _ready():
    velocity = Vector3(0, 0, -1)

#func _process(delta):
#   pass

func _physics_process(delta):
    translate(velocity * speed * delta)

func _on_Timer_timeout():
    queue_free()

func _on_PlayerBullet_area_entered(area):
    if is_queued_for_deletion():
        return
    # print("PlayerBullet Hit!")
    queue_free()

  • 変数 attack_point を追加して、敵への攻撃力を入れておく。
  • 敵と当たった時は、敵側でこの attack_point を参照して処理をする。


これで、プレイヤーの弾が敵に当たったり、敵弾がプレイヤーに当たったりすると、それぞれのHPが減って、HUD上の表示が更新される状態になった。

しかし、このままだとプレイヤーに敵弾に当たったことが分かりづらい。次回はプレイヤーや敵がダメージを受けた時の簡単なエフェクト(?)をつけてみる。

#2 [nitijyou] 浴室のミニクリプトン電球を交換

朝、親父さんから、浴室(風呂場)に2つある照明の向かって右側がつかなくなったからチェックしてくれ、と頼まれた。確認した感じでは電球が切れてたようで。予備のミニクリプトン電球は親父さんが既に買っていた。親父さん用の押し入れの上のほうの黄色いプラスチック製の箱の中に2個セットの封を切ってない製品があったので1個を使用。まだ1個残ってるので次回電球が切れた時はソレを使えばよい。と、こうしてメモしておくけれど自分のことだからきっと絶対に忘れてしまうだろうなコレ…。

おそらくだけど、交換に使った製品は LDS100V54W・W・K・2P だと思う。100V、60W型(54W)、E17口金35mm径、ではなかろうか。パッケージがそんな感じの見た目だし。今回使ったのはホワイトだけど、クリアの製品もあるらしい。型番は LDS100V54W・C・K になる模様。

考えてみたらLED電球に交換するのもアリだったのかもしれない。ググったところ、E17口金、60W相当、密閉器具対応のLED電球は既にあるようだし。LED電球にすれば電球色以外にも昼白色や昼光色を選べるので、浴室内の雰囲気が結構変わるかもしれない。ただ、まだ値段が高目ではあるけれど…。

2020/11/17(火) [n年前の日記]

#1 [godot] Godot Engineでダメージエフェクトを作成

Godot Engine 3.2.3 x64 を使って3D表示の簡単なシューティングゲームっぽいものを作る。

今回は、プレイヤーや敵に弾が当たったことを分かりやすくするために簡単なダメージエフェクトをつけてみる。

プレイヤーの点滅表示処理を追加。 :

やはりアクションゲームの類で自機がダメージを受けたら点滅するものだろう。って一体いつの時代の話ですか…昭和か…。何にせよ、とりあえず点滅表示処理を追加してみる。

プレイヤーのシーン、res://assets/Player.tscn を開いて、Timer を2つ追加。DmagaeTimer と BlinkTimer にリネーム。

3d_tuto12_create_damage_effect_ss01.png


DamageTimer には、ダメージを受けてから何秒間はダメージを受けないかを指定。
  • Wait Time を 2 に。
  • One Shot を有効化。

3d_tuto12_create_damage_effect_ss02.png


BlinkTimer には、表示と非表示を切り替える時間間隔を指定。
  • Wait Time を 0.05 に。

3d_tuto12_create_damage_effect_ss03.png


それぞれの timeoutシグナルにメソッドを接続してやる。
  1. DmagaeTimer や BlinkTimer を選んでから、ノードタブをクリック → シグナルをクリック。
  2. timeout を右クリックして「接続」。
  3. Player を選んで「接続」。
プレイヤーのスクリプトファイル、res://scripts/Player.gd に、_on_DamageTimer_timeout() と _on_BlinkTimer_timeout() の2つのメソッドが追記される。

スクリプトファイル Player.gd に処理を追加。内容は以下。今回の処理に関係があるところだけ貼っておく。

_Player.gd
# ...

var damaging = false

func _ready():
    # ...

    damage = 0
    damaging = false

    # ...

func _physics_process(delta):

    # ...

    if not damaging:
        if damage > 0:
            hp -= damage
            damage = 0
            if hp <= 0:
                hp = 0
            emit_signal("player_damaged")
            damaging = true
            $DamageTimer.start()
            $BlinkTimer.start()

# ...

func _on_DamageTimer_timeout():
    $BlinkTimer.stop()
    damage = 0
    damaging = false
    visible = true
    if hp <= 0:
        hp = 0
        emit_signal("player_died")

func _on_BlinkTimer_timeout():
    visible = not visible

  • ダメージ中を示すフラグ、damaging を用意。
  • ダメージ中は、自分がダメージを受けたかどうかは判定しない。
  • ダメージを受けたら、ダメージ中フラグを立ててから、$DamageTimer.start()、$BlinkTimer.start() を呼んで、2つの Timer を開始させる。
  • BlinkTimer は指定した時間間隔で timeoutシグナルを何度も繰り返し発行する。そのたびに _on_BlinkTimer_timeout() が呼ばれる。このメソッドの中で、visibleプロパティを反転させて、表示と非表示を切り替えている。
  • DmagaeTimer は指定時間が経過すると timeoutシグナルを1回だけ発行。_on_DamageTimer_timeout() が呼ばれる。BlinkTimerを停止させて、ダメージ中フラグを降ろして、表示を有効化。

これで、プレイヤーに敵弾が当たってダメージを受けると一定時間点滅するようになった。

画面フラッシュを追加。 :

プレイヤーに弾が当たると点滅するようになったけど、これではまだダメージを受けたことが伝わりにくいので、画面を軽くフラッシュさせてみる。

フラッシュさせるためのノードは、HUDシーンに追加する。res:/assets/Hud.tscn を開く。

ColorRectノードを追加。ColorRectノードは指定色で矩形を描画できる。

3d_tuto12_create_damage_effect_ss04.png


Flash にリネーム。

3d_tuto12_create_damage_effect_ss05.png


Flash (ColorRect) のプロパティを変更。
  • Color を RGBA=(255, 255, 255, 200) に。
  • Size x, y を (1280, 720) に。ゲームウインドウ全体を覆いつくすサイズを指定。

3d_tuto12_create_damage_effect_ss05b.png


Timer を追加。FlashTimer にリネーム。この Timer を使って、一定時間が過ぎたらフラッシュ状態を終了させる。

3d_tuto12_create_damage_effect_ss06.png


FlashTimer のプロパティを変更。
  • Wait Time を 0.125 に。0.125秒だけ Flash を表示させる。
  • One Shot を有効化。

3d_tuto12_create_damage_effect_ss08.png


FlashTimer の timeoutシグナルにメソッドを接続。
  1. FlashTimer を選択してから、ノードタブをクリック → シグナルをクリック。
  2. timeout を右クリックして「接続」。
  3. Hud を選択して「接続」。
res://scripts/Hud.gd に、_on_FlashTimer_timeout() が追記される。

Flash の表示順を変更。ノード一覧の一番上に置くことで、HP表示より奥に表示されるようにする。

3d_tuto12_create_damage_effect_ss07.png


HUDシーンのスクリプト、res://scripts/Hud.gd を修正。内容は以下。

_Hud.gd
# ...

func _ready():
    $Flash.visible = false

# ...

func start_flash():
    $Flash.visible = true
    $FlashTimer.start()
    
func _on_FlashTimer_timeout():
    $Flash.visible = false

  • 初期化処理時に Flashノードを非表示にする。
  • 画面フラッシュを開始するメソッド、start_flash() を追加。Flashノードの表示を有効化して、FlashTimer を開始している。
  • FlashTimer は指定時間が経過すると timeout シグナルを発行して _on_FlashTimer_timeout() が呼ばれる。Flashノードを非表示にする。

Mainシーンのスクリプト、res://scripts/Main.gd も修正。内容は以下。

_Main.gd
# ...

func damage_player():
    # ...
    $Hud.start_flash()

# ...

  • プレイヤーがダメージを受けると Main.gd内の damage_player() が呼ばれる。その中で $Hud.start_flash() を呼んで Hud の画面フラッシュを開始させる。

これで、プレイヤーに敵弾が当たってダメージを受けると、一瞬画面がフラッシュするようになった。

敵のダメージエフェクトを追加。 :

敵のスクリプト、res://scripts/EnemyZako.gd を修正して、敵がダメージを受けた時のエフェクト(?)を追加する。

今回は、一定時間(0.25秒)、ランダムに位置がぶれる処理を追加してみた。

_EnemyZako.gd
# ...

var damage_timer = 0

var rnd = RandomNumberGenerator.new()

func _ready():
    # ...

    damage = 0
    damage_timer = 0

    # ...

func _physics_process(delta):
    # ...
    check_damage()
    damaging_animation(delta)
    
# ...

func check_damage():
    if damage > 0:
        hp -= damage
        damage = 0
        damage_timer = 0.25
        if hp <= 0:
            hp = 0
            emit_signal("enemy_died")
        emit_signal("enemy_damaged")

func damaging_animation(delta):
    if damage_timer > 0:
        damage_timer -= delta
        var target_mesh = $EnemyZakoModel
        if damage_timer <= 0:
            damage_timer = 0
            target_mesh.translation = Vector3()
        else:
            var r = 0.5
            var x = rnd.randf_range(-r, r)
            var z = rnd.randf_range(-r, r)
            target_mesh.translation = Vector3(x, 0, z)

# ...
            
func _on_EnemyZako_area_entered(area):
    if is_queued_for_deletion():
        return
    # print("playerbullet hit the enemy")
    if area.is_in_group("playerbullets"):
        damage = area.attack_point

# ...


  • var rnd = RandomNumberGenerator.new() で疑似乱数生成器を用意する。
  • rnd.randf_range(-r, r) で、-r から r の範囲で乱数を生成。
  • 自分(EnemyZako)の座標ではなく、その下にぶら下がってる EnemyZakoModel(表示モデルを担当)の位置をずらしている。
  • 時間経過を、Timerノードを使わずにスクリプト内の処理で測っている。

これで、プレイヤーや敵がダメージを受けた時に、少しは見た目で分かりやすくなった…かどうかは怪しいけれど、とりあえず簡易の処理は追加できた。

次回はタイトル画面やゲームオーバー画面を作成してみる。

#2 [godot] Godot Engineでタイトル画面その他を作成

Godot Engine 3.2.3 x64 を使って3D表示の簡単なシューティングゲームっぽいものを作る。

今回は、タイトル画面、ゲームオーバー画面、ステージクリア(You Win)画面を作成してみる。

タイトル画面を作成。 :

タイトル画面のシーンを作成。シーン → 新規シーン。

以下のようなノード構成を作成。

3d_tuto13_create_title_ss01.png


ルートノードを Title にリネーム。

3d_tuto13_create_title_ss02.png

Title (Node2D)
  │
  └─ CanvasLayer
         │
         ├─ ColorRect
         │
         ├─ Label
         │
         └─ Button


res:// 直下に Title.tscn として保存。

3d_tuto13_create_title_ss03.png

各ノードをレイアウト。 :

以下のような見た目になるように、各ノードのプロパティを設定した。

3d_tuto13_create_title_ss04.png

  • ColorRect で指定色の矩形を描画できる。青色にして、画面一杯に表示される size にした。
  • Label で文字を描画できる。ゲームのタイトル「Simple Shoot'Em Up」を表示させた。使ったフォントは Vegur-Bold.otf。
  • Button でマウスクリックに反応するボタンを置ける。「START」と表示させて下のほうに配置した。

スクリプトを書く。 :

Title にスクリプトをアタッチして、res://scripts/Title.gd として保存。

ボタン(Button)を押した時に発行される pressed() シグナルにメソッドを接続する。
  1. Button を選択
  2. ノードタブをクリック → シグナルをクリック
  3. pressed() を右クリックして「接続」
  4. Title を選択して「接続」

3d_tuto13_create_title_ss05.png


Title.gd の最後に、_on_Button_pressed() というメソッドが追記された。ボタンをマウスでクリックすると、このメソッドが呼ばれる状態になった。

3d_tuto13_create_title_ss06.png


スクリプトファイル Title.gd を修正する。内容は以下。

_Title.gd
extends Node2D

func _ready():
    pass # Replace with function body.

#func _process(delta):
#   pass

func _on_Button_pressed():
    get_tree().change_scene("res://Main.tscn")

  • get_tree().change_scene("res://Main.tscn") で、res://Main.tscn にシーンを切り替える、という指定をしている。

これで、ボタンをマウスクリックすると Main.tscn にシーンが切り替わる状態になった。

ボタンにショートカットキーを割り当て。 :

この状態では画面上のボタンをマウスでクリックしないと反応しないけど、できればキーボードを叩いた時も反応してほしい。Buttonノードにはショートカットキーを割り当てることもできるので、その設定をする。

Button を選択して、Shortcutプロパティを設定。
  1. Shortcut の横の「空」をクリックして「新規 Shortcut」を選択。
  2. 作成された「Shortcut」をクリックするとその下にもShortcutの欄が出てくる。
  3. 横の「空」をクリックして「新規 InputEventAction」を選択。
  4. 作成された「InputEventAction」をクリックするとその下に Action 等が出てくる。
  5. Action に「ui_accept」と入力。

3d_tuto13_create_title_ss07.png

  • ui_accept には、デフォルトでスペースキーやEnterキーが割り当てられている。プロジェクト設定で変更できる。

これで、スペースキーやEnterキーを叩いてもボタンが反応するようになった。

メインシーンとして設定する。 :

ゲームを開始したら、Mainシーンではなく、この Titleシーンが真っ先に表示されてほしい。Title.tscn をメインシーンとして設定する。

ファイル一覧ウインドウで Title.tscn を右クリックして「メインシーンとして設定」を選択。

3d_tuto13_create_title_ss08.png

これで、このプロジェクトのメインシーンは Title.tscn になった。今後はF5キーを押すとメインシーン(Title.tscn) から実行される。

ゲームオーバー画面やステージクリア画面を作成。 :

Titleシーンを作った時と同じ手順で、ゲームオーバー画面とステージクリア画面のシーンを作成する。

それぞれ、ルートノードを、「GameOver」「YouWin」にリネームしておく。

3d_tuto13_create_title_ss09.png

3d_tuto13_create_title_ss10.png


ゲームオーバー画面にスクリプトをアタッチする。このスクリプトはステージクリア画面でも共用したいので、スクリプトファイル名は「GoToTitle.gd」にして保存する。

3d_tuto13_create_title_ss11.png


ステージクリア画面にも、ゲームオーバー画面と同じく GoToTitle.gd をアタッチ。Script → 「読込み」で GoToTitle.gd を選択してやる。もし操作を間違った時は、「クリア」を選べば「空」に戻る。

3d_tuto13_create_title_ss12.png


スクリプト GoToTitle.gd を修正。内容は以下。

_GoToTitle.gd
extends Node2D

func _ready():
    pass # Replace with function body.

func _on_Button_pressed():
    get_tree().change_scene("res://Title.tscn")

  • get_tree().change_scene("res://Title.tscn") を呼ぶことで、res://Title.tscn にシーンを切り替える。

ゲームオーバー画面、ステージクリア画面の双方で、Button をマウスクリックした時に発行される pressed()シグナルにメソッドを接続してやる。
  1. GameOver、または YouWin を選択
  2. ノードタブをクリック → シグナルをクリック
  3. pressed() を右クリックして「接続」
  4. スクリプト GoToTitle.gd をアタッチしているノード(GameOver、YouWin)を選択
  5. メソッド名には _on_Button_pressed を入力して「接続」

また、Button の Shortcut プロパティも設定して、キーボードを叩いてもボタンが反応するようにしておく。

ゲームオーバー画面にシーンを切り替える処理を追加。 :

Mainシーンのスクリプト Main.gd を修正。追加内容は以下。

_Main.gd
# ...

func die_player():
    get_tree().change_scene("res://GameOver.tscn")
    
func die_enemy():
    get_tree().change_scene("res://YouWin.tscn")

  • ゲームオーバー画面にシーンを切り替えるメソッド、die_player() を追加。
  • ステージクリア画面にシーンを切り替えるメソッド、die_enemy() を追加。

Player を選択して、プレイヤーが死んだ時に発行されるカスタムシグナル player_died() にメソッドを接続してやる。
  1. ノードタブをクリック → シグナルをクリック
  2. player_died() を右クリックして「接続」

3d_tuto13_create_title_ss13.png


Main を選択して、メソッド名に die_player を入力して「接続」。

3d_tuto13_create_title_ss14.png

これで、プレイヤーが死ぬと、Main.gd 内の die_player() が呼ばれて、ゲームオーバー画面に切り替わる状態になった。


同様に、敵にも設定をする。EnemyZako を選択して、敵が死んだ時に発行されるカスタムシグナル enemy_died() にメソッドを接続。

3d_tuto13_create_title_ss15.png


Main を選択して、メソッド名に die_enemy() を入力して「接続」。

3d_tuto13_create_title_ss16.png

これで、敵が死ぬと、Main.gd 内の die_enemy() が呼ばれて、ステージクリア画面に切り替わる状態になった。

動作確認。 :

F5キーを押して実行してみる。

3d_tuto13_create_title_ss17.png

プロジェクトのメインシーンとして Title.tscn を設定済みなので、F5キーを押せば最初にタイトル画面が表示されるはず。




タイトル画面 → ゲーム画面 → ゲームオーバー or ステージクリア → タイトル画面、とシーンが切り替わっていくようになった。

次回は…。今現在はプレイヤーが画面端を超えても平気で移動できてしまうので、そのあたりをどうにかしてみたい。

#3 [godot] Godot Engineでプレイヤーが画面端を超えないように補正

Godot Engine 3.2.3 x64 を使って3D表示の簡単なシューティングゲームっぽいものを作る。

今回は、プレイヤーキャラが画面端を超えて移動しないように補正する処理を追加してみる。

Player のスクリプトファイル、res://scripts/Player.gd を修正。追記した内容は以下。

_Player.gd
# ...

export var padding = 1.7
var camera:Camera
var disparea = Vector2()
var btopleft = Vector3()
var bbottomright = Vector3()

func _ready():
    # ...

    init_adjust_work()

# ...

func _physics_process(delta):
    # ...
    
    adjust_pos(padding)

    # ...

# ...

func init_adjust_work():
    disparea = get_disp_area()
    camera = get_tree().root.get_node("Main/Camera")
    calc_move_area(camera, disparea.x, disparea.y)

# get project display width and height
func get_disp_area():
    var w = ProjectSettings.get_setting("display/window/size/width")
    var h = ProjectSettings.get_setting("display/window/size/height")
    return Vector2(w, h)
    
func adjust_pos(padding):
    if translation.z < btopleft.z + padding:
        translation.z = btopleft.z + padding
    if translation.z > bbottomright.z - padding:
        translation.z = bbottomright.z - padding
        
    var zd = btopleft.z - bbottomright.z
    var lz = translation.z - bbottomright.z
    var x = lz * (-btopleft.x - bbottomright.x) / zd + bbottomright.x
    
    if translation.x > x - padding:
        translation.x = x - padding
    if translation.x < -x + padding:
        translation.x = -x + padding

func calc_move_area(camera:Camera, w, h):
    var cpos:Vector3 = camera.translation
    var crot:Vector3 = camera.rotation_degrees
    var fov = camera.fov
    var d = (h/2) / tan(deg2rad(fov/2))
    var p1 = Vector3(-w/2, h/2, -d)
    var p2 = Vector3(w/2, -h/2, -d)
    var q1:Vector3 = _get_border(p1, -crot.x, -cpos.y, cpos.z)
    var q2:Vector3 = _get_border(p2, -crot.x, -cpos.y, cpos.z)
    btopleft = q1
    bbottomright = q2
    
    if false:
        print("topleft = (%f, %f, %f)" % [q1.x, q1.y, q1.z])
        print("bottomright = (%f, %f, %f)" % [q2.x, q2.y, q2.z])

func _get_border(p:Vector3, rotx, y, cz):
    var v2:Vector2 = _get_rot_pos(p.z, p.y, rotx)
    var pr = Vector3(p.x, v2.y, v2.x)
    var x = y * pr.x / pr.y
    var z = y * pr.z / pr.y + cz
    return Vector3(x, 0, z)

func _get_rot_pos(x, y, ang):
    var a = deg2rad(ang)
    var xr = x * cos(a) - y * sin(a)
    var yr = x * sin(a) + y * cos(a)
    return Vector2(xr, yr)

何をやっているのかというと…。
カメラから見えている範囲のx,z座標を求めるあたりで、なんだか計算が面倒臭いことになっている。

ただ、Godot Engine のことだから、もっと簡単に値を求める機能が既に用意されてそうな気もする。ググってもそのものズバリの情報が出てこなくて、こんな処理を書いてしまったけれど…。もっと良い方法・便利なメソッドがあったら誰か教えてください。みたいな。

おそらく結構ダサいことをしている気もするけれど、何にせよ、これでプレイヤーが画面外に出ない状態になった。

次回は、3DCGソフトの blender で作成した飛行機モデルデータ、敵モデルデータをインポートして、ゲーム画面の見栄えを改善したい。

関連ページ。 :

余談。 :

Godot Engine には、3D空間内の座標が、カメラから見えている範囲の中にあるか、外にあるかを調べるメソッドが用意されているので、それを使って範囲外なら補正する処理を試したこともあったのだけど。

_mieki256's diary - 自機が画面外に行かないようにしたい

そのやり方だと、画面の端でプレイヤーを斜め移動させた時にガタガタした移動になっちゃって、このやり方ではダメだなと諦めた記憶が…。まあ、見た目は酷いけれど、画面外に出さない処理をそういうやり方でやれないこともない…と、一応メモしておきます。

他にも、画面の端に壁相当のオブジェクトを配置しておいて、その壁オブジェクトとプレイヤーでアタリ判定・衝突判定をして、画面外に出ないようにしてしまう、という方法もありそう。ただ、カメラの各プロパティをちょっと修正するたびに、壁オブジェクトの配置についても修正する手間が増えるであろう予感も…。

2020/11/18(水) [n年前の日記]

#1 [godot] Godot Engineで3Dモデルデータをインポート

Godot Engine 3.2.3 x64 を使って3D表示の簡単なシューティングゲームっぽいものを作る。

今回は、3DCGソフト blender 2.83.9 x64 LTS で作成した飛行機(自機)や敵のモデルデータをインポートしたい。

自機のモデルデータをblenderからエクスポート。 :

blender で飛行機っぽいモデルデータを作ってみた。CC0 / Public Domain ってことで。中には blender用のファイル airplane_type_b.blend やテクスチャ画像が入っている。

_airplane_type_b_20201108.zip

Godot Engine はいくつかの3Dモデルデータフォーマットに対応しているけれど、アニメーションを含まない形状データだけなら glTF 2.0 でやり取りするのが良さそうな気がする。glTF 2.0 なら、他のフォーマットと違ってテクスチャもそのまま反映されるので。

blenderから glTF 2.0形式でエクスポートする。ファイル → エクスポート → glTF 2.0 (.glb/.gltf)を選択。

3d_tuto15_import_3dmodel_ss01.jpg


フォーマットは「glTFバイナリ (.glb)」にした。その他の設定はスクリーンショットを参考に。airplane_type_b.glb としてエクスポート。

3d_tuto15_import_3dmodel_ss02.png

Godot Engineにインポート。 :

blenderからエクスポートした .glb を、Godot Engine のエディタ画面にドラッグアンドドロップしてインポートする。

3d_tuto15_import_3dmodel_ss03.jpg


res://imports/ の下に移動した。

3d_tuto15_import_3dmodel_ss04.png

Godot Engine で開く。 :

インポートした .glb を右クリックして「シーンを開く」を選択。

3d_tuto15_import_3dmodel_ss05.png


確認ウインドウが開く。とりあえず「新規の継承」を選択。

3d_tuto15_import_3dmodel_ss06.png


Godot Engine のエディタ画面内にモデルデータが表示された。

3d_tuto15_import_3dmodel_ss07.jpg


Godot Engine のシーンとして保存しておく。res://assets/ の下に、airplane_type_b.tscn として保存した。

3d_tuto15_import_3dmodel_ss08.png

プレイヤーのモデルデータを差し替える。 :

今まで仮で表示していたプレイヤーキャラのモデルデータを差し替える。

プレイヤーのシーン、Player.tscn を開いて、新規インスタンスを読み込むボタンをクリック。airplane_type_b.tscn を開く。

3d_tuto15_import_3dmodel_ss09.png


Player の下に airplane_type_b ノードとして追加された。

3d_tuto15_import_3dmodel_ss10.jpg


PlayerModel の下にドラッグして移動して、向きや大きさを変更する。

3d_tuto15_import_3dmodel_ss11.jpg


今まで表示していた仮モデルは、目のアイコンをクリックして非表示にする。仮モデルを今後一切使わない予定なら、右クリックして「削除」してしまってもいい。

3d_tuto15_import_3dmodel_ss12.jpg


アタリ範囲を修正。CollisionShape を選択して大きさや位置を修正する。

3d_tuto15_import_3dmodel_ss13.png


シーンを保存して動作確認。Mainシーンを開いてF6キーを押す。

3d_tuto15_import_3dmodel_ss14.png

これで、プレイヤーキャラのモデルデータを、今回インポートしたモデルデータで差し替えることができた。

敵のモデルデータをblenderからエクスポート。 :

敵のモデルデータをエクスポートする。これも blender で作成した。CC0 / Public Domain ってことで。

_enemy_type_b_20201108.zip

解凍すると、blender用のファイル、enemy_type_b_fix.blend が入っている。このモデルデータは、両手がくるくると回るアニメーションデータを含んでいる。

現時点では、こういった複数のアニメーションを持っているデータに関しては、ESCN (.escn) 形式で ―― Godot Engine にとってネイティブ(?)な形式でエクスポートしておくと、比較的真っ当にアニメーションのデータをエクスポート・インポートできるらしい。

blender から ESCN形式でエクスポートするためにはアドオンのインストールと有効化が必要になる。該当アドオンはgithub上で公開されてる。

_godotengine/godot-blender-exporter: Addon for Blender to directly export to a Godot Scene

  • 上記ページ内の、「Code」と書かれた緑色のボタンをクリック → 「Download ZIP」を選択。godot-blender-exporter-master.zip がダウンロードできる。
  • 解凍して、io_scene_godot というフォルダを blender のユーザ設定フォルダにコピーすればインストールできる。

blenderのユーザ設定フォルダは、Windows環境ならおそらく以下にあるはず。
C:\Users\<ユーザアカウント名>\AppData\Roaming\Blender Foundation\Blender\2.83\scripts\addons\

io_scene_godotフォルダをコピーしたらアドオンを有効化する。
  • blender を起動して、編集 → プリファレンス → アドオン。
  • 検索欄に「godot」と打ち込めば「Import-Export: Godot Engine Exporter」がリストアップされる。
  • チェックを入れて有効化。
これで、このアドオンが使えるようになった。

敵のモデルデータを blender からエクスポートする。ファイル → エクスポート → Godot Engine (.escn) を選択。

3d_tuto15_import_3dmodel_ss15.jpg


保存先フォルダは、Godot Engine のプロジェクトフォルダ\imports\ を指定しておく。その他の設定はスクリーンショットを参考に。enemy_type_b_fix.escn というファイル名で保存した。

3d_tuto15_import_3dmodel_ss16.jpg

Godot Engineで敵のモデルデータを開く。 :

Godot Engine で敵のモデルデータを開く。enemy_type_b_fix.escn をダブルクリック。

3d_tuto15_import_3dmodel_ss17.png


Godot Engine のエディタ画面内に、敵のモデルデータが表示された。

3d_tuto15_import_3dmodel_ss18.png


Godot Engine のシーンファイルとして保存しておく。res://assets/ の下に enemy_type_b_fix.tscn として保存した。

3d_tuto15_import_3dmodel_ss19.png

アニメーション設定を修正。 :

この敵のモデルデータはアニメーションデータを持っているけど、発生と同時にアニメーションを再生したり、アニメーションをループさせたりしたい。そのために少しだけ設定をし直す。

設定を変更するために、継承をクリアしておく。enemy_type_b_fix を右クリックして「継承をクリア」。

3d_tuto15_import_3dmodel_ss20.png


アニメーションを管理しているノード、AnimationPlayer を選択して、自動再生とループ再生のアイコンをクリックして有効にしておく。

3d_tuto15_import_3dmodel_ss21.png


この状態で、enemy_type_b_fix.tscn を一旦保存。

敵のモデルデータを差し替える。 :

敵のモデルデータを差し替える。res://assets/EnemyZako.tscn を開く。インスタンス追加アイコンをクリック。enemy_type_b_fix.tscn を開く。

3d_tuto15_import_3dmodel_ss22.png


enemy_type_b_fix.tscn が表示された。

3d_tuto15_import_3dmodel_ss23.png


  • enemy_type_b_fix の位置、大きさ、向きを調整。
  • enemy_type_b_fixノードを EnemyZakoModel の下に配置。
  • 今まで表示していた仮モデルは非表示にする。
  • CollisionShape を選択してアタリ範囲を修正。

3d_tuto15_import_3dmodel_ss24.png


Mainシーンを開いて、F6キーを押して動作確認。

3d_tuto15_import_3dmodel_ss25.png

これで、敵のモデルデータも差し替えることができた。

位置や大きさについては、なんとなくイイ感じの見た目になるように、その都度修正のこと。

次回は、背景についてもモデルデータを差し替えたい。

#2 [godot] Godot Engineで背景の3Dモデルデータをインポート

Godot Engine 3.2.3 x64 を使って3D表示の簡単なシューティングゲームっぽいものを作る。

今回は、背景についてもモデルデータを差し替えてみる。

モデルデータをエクスポート。 :

blender で背景モデルを作成して glTF 2.0 でエクスポート。モデルデータは以下。CC0 / Public Domain ってことで。

_bg_type_c_20201109.zip (スクリーンショット内で使ってた版)
_bg_type_c_take3_20201111.zip (再作成版。大きさや構成を変更してある)

アニメーションを含んでないモデルデータなので、glTF 2.0 でエクスポートすれば問題は起きにくいはず。

Godot Engine にインポートして開いてみる。表示された。bg_type_c.tscn というファイル名でシーンとして保存。

3d_tuto16_import_bgmodel_ss01.jpg

Bgシーンに読み込んでみる。 :

Bgシーン、res://assets/Bg.tscn を開いて、インスタンスを追加。bg_type_c.tscn を開く。今まで使っていた仮モデルは非表示にするか削除する。

BgModel の下に配置して、右クリック → 複製で数を増やして、比較的広大な(?)シーンにした。

3d_tuto16_import_bgmodel_ss02.jpg


Mainシーンを開いてみる。反映されている。

3d_tuto16_import_bgmodel_ss03.jpg

Bgシーンの動かし方を変えてみる。 :

Bgシーンは BgModel を動かすことで背景がスクロール(?)しているように見せかけているけれど、z軸方向に動いてるだけで面白みがないような気がしてきた。x軸方向にもずらしたり、z軸で回転させたりして、動きに色気(?)をつけてみる。

res://scripts/Bg.gd を修正。内容は以下。

_Bg.gd
extends Spatial

export var scroll_speed = 120
export var limit_z = 80
export var add_z = -80

export var angle_add = 20
export var x_shift_range = 80
export var rotz_range = 10
var angle = 0

func _ready():
    pass # Replace with function body.

func _process(delta):
    angle += (angle_add * delta)
    if angle > 360.0:
        angle -= 360.0
        
    var rz = rotz_range * sin(deg2rad(sin(deg2rad(-angle))))
    $BgModel.rotation.z = rz
    $BgModel.translation.x = x_shift_range * sin(deg2rad(angle))
    
    $BgModel.translation.z += scroll_speed * delta
    if $BgModel.translation.z >= limit_z:
        $BgModel.translation.z += add_z

敵が弾を撃つ処理も修正。 :

ついでに、敵が弾を撃つ際の処理も若干修正。res://scripts/EnemyZako.gd を修正。

_EnemyZako.gd
# ...
            
func _on_ShotTimer_timeout():
    var angle_add = 12
    var angle = 90 - angle_add * 3
    var spd = 0.2
    for i in range(7):
        _shot(translation, angle, spd)
        if hp <= hpmax * 0.7:
            _shot(translation, angle, spd * 0.8)
        if hp <= hpmax * 0.3:
            _shot(translation, angle, spd * 1.2)
            _shot(translation, angle, spd * 1.1)
            _shot(translation, angle, spd * 0.9)
        angle += angle_add
    
# ...

  • 敵のHPに応じて、発射する弾の数を変えている。

動作確認。 :

Mainシーンを開いてF6キーを押して動作確認。



それらしい画面になってきた。

次回はサウンドを追加してみる。

#3 [godot] Godot Engineでサウンドを追加

Godot Engine 3.2.3 x64 を使って3D表示の簡単なシューティングゲームっぽいものを作る。

今回はサウンドを追加してみる。

利用するサウンドファイルは以下。自作しました。CC0 / Public Domain ってことで。

_simpleshootemup_sounds.zip

解凍すると以下のファイルが入っている。

プロジェクトフォルダにインポート。 :

.wav や .ogg をGodot Engineのプロジェクトフォルダ\imports\ にコピー。自動でインポートされる。

3d_tuto17_add_sounds_ss01.png


インポート設定を確認。bgm.ogg を選択して、インポートタブをクリック。BGMはループ再生してほしいので、Loop にチェックが入ってることを確認する。もしチェックが入ってなかったらチェックを入れて「再インポート」をクリック。

3d_tuto17_add_sounds_ss02.png


SEとして使う各wavについても確認。1回鳴らしたら再生終了してほしいので、Loopにチェックが入ってないことを確認する。

3d_tuto17_add_sounds_ss03.png

BGMを追加。 :

BGMを追加する。Mainシーンを開いて、AudioStreamPlayerノードを追加する。

3d_tuto17_add_sounds_ss04.png


Bgm にリネーム。

3d_tuto17_add_sounds_ss05.png


Bgm を選択して、Stream に bgm.ogg を設定する。
  • ファイル一覧ウインドウから bgm.ogg をドラッグアンドドロップ。
  • あるいは、Stream の横の「空」をクリックして「読込み」→ bgm.ogg を選択。

3d_tuto17_add_sounds_ss06.png


スクリプトに、BGM再生開始を記述。res://scripts/Main.gd を開いて、初期化処理 _ready() の中に、$Bgm.play() を追記する。

3d_tuto17_add_sounds_ss07.png


ついでに一応、ゲームオーバー (die_player()) とステージクリア (die_enemy()) の中で、$Bgm.stop() を呼んでBGMを停止しておく。すぐにシーンが切り替わってBGMが消えるのでこの処理はしなくてもいいのかもしれないけれど、一応念のため。

3d_tuto17_add_sounds_ss08.png

プレイヤーのダメージSEを追加。 :

プレイヤーがダメージを受けた時にダメージSEを鳴らしたい。

プレイヤーのシーン、res://assets/Player.tscn を開いて、AudioStreamPlayerノードを追加。DamageSe にリネーム。

3d_tuto17_add_sounds_ss09.png


DamageSe を選択して、Stream に player_damage_se.wav を指定。

3d_tuto17_add_sounds_ss10.png


スクリプト、Player.gd を修正。SEの再生開始を指定する。ダメージ処理の開始部分に ―― emit_siginal("player_damaged") を呼んでる行の前後のあたりに、$DamageSe.play() を追記する。

3d_tuto17_add_sounds_ss11.png

これで、プレイヤーがダメージを受けたタイミングでダメージSEが鳴るようになった。

敵のSEを追加。 :

敵にもSEを追加していく。ダメージを受けた時にダメージSEを鳴らして、弾を撃った時に発射SEを鳴らしたい。

EnemyZako.tscn を開いて、AudioStreamPlayerノードを2つ追加。DamageSe と ShotSe にリネーム。

3d_tuto17_add_sounds_ss12.png


Streamプロパティに wav ファイルを指定。
  • DamageSe の Stream に enemy_damage_se.wav を指定。
  • ShotSe の Stream に enemy_shot_se.wav を指定。

スクリプト内で各SEの再生を指定する。EnemyZako.gd を編集。

ダメージを受けるタイミングで ―― emit_siginal("enemy_damaged")を呼んでる行の前後で、$DamageSe.play() を呼ぶ。

3d_tuto17_add_sounds_ss14.png


弾を撃つタイミングで ―― _on_ShotTimer_timeout() の中で、$ShotSe.play() を呼ぶ。

3d_tuto17_add_sounds_ss13.png


これで、敵がダメージを受けた時と弾を撃った時にSEが鳴るようになった。

動作確認。 :

動作確認をしてみる。Mainシーンを開いてF6キーを押す。



ちゃんと音が鳴ってくれた。

次回はプロジェクトをエクスポートして、Windows上で動くexeファイルや、Webブラウザ上で動くHTML5版を出力してみる。

#4 [windows] 「今すぐ会議を開始する」って何だろう

Windows10 x64 2004 を使っていたら、タスクトレイに「今すぐ会議を開始する」というアイコンが表示されていることに気付いた。なんじゃこりゃ。

ググってみたら、Skype がそういう表示を出しているという話を見かけた。なるほど。鬱陶しいな…。Skype をアンインストールすれば消えるのだろうか。でも自分の環境には Skype がインストールされてないっぽいのだけど…。

右クリックして「非表示」を選べば表示を無効化できるらしい。

_今すぐ会議を開始するを非表示にする方法 | とは

とりあえず非表示にしておいた。でも Microsoft のことだから、どうせまた何かの拍子にこのアイコンが出てくる状態に戻ったりするのだろうなあ…。実に鬱陶しい…。

2020/11/19(木) [n年前の日記]

#1 [godot] Godot Engineでプロジェクトをエクスポート

Godot Engine 3.2.3 x64 を使って3D表示の簡単なシューティングゲームっぽいものを作る。

今回はプロジェクトをエクスポートして、Windows上で動くexeファイルや、Webブラウザ上で動くHTML5版を出力してみる。

手順は、以前2Dゲームモドキを作成した際にメモした内容とほぼ同じ。

_mieki256's diary - Godot Engineでプロジェクトをエクスポート

プロジェクト → エクスポート。

3d_tuto18_export_project_ss01.png


エクスポートするプリセットを「追加」して、「プロジェクトのエクスポート」をクリック。

3d_tuto18_export_project_ss02.png


Windows Desktop版はexeファイルを実行すればすんなり動くはずだけど、HTML5版は動作確認が少し面倒臭い。

以前もメモしたけれど、昨今の Webブラウザはローカルファイルにいきなりアクセスできないようになってるそうで…。Python を使ってローカルWebサーバを起動して動作確認する。そのあたりは以前メモしたので参考にしてください。

_HTML5の動作確認 - Godot Engineでプロジェクトをエクスポート

Windows Desktop版の完成品。 :

Windows Desktop でエクスポートしてみた。

_simpleshootemup_windowsdesktop_20201119.zip (25.5MB)

解凍すると、中に simpleshootemup.exe と simpleshootemup.pck が入ってる。simpleshootemup.exe を実行すればプレイできる。

自分の環境は以下。
  • CPU : AMD Ryzen 7 1700
  • GPU (videocard) : NVIDIA GeForce GTX 1060 6GB
  • RAM (Memory) : 16GB
  • OS : Windows10 x64 2004
このスペック上では比較的滑らかに動いてるように見える。FPSは測定してないけど…。

HTML5版の完成品。 :

HTML5でエクスポートしてみた。以下のページを開けばWebブラウザ上で実行できるはず。たぶん。

_simpleshootemup.html

Windows10 x4 2004 + 各ブラウザで動作確認してみたが、若干悩ましい結果になった。
  • Mozila Firefox 82.0.3 ... ガクガク状態。見るからに酷い。それでもまあ、一応は動いてくれた。
  • Google Chrome 87.0.4280.66 ... 比較的滑らかに動く。ヌルヌル。
  • Microsoft Edge 86.0.622.69 ... Google Chrome ほど滑らかではなく時々ガクッとするけれど Firefox ほどガクガクではない。
  • Vivaldi 3.4.2066.106 ... Microsoft Edge と似たような感じ。

普段常用している Firefox でガクガク状態だったのでこれはヤバイと頭を抱えたけれど、Google Chrome ならヌルヌルだったので少しホッとした。この手のソレを動かすときは Google Chrome を使うべきということなのかな…。それとも、自分の環境の Firefox はアドオンをたくさん入れてるから、その分動作速度が遅くなっているのだろうか…?

とりあえずこれで完成。 :

ひとまずこれで完成。正直なところ、これでゲームになってるかと言えば全然なってないのだけど、Godot Engine を使えばこういう見た目のゲームも作っていけそうですよと一応紹介できる程度のソレにはなったかなと…。

#2 [pc] Firefox 83.0がLAN内のPCにアクセスできない仕様になってた

Windows10 x64 2004 上で Firefox が 83.0 に更新されていたのだけど、自分にとっては致命的な問題が発生。

ブックマークに入っている http://hoge/ (hoge は LAN内の任意のホスト名) を開こうとしたら、https://www.hoge.com/ というURLに勝手に書き換えられてしまって「そんなURLは存在しねえんだよこのクソボケ。404じゃ」と言ってくる…。ちょ、おま…勝手にそんなことすんなや…。

しかも、アドレスバー(urlbar, Location bar)に直接 http://hoge/ を打ち込んでも、Enterキーを押したら https://www.hoge.com/ に書き換えられて404。おい…てめえ…いいかげんにしろよ…。「意地でも書き換えてやるぜ!」ってか…。

まさかOSがおかしいのではと気になって、Google Chrome 87.0.4280.66 を起動してみたけれど、Google Chrome なら http://hoge/ にアクセスできた。Microsoft Edge 86.0.622.69 もアクセスできたし、Vivaldi 3.4.2066.106 もアクセスできた。Firefox 83.0 だけがおかしい。

たぶんコレ、Firefox 83.0 から導入されたという HTTPS-Onlyモードのせいだろうなあ…。そのあたりの仕様を入れる際に、こういう仕様バグも混入させてしまったのだろう…。

しかし困った。ずっとこのままの仕様で行くつもりなんだろうか。これではLAN内のPCにホスト名でアクセスできないわけで。一々IPアドレスを調べて打ち込めとでも言うのか。LAN内の何かしらをWebブラウザで動作確認したい時に、Firefoxだけが使えない・そもそもページにアクセスできない状態になってしまうではないか…。

やはり Google Chrome に乗り換えていくしかないのかな…。ますます Google に支配されてしまう…。

ドメイン補完をしない設定にしてみた。 :

ググった感じでは、前述のURL書き換えはドメイン補完と呼ぶらしい。設定で無効にできるらしいので試してみたり。

_Firefoxのロケーションバー(URL欄)の自動補完・検索機能を完全に無効化する : Web Memo. SE

about:config を開いて browser.fixup.alternate.enabled を false に。

たしかに、www だの com だのを勝手につけてこない状態になってくれた。

しかし、相変わらずLAN内のPCにアクセスできない。IPアドレスを打つと開けるのだけど。他のブラウザならホスト名で開けるのだけどなあ…。

Firefox 82.0.3に戻した。 :

このままでは使い物にならないので、仕方ないからちとバージョンを以前に戻すことにした。Firefox 82.0.3 のセットアップファイルをDLしてインストール。

しかし、起動させようとすると「ダウングレードしたからプロファイルが使えないかもしれない。新しいプロファイルを作れ」と言ってきて、新規プロファイルを作成しないと先に進めない…。泣く泣く新規作成。

ブックマークとパスワードは Firefox Sync にログインして同期をさせたら復活したけれど、常用していたアドオンをメモするのを忘れていた…。アドオンが全部消えてしまった…。アドオンまで Firefox Sync で同期させると Linux機で Firefox を使おうとしたときにハマるから除外してたんだよな…。

about:profiles を開いて、プロファイルが入ってるフォルダの場所を確認。旧プロファイルのフォルダの中から、extensions フォルダを新しいプロファイルフォルダの中にコピー。Firefox を再起動したらアドオンがインストールされた状態にはなった。ただ、全部無効化されてるし、設定も全部消えていた。設定し直し。泣きそう。

それはともかく、Firefox 82.0.3 なら http://ホスト名/ でも開けた。まあ、今までも開けてたから予想通りだけど。やはり Firefox 83.0 だけがおかしい。

2020/11/20(金) [n年前の日記]

#1 [firefox] Firefoxの設定をし直しているところ

Firefox 83.0 にしたらLAN内のPCにアクセスできなくなって 82.0.3 に戻したのだけど、新規プロファイルの作成を強制されて設定が全部消えてしまったので設定し直しているところ。

以下のページを参考に色々指定。

_Firefoxのロケーションバー(URL欄)の自動補完・検索機能を完全に無効化する : Web Memo. SE
_Firefox のロケーション バーと検索バーを新しいタブで開かせる - Compnet
_Firefox 69 以降でも userChrome.css を使う方法
_Firefox userChrome.cssのコードまとめ - バグ取りの日々
_How to Hide Firefox’s New “Saved to Library” Confirmation Popup | Stephan Sokolow's Blog
_Firefoxチューニング - ドメイン補完機能などをチューニングする | マイナビニュース
_うしくんの日々 - Firefoxのドメイン補完機能は余計なお世話
_single word hostname | Firefox サポートフォーラム | Mozilla サポート

「ライブラリーに保存しました」を非表示したい。 :

ブックマークを追加しようとすると「ライブラリーに保存しました」と一々メッセージが表示される。これが地味に鬱陶しい。ブックマークしたらURLバー上で青い星が表示されるのだからソレを見れば事足りるわけで。故に件のメッセージ表示を非表示にしたいのだけど、ググった感じでは userChrome.css を設定することで消せるらしいので試したり。

昨今の Firefox は userChrome.css が無効になっているらしいので、まずは有効化。その後、userChrome.css を新規作成して追記する。

  • userChrome.css の有効化 : toolkit.legacyUserProfileCustomizations.stylesheets を true に。
  • userChrome.css の新規作成。about:profiles を開いてプロファイルフォルダを開き、ルートフォルダ内に chrome フォルダを新規作成して、その中に userChrome.css を新規作成。

ブックマーク登録時に「ライブラリーに保存しました」とメッセージが出るのを抑制する。userChrome.css に以下を記述。
/* Hide "Saved to Library!" bookmark confirmation popup */
#confirmation-hint { display: none !important; }

2020/11/21() [n年前の日記]

#1 [windows] デスクトップ上で使える定規ソフトを試用

画像の上で距離を測るためのソフトが欲しいなと。定規ソフトとでもいうか…。Windows10上で動きそうなソフトについて、ググっていくつか試用してみたり。

Medirを試用。 :

_Medirの詳細情報 : Vector ソフトを探す!

たしか以前は Medir を使っていた気がする…。今回は、1.2build5 をインストール。

L型の定規っぽいものがデスクトップ上に表示されるので、大体の長さを測ることができる。半透明表示もできるし、左上のターゲットっぽいアイコンをドラッグすれば斜めの距離を測ることもできる。

ただ、フォントが小さくて、老眼がどんどん進行中の自分にはちょっと厳しい。数値が読めない…。

HiRulerを試用。 :

_HiRulerの詳細情報 : Vector ソフトを探す!

HiRuler も以前使っていた気がする。今回は 1.35 をインストール。

縦横に目盛りがついた半透明の矩形が表示されるので、ウインドウサイズ等を測る時には都合が良かった記憶が。ただ、それ以外では機能が少ないのであまり使う場面がなかった記憶もあるような…。

L型ものさしを試用。 :

_L 型ものさし - k本的に無料ソフト・フリーソフト

L型ものさしは、初めて試用。1.1.0 をインストールした。

名前の通りL型の定規が表示される。半透明にもできるし、任意の角度で回転もできる。フォント種類やフォントサイズもカスタイマイズできるので、老眼の自分でも読めるフォントサイズにすることができた。

測ルンですを試用。 :

_「測ルンです」指定した2点間距離をピクセル単位などで計測 - 窓の杜

測ルンですも初めて試用。0.7.1 をインストール。

これは他の定規ソフトとは違って、常時デスクトップ上に定規らしき何かを表示するタイプではないっぽい。デスクトップ上で始点と終点をクリックすることで、間の距離を測定できる。連続でクリックして複数の直線の合計を測るモードも用意されているので、曲がりくねった道っぽいものの長さを測る時には便利そうだなと。

ただ、フォントが小さくて読みづらい…。ポップアップで距離が表示されるけど、読めない…。

フォントサイズって大事だなと。 :

フォントサイズを変更できる機能があるかどうかって大事だなと。若い頃(?)は気にも留めなかったけど、老眼になるとフォントが読めなくなるわけで…。

#2 [zatta] 頭身について少し調べてた

某ゲームのキャラメイク画面を操作しているうちになんだかちょっと頭身だの足の長さだのが気になってきて。某ゲームの各キャラはどうも足が長すぎる気がするというか…。しかし実際の人間はどのくらいの足の長さなのか自分は知らなくて、これはちょっと調べてみないといかんなと。

ググったところ、股下/身長、で得られる値で足の長さを判断することが多いらしい。身長を100%とした場合、足の長さは何%なのか、ということだろうなと。日本人の場合、平均値は 0.45〜0.46ぐらいになるそうで。世代というか産まれた年代によって差が出てくるらしいけど。それと、白人の場合はもうちょっと足が長くなるっぽい。

某ゲームのキャラを測ってみたら、0.50ぐらいあった。やっぱり足が長い状態でデザインされているのだな…。これでは自然な見た目にならんよな…。まあ、フィギュアみたいなものとしてデザインしたのだろうと想像するけど。

さておき。日本人の足の長さの平均値は分かったけれど、例えば年齢別では値が変わってくるのかどうかが気になって。赤ん坊と成人では当然違うのだから、その間の年齢の足の長さも違うだろうなと。そのあたりも調べてみよう…。

2020/11/22() [n年前の日記]

#1 [cg_tools] MakeHuman 1.2.0を試用

パラメータを変更して人体3Dモデルを生成できる MakeHuman の 1.2.0 が公開されたという記事を目にしたので、興味が湧いて試用中。環境は Windows10 x64 2004 + blender 2.83.9 x64 LTS。

起動して、Community というタブをクリックして、Synchronize をクリックすれば、公式サイト上にアップロードされてるユーザ作成データの一覧を取得できる…らしいのだけど、これがかなり待たされる。止まってるのではないかと思えるほど…。それでもまあ、なんとか一覧が表示されるようになった。ModelもいくつかDLできた。

今回のバージョンから、ファイル保存しなくてもモデルデータを blender にインポートできるようになったらしい。操作方法が分からなかったけど弄ってたらなんとなくちょっとだけ分かってきた。たぶん。
MakeHuman側で表示させてる分には正直なところ「大丈夫かコレ」と不安になるけれど、blenderにインポートしてライトをいくつか置いてレンダリングすれば結構それっぽくなるなと…。照明の当て方って本当に重要なんだなと…。

2020/11/23(月) [n年前の日記]

#1 [godot] Godot Engineで3D表示の簡単なシューティングゲームを作ってみる、のまとめ

Godot Engine 3.2.3 x64 を使って、3D表示の簡単なシューティングゲームっぽいものを作ってみる手順をメモしたけれど、この日記ページでは記事を追っていくのが面倒臭いので各記事へのリンクを一応まとめておこうかと。

_プロジェクトを作成
_プレイヤーキャラシーンを作成
_メインシーンを作成
_プレイヤーをカーソルキーで動かす
_背景シーンを作成
_プレイヤーの弾を撃つ
_敵のシーンを作成
_敵から弾を撃たせる
_アタリ属性を設定
_アタリ判定処理を書く
_HUDシーンを作成
_ダメージエフェクトを作成
_タイトル画面その他を作成
_プレイヤーが画面端を超えないように補正
_3Dモデルデータをインポート
_背景の3Dモデルデータをインポート
_サウンドを追加
_プロジェクトをエクスポート

完成品は以下。

_simpleshootemup.html

#2 [pc] メインPCの画面表示が怪しい

今日も、メインPCがスリープから復帰するタイミングで画面表示がおかしくなった。画面全体に縦線が入って、色も青成分が無くなった感じの状態。一度その状態になってしまうとOSを再起動しても治らない。BIOS画面からして表示がおかしいまま。

大昔に目撃した、ビデオカードが壊れた時の症状に似ている気もするのだけど、液晶ディスプレイの電源を切って入れ直すと正常表示されてしまうし、ずっとPCを使ってる時は表示がおかしくなったりしないので、ビデオカードではなく液晶ディスプレイが壊れかけているのではと想像しているのだけど…。

もしビデオカードが壊れているなら、液晶ディスプレイ側でどんな操作をしても正常表示されたりはしないだろうし、PCを使ってる間にも画面がおかしくなったりするのではないかと。特に、3Dゲームの類を動かしてGPUに負荷をかけて発熱を増やせば即座に症状が出てくるだろうと思うのだけどそういうわけでもないので、これはディスプレイ側じゃないのかなと。

余談。 :

ちなみに、大昔に体験したビデオカードの故障は、ビデオメモリにサムスン製メモリを使ったNIVIDIA GPU搭載カードで発生してしまって…。どうも当時のサムスン製メモリは熱に対する耐久性がほとんど無かったらしくて、更にそのNVIDIA製GPUはかなり発熱する製品で。数年使うと結構な確率で寿命を迎えていたようで。当時ググったら、似た構成のビデオカードが似たような時期に次々に故障していたと知ってコレはダメ製品だなあと思った記憶が。

もっとも、たしかアナログ接続でディスプレイと接続していた時代の話なので、今では役に立たない話というか、そういう時代もあったねえ、程度の話なのだけど。何にせよ、そういうことがあったのでサムスン製品には全く良い印象を持ってないという…。

そういえば Intel Core2Duo を使ってた頃もメインメモリでサムスン製メモリを掴んでしまって、そのうちメモリエラーが出始めて悩んだ記憶が。轟音爆風FANをつけてメモリ周辺も冷却するようにしたらメモリエラーが出なくなって…。サムスン製品は、やはり熱に対する耐久性が低いのかなあと。

まあ、今回はそういう壊れ方じゃないのではと思ってるのでアレだけど。完全に余談でした。

#3 [zatta] 日記をアップロード

2020/11/03を最後に日記をアップロードしてなかったのでアップロード。

2020/11/24(火) [n年前の日記]

#1 [anime][neta] 「がんばれ!!ロボコちゃん」ってどうだろう

妄想メモ。

ネットサーフィンしていたら「ロボコンもネタ切れ気味」という一文が目に入って。「いやいや、そんな馬鹿な。たしか最近映画化してたぐらいだし、アレもアレンジ次第で全然復活させられるのでは」と思ったのだけど、そこで話してた「ロボコン」は「高専ロボコン」のことで、自分すっかり勘違いして空回りというオチに。

それはさておき。「がんばれ!!ロボコン」をアレンジというと、どういう手があるかなとついつい妄想してしまったり。例えば…。近年流行りの安易なアレだけど、登場するロボットを全員美少女ロボット化するのはどうかなあ、と。安易だけど。これから売り出したい若手女優さん・女性タレントを集めてきてずらりと並べて…。でもソレたぶんどこかの女子校の教室にしか見えない…。だけど全員、ライダー01に出てきたロボット達みたいに耳に何か機械をつけていて。AKB48ならぬRBK48とでも名付けてイベント等でライブさせてみたりとか。48人は多過ぎるか…。何人ぐらいなら適切なんだろう。24人? 12人?

てなバカ妄想をしつつ、似たような企画はもう既にあるんじゃないかと「がんばれロボコ」でググったら薄い本が…。オリジナル作品っぽいけど、まあそういう感じのタイトルを誰もが思いつくわなと…。

他の作品を美少女化したらどうなるだろう。 :

そういえば石ノ森章太郎作品で全員美少女化的リメイク企画って聞いたことないなと。いや、石ノ森先生のことだからそれっぽい作品を絶対出してるはずで、自分が思い出せないだけだろうけど…。何かメジャーな作品でそういうアレをしたらどうなるだろう。例えば「サイボーグ009」を全員美少女化、とか。若い女優さんを9人ずらりと並べてアクションポーズをとらせて、ってどう見ても色物企画…。いや、サイボーグ少女がそれだけ居れば、例えば攻殻機動隊っぽい雰囲気にすることもできるのでは。草薙少佐みたいなのが9人並んで活躍したら、それはもう軍隊並みの…。「スケバン刑事」や「少女コマンドーIZUMI」をなんとなく連想。

てな妄想をしていて、ふと気になってググってみたら「009ノ1」という公式作品が既にあったと今頃になって知り。アニメ化や映画化までされてたのね…。しかも実写映画版は坂本浩一監督作品…。東映の平成ライダー・戦隊スタッフが作ってたとは…。知らなかった…。なんかもう色々と本物というか公式というか。

_石ノ森作品のリスト を眺めてみると、やはりその手のアレンジは先生自身が結構やってるんだなあ、てな気分になってきたりもして。

なら、ここは一つ逆に考えて全員を(以下略。

2020/11/25(水) [n年前の日記]

#1 [godot] Godot Engineでパーティクルを試したり

Godot Engine 3.2.3 x64 を使って操作方法を勉強中。

Godot Engine にはパーティクルを発生させるノードが用意されてるらしいので試してみたり。パーティクルというのは…以下のような感じのソレ。

godot_particles_ss01.gif

参考ページ。 :

試してみた。 :

とりあえず試してみた。画像は以下を使用。

star01_48x48.png
_star01_48x48.png

2Dゲームの場合は、シーンに Particles2Dノード、もしくは CPUParticles2Dノードを追加すると使える。3Dの場合は、名前に2Dがつかないノードを選べばいい。

godot_particles_ss02.png

  • GLES3 を使ってる場合は、GPUを使って処理をする Particles2D を選べる。
  • GLES2 を使ってる場合は、CPUを使って処理をする CPUParticles2D を使う。ただしパフォーマンスは落ちるらしい。

各プロパティについて。 :

公式ドキュメントを眺めれば各プロパティの意味も分かるだろうけど、自分も軽くメモしておこう…。

もっとも、ここに列挙したプロパティをきっちり真面目に全部覚える必要はないわけで。Texture に何か画像をドラッグアンドドロップしてから各プロパティをテキトーに弄っていけばイイ感じのパーティクルになるだろうから、そういうノリで。せっかくGUIで即座に値を変更できるツールなのだから、大昔のアドベンチャーゲーム感覚 ―― 画面のどこかを手当たり次第にマウスクリックすればいつもと違うメッセージが出てきたぞ、てなノリで操作すればなんとなく分かるはず。

以下は CPUParticles2D のプロパティ。

godot_particles_ss03.png

  • Emitting : パーティクルを発生させるかさせないか。true か false で変えられる
  • Amount : パーティクル発生数
  • Lifetime : パーティクルの生存時間。単位は秒
  • OneShot : 有効なら1回だけ発生させて自身を消滅させる
  • Speed Scale : 速度スケール。値が大きくなれば早くなるし、小さくなれば遅くなる
  • Explosiveness : 0ならポポポポと連続で発生。1ならバッと一気に発生。0.x ならポポッ…と発生
  • Local Coords : 有効なら、発生元の座標を基準にしながら動く。無効ならグローバル座標で動く
  • Texture : パーティクル1つあたりで表示する画像ファイルを指定
  • Emission Shape : 発生元の形状。Point なら1点から発生。Box なら矩形範囲の中で発生
  • Direction - Direction : パーティクルを発射する方向を指定
  • Direction - Spread : 方向に対して -α - +αの角度で発生。180度を指定すれば全方向に発射するようになる
  • Gravity : 重力
  • Initial Velocity - Velocity : 初期速度
  • Linear Accel - Accel : 加減速度。マイナス値なら減速。プラス値なら加速
  • Angle - Angle : 初期表示角度
  • Scale Amount : 初期表示サイズ
  • Scale Amount Curve : 表示サイズが変化していく様子をグラフで指定

  • 「xxx Random」は、xxx をランダムに変化させる割合を指定できる。
  • 「xxx Curve」は、xxx の変化の仕方をグラフで指定できる。「空」をクリックして「新規 Curve」を選べばカーブを作成できる。
  • カーブ(グラフ?)の中で右クリック → 「ポイントを追加」を選べば制御点を増やせる。
  • ポイント(制御点)をクリックすれば傾きを指定する線が出てくるので、ドラッグしてカーブの形を変えられる。

html5でエクスポートしてみた。 :

CPUParticles2D をマウスカーソルの位置に0.25秒間隔で発生させるプロジェクトを作って、html5でエクスポートしてみた。Webブラウザ上でも動くはず。

_particles_test_gles20.html

2020/11/26(木) [n年前の日記]

#1 [godot] Godot Engineでビルボードを使った3Dパーティクルを試したり

Godot Engine 3.2.3 x64 を使って操作方法を勉強中。Godot Engine のパーティクル機能について試しているところ。

2Dのパーティクルはできたので、3Dのパーティクルを試してみた。CPUParticlesノードを使って3Dモデルを ―― メッシュ(Mesh)を発生させることはできたものの、ビルボードを発生させるやり方が分からなくてちょっと悩んだり。

とりあえず、以下の画像を使って実験。

star01_48x48.png
_star01_48x48.png

試してみたけど、たぶん以下のような感じでビルボードのパーティクルを出せるのかなと。

まず、Drawing - Mesh は、QuadMesh を選択。

godot_particles_3d_ss01.png


Material は SpatialMaterial を選んで、以下を設定。

godot_particles_3d_ss02.png

動作確認。 :

html5でエクスポートしてみた。

_particles_test_3d.html

箱とビルボード(星の画像)の2種類をパーティクルとして発生させてる。カメラが動いても星の見た目が変わらない ―― ビルボードで表示できてることぐらいは一応分かるかなと。

AMD/ATI製GPU環境では注意。 :

AMD/ATI製GPUを使ってる場合は、GPUを使って処理をする Particlesノードを使うとビルボードが有効にならない場合もあるらしい。

_Is there any problem with the option Billboard Mode of Particles 3D? - Issue #34158 - godotengine/godot

上記の例では最新ドライバにアップデートして問題が解決したと報告されてるけど…。

Godot Engine は OpenGL を使って描画をしているらしいのだけど、AMD/ATI製GPUのドライバはOpenGL周りに関して仕様が未実装だったりバグがあったりと、かなり評判が悪くて。 *1

_本の虫: OpenGLドライバー品質の実情

ただ、前述のページのやり取りの中で、CPUParticles を使えばパフォーマンスは落ちるけどAMD/ATIのドライバに起因するバグを回避できるかもしれない、という話も出てるようなので、不安な時はそっちを使っておいたほうがいいのかもしれないなと。

*1: 自分も以前、OpenGLを勉強した時にバグに遭遇して悩んだ記憶が…。当時OpenGLで描画していた今は亡き(?)某3DCGソフトも「AMD/ATI RADEON環境では基本的に動作を保証しません」と説明書に一言加えてたぐらいで。そのくらいAMD/ATI製GPUのドライバは出来が酷い…。

2020/11/27(金) [n年前の日記]

#1 [godot] Godot Engineでマウスを動かしてカメラを動かしたい

Godot Engine 3.2.3 x64 を勉強中。Godot Engine のカメラをマウス操作で動かしたいなと。

色々ググってコピペして、こんな感じになった。

_Main.gd
extends Spatial

export var camera_dist = 50
export var angle_speed = 15
var ang = Vector3()

func _ready():
    ang = $Camera.rotation_degrees

func _process(delta):
    ang.y += angle_speed * delta
    set_camera_angle(ang)

func _input(event):
    if event is InputEventMouseMotion:
        ang.y -= (event.relative.x * 360 / 1280)
        ang.x -= (event.relative.y * 180 / 720)
        set_camera_angle(ang)
        
func set_camera_angle(angle):
    var pos = Vector3()
    var d = abs(camera_dist * cos(deg2rad(angle.x)))
    pos.y = camera_dist * sin(deg2rad(-angle.x))
    pos.z = d * cos(deg2rad(angle.y))
    pos.x = d * sin(deg2rad(angle.y))
    $Camera.rotation_degrees = angle
    $Camera.translation = pos


html5でエクスポートしてみた。Webブラウザ上で動くはず。マウスを動かすとカメラがグルグル回る。

_particles_test_3d.html

2021/01/28追記。 :

Webブラウザ上で表示すると、カメラの向きが妙だなと…。まあ、こんな感じでカメラを動かせるっぽい、ということで…。

#2 [anime] 「ルパン三世 THE FIRST」を視聴

TV放映されてたので視聴。ルパン三世のCGアニメ劇場版。山崎貴監督作品。

映像が凄いな…。冒頭、実写かと思ってしまった。

次元と銭形の顔のデザイン・モデリングが実にイイ感じ。次元は体臭が感じられそうなイケメンおじさんだし、銭形はゴツゴツカクカク感がなかなか。

カーチェイスや飛行機のアクションが迫力あるシーンになってた気もする。実写では難しいアクションもアニメなら実現可能なわけで…。CGアニメは実写のリアリティとアニメならではの荒唐無稽さの両方を兼ね備えた映像を追求できるのだなと改めて思えてきたりもして。

監督さんがカリ城大好きなせいか既存作品のオマージュが散りばめられていて、小ネタを見つけるだけでも楽しめるかもしれないなと。脚本や設定についてもファミリー向け路線のルパン三世として比較的よく出来ていた気がしたり。TVSPの豪華版とでもいうか…。 *1

それにしても、モンキーパンチ先生にもこの映像を見てもらいたかった…。CGが大好きだった先生のことだから、脚本や演出はともかく、映像については間違いなく喜んでくれただろうなと…。
*1: ただ、「ルパン一味って大体こんな感じだよね? 違うかな? コレでたぶん合ってるよね? どうですかね?」てなノリがずっと感じられたあたりが…。自分のイメージしたルパンを観客にゴリ押しするのではなく、皆がイメージするルパン三世の最大公約数を探す作業だったのではと想像したりもして。角は全部削り落としてひたすら丸くする、みたいな…。まあ、尖ったルパンは別路線で作ってるし、こっちは万人向けを要求されたはずの企画だろうから、これはこれで。ちゃんとルパンになってた気がするので監督はドヤ顔していいと思いました。

2020/11/28() [n年前の日記]

#1 [godot] Godot Engineで多重スクロールを試したり

Godot Engine 3.2.3 x64 を勉強中。Godot Engine で背景の多重スクロールをしてみたい。Parallax Scroll、視差スクロールと呼ばれるらしいけど。

_Parallax scrolling - Wikipedia

以下のページが参考になった。ありがたや。

_【Godot Engine】背景無限スクロールのやり方 - えんどーめも

試した結果を html5 でエクスポートしてみた。

_parallax_test01.html

使用画像。 :

使用画像は以下。CC0 / Public Domain ってことで。

scifi_bg_chip_base.png
_scifi_bg_chip_base.png


enemy_ball0.png
_enemy_ball0.png

ノード等についてメモ。 :

多重スクロールをするには、ParallaxBackgroundノードとParallaxLayerノードを使うらしい。

以下のようなノード構成にしてみた。

godot_parallax_ss01.png

Main (Node)
│
├─ ParallaxBackground
│     │
│     ├─ ParallaxLayer
│     │     │
│     │     └─ TileMap
│     │
│     ├─ ParallaxLayer
│     │     │
│     │     └─ TileMap
│     │
│     └─ ParallaxLayer
│            │
│            └─ TileMap
│       
└─ Sprite
       │
       └─ Camera2D

ParallaxLayer 1つで背景1面分を担当するらしい。

各面の速度の違いは、ParallaxLayer のプロパティ、Motion - Scale で指定する。1なら等速(?)スクロール。1より小さければ遅くなるし、1より大きければ速くなる。

godot_parallax_ss02.png


ParallaxLayer の下にぶら下げた表示ノードは、繰り返し表示もできるらしい。Motion - Mirroring でサイズ?を指定すれば、そのサイズで繰り返し表示される状態になる。

godot_parallax_ss03.png


Camera2Dノードはカメラを担当するノードっぽい。

godot_parallax_ss04.png

  • Current にチェックを入れて有効化すると、そのCamera2Dで指定された範囲がウインドウに表示される模様。
  • Limit に値を指定すれば、その範囲内だけを表示する状態になる。
  • Smoothing にチェックを入れれば、カメラが動く時に若干動きが遅れて滑らかなカメラの動きになる。

#2 [anime][neta] ルパン三世パート2の映像としてアルバトロスの映像を流すのは何か違う気がする

思考メモ。

昨日、TV放送されたCGアニメ版ルパン三世を視聴していたのですが。

放送直後にちょこっとTVシリーズを紹介する場面があって。そこでTVアニメ版のパート1、パート2、と映像が流れていったのだけど、パート2の映像として宮崎駿演出担当・テレコム作画回の「死の翼アルバトロス」の映像がずっと流れていて…。

_死の翼アルバトロス - Wikipedia

そこがどうにも気になってしまって。

たしかに「アルバトロス」もパート2の中の一エピソードではあるので間違ってはいないのだけど…。パート2の代表的な映像として「アルバトロス」を流すのは違うだろー、と、当時視聴していた自分は思ってしまったのでした。

あの回はパート2のイメージとあまりに違い過ぎるからTV局が受け取り拒否しようとしたという逸話(噂? 都市伝説?)があるぐらいに、当時としては「コレはさすがにナシだろー」な回で…。子供だった自分もTVの前で「このルパンはなんかおかしい」「いつものルパンじゃない」「なんなんだこの回」とかなり困惑した記憶があるほどで。

そのぐらい、パート2全体の中では異質な作画、異質な話なので、パート2を未見の人達に「パート2ってこんな感じの作画・映像でしたよ」と言いながら見せてはいけない回じゃないのかなと。名エピソードだけどかなり毛色が違う特殊な回ですよー、と言いながら紹介しないといかん回でしょうと。

まあ、宮崎駿の知名度を利用して少しでも興味を持ってもらいたいという意図があるんだろうけど…。なんだかちょっと歴史の改竄っぽい気配がして、これいいのかな、マズいのでは、どうなんだろう、という不安が…。

パート2と言ったらやはり北原健雄さんのあのキャラデザだよなと…。テレコム回はキャラデザからしてなんか違ってて、メインスタッフが修正を要求しても頑として直してくれなくて、とうとう途中から諦めちゃって「もういいよ。テレコムは勝手にやってくれ」「アイツらの担当回には責任持たねえよ。知らねえよ」と素通し状態になったぐらいにメインスタッフから不評を買ってたとも聞くわけで。なのに、そっちを代表扱いにしちゃいかんだろうと…。

もちろん、そういった色んなノリが混在してるあたりもパート2らしさ、とも思うんですけど。パート2の映像として「アルバトロス」を前面に出すのは絶対違うよなー、と自分は思うのです…。

そういえば、ルパン三世CGアニメ版の宣伝特番でも「カリ城は大ヒット!」と平然と嘘を言ってたし…。既存作品の紹介の仕方が雑というか怪しいというか、そういうところがどうも気になる…。知っててわざとやってるのか、それとも知らないから平気でそういうことをしちゃうのか、判断がつかなくて…。

余談。経緯を無視するのは良くない気がする。 :

余談。宮崎駿が担当した「カリ城」「アルバトロス」「さらば愛しきルパンよ」は、パート2への嫉妬というか恨みというか、そういうドロドロしたアレからできちゃった経緯があるわけで…。

TVアニメ版パート1の後半は高畑+宮崎コンビが担当してるけど、本放送時は全く視聴率が取れなくて惨敗状態で放送を終えるのですが。その後再放送するたびに何故か(?)視聴率が伸びていって、気をよくしたTV局がパート2の制作を企画して、高畑+宮崎コンビが示してくれたパート1後半のドタバタ路線を継承発展する方向でパート2を作って子供達に大人気、という流れがあるわけで。

しかし宮崎駿としては面白くないわけですよ。パート1を作った時はあんだけボロクソに自分達を叩いてたのに、手のひらクルー状態でパート2を作って、しかもパート2のスタッフはまるで自分達の手柄のように振舞ってやがる。ふざけんなと。あの時の俺達に対する仕打ちは一体何だったのかと。

なので、宮崎駿はこっそりと ―― いや、堂々と、自分の担当回でパート2のルパンの全否定を始めちゃう。溜め込んでいた恨みつらみが、パート2に向かって暴発(?)してしまうのです。
  • 「カリ城」ではルパンがおじさんキャラになってるけれど、何がパート2だよ、ケッ。今更ルパンでもないだろ、アイツはもうおじさんみたいなもんだろうが、という意識がああいうルパン像に繋がっていくわけで。たしか緑ジャケットにしたのもパート2の否定だったような…。違ったかな…。
  • 「アルバトロス」の中で見せたバリバリにアクションする不二子像は、パート2の不二子像の否定から出てきているし。
  • パート2最終回では「お前達が今まで見ていたパート2のルパンは全部偽ルパンだったんだよ!」と言い出すし。嘘じゃないです。インタビュー記事で語ってますから。さすがに後になって「アレはやり過ぎだった…」「自分は何様のつもりなのか…」と反省してましたけど。
宮崎駿という天才的なアニメ作家の人間的な面白さが感じ取れる実に良いエピソードだと思うし、どれもちゃんと面白い映画・回になったので結果オーライだと思うのですが、なぜか恨まれちゃったパート2のメインスタッフにとっては溜まったもんじゃない…。

そういう経緯があるので、実はパート2の否定をしている「アルバトロス」をパート2の代表映像として出すのは違うよなー、と思ってしまうわけで。宮崎駿が否定しようとしていた ―― 「こんなのは偽ルパンだ!」とイラついてた映像のほうが、本来のパート2だよなと。あそこはやっぱり北原ルパンを画面に出してくれないと「ああ、パート2ですね」って感じにならないよなあ…。テレコムのルパンを出すのは違う…。

いやまあ、「アルバトロス」もパート2の一エピソードではあるので間違ってはいないのですけど。とりあえず、ちょっとコレ分かってねえなー、とは思いました。みたいな。それともアレかな。「せめてこの回だけでも見てくれ。マジで面白いから」という気持ちがそこにあったのだろうか…。それならそれで分かる…。たしかに宮崎駿担当回は一見の価値アリ、まだ見てないなんて人生で損をしてるレベル、なんだよなあ…。

こういうアレコレってTVドラマとして作れたりしないのかな…。難しいかな…。

2020/11/29() [n年前の日記]

#1 [godot] Godot EngineでBGアタリについて実験中

Godot Engine 3.2.3 x64 を勉強中。

Godot Engine でBGアタリの処理について実験中。 …はずなのだけど、動作が怪しい瞬間が多々あって…。 なぜこんな動きに…。

2020/11/30(月) [n年前の日記]

#1 [godot] Godot EngineでBGアタリについて実験中その2

Godot Engine 3.2.3 x64 を勉強中。BGアタリ処理について実験しているところ。

斜め床の上に着地した際に妙な動きになっちゃう問題が未解決だけど…。それ以外は一応らしく動いてる感じになったので試しにhtml5でエクスポートしてアップロード。Webブラウザ上で動くはず。(※ 2020/12/01追記。背景の奥にColorRectノードを置いて色替えする版で差し替えてみた。)

_parallax_test01.html

画面をクリックしないとキー入力が反応しないかもしれない。

使用画像は以下。CC0 / Public Domain ってことで。

_player_640x640_80x80.png (1キャラ: 80x80ドット, 8x8個, 画像サイズ: 640x640ドット)
_scifi_bg_chip_base.png (1セル: 64x64ドット, 8x8個, 画像サイズ: 512x512ドット)

ノード構成やスクリプトについてメモ。 :

ノード構成は以下のようにした。

bg_collision_ss04.png

  • プレイヤーキャラは KinematicBody2D が担当。
  • BGアタリを担当する TileMap は、背景の多重スクロールを担当する ParallaxBackground, ParallaxLayer の中に入れてしまうと正常動作しない。プレイヤーキャラと同階層に置いたら期待通りの動作をしてくれた。
  • 単に表示するだけでアタリ判定をしないBGについては、ParallaxBackground, ParallaxLayer の中に入れてしまって問題無い。


重力については、プロジェクト設定の中で値を指定することができる。

bg_collision_ss01.png

bg_collision_ss02.png


プロジェクト設定のインプットマップで、move_left, move_right, move_up も追加。

bg_collision_ss03.png


プレイヤーキャラを動かしてるスクリプトは以下。KinematicBody2D にスクリプトをアタッチした。

_KinematicBody2D.gd
extends KinematicBody2D

export var walk_force = 2000.0
export var walk_max_speed = 400.0
export var stop_force = 1600.0
export var jump_speed = 960.0

var velocity = Vector2()
var gravity
var jumping = false

func _ready():
    gravity = ProjectSettings.get_setting("physics/2d/default_gravity")

#func _process(delta):
#   pass

func _physics_process(delta):
    var right = Input.get_action_strength("move_right")
    var left = Input.get_action_strength("move_left")
    var input = right - left
    var walk = walk_force * input
    if abs(walk) < walk_force * 0.2:
        velocity.x = move_toward(velocity.x, 0, stop_force * delta)
        # velocity.x = 0
    else:
        velocity.x += walk * delta
        # velocity.x = walk_max_speed * input
    velocity.x = clamp(velocity.x, -walk_max_speed, walk_max_speed)
    velocity.y += gravity * delta

    var snap = Vector2(0, 32)
    if is_on_floor():
        jumping = false
        if Input.is_action_pressed("move_up"):
            velocity.y = -jump_speed
            jumping = true
            snap = Vector2.ZERO
    else:
        snap = Vector2.ZERO
        
    velocity = move_and_slide_with_snap(velocity, snap, Vector2.UP, true, 4, deg2rad(60))
    # velocity = move_and_slide(velocity, Vector2.UP)
    
    _set_label_text("velo: (%.2f, %.2f)" % [velocity.x, velocity.y])
    
    if right > 0.5:
        $Sprite.flip_h = false
    if left > 0.5:
        $Sprite.flip_h = true
    
    if jumping:
        $Sprite.frame = 2
    elif is_on_floor():
        $Sprite.frame = 0
    else:
        $Sprite.frame = 1

func _set_label_text(t):
    $Label.text = t

  • gravity = ProjectSettings.get_setting("physics/2d/default_gravity") で、プロジェクト設定の default_gravity を読み取ってる。
  • KinematicBody2D は一定の時間間隔で _physics_process(delta) を呼び出すので、その中に移動処理を書く。
  • _process(delta) も一定の時間間隔で呼ばれるけれど、状況によっては物理計算・衝突判定が正しく行われないのだとか。アタリを持ってるオブジェクトは _physics_process(delta) 内で処理をせよ、ということになっているらしい。
  • Input.get_action_strength("xxx") で、xxxキーやxxxボタンを押したかどうかが 0 〜 1 の値で得られる。アナログジョイスティックを割り当てた時には、おそらく 0.n の値が返ってくるのではないか。たぶん。
  • velocity = move_and_slide_with_snap() でBGアタリとの衝突判定+補正処理をする。内部で delta を使って計算しているらしいので、与えるベクトルに対して事前に delta を掛けておかなくてもいい。
  • move_and_slide*() を呼んでおけば、is_on_floor() で床の上に立っているかどうかを調べられる。立っていたら true。立ってなかったら false。
  • move_and_slide() と move_and_slide_with_snap() の違いは、前者が斜め床に非対応で、後者が斜め床に対応 ―― 床に吸着して移動ができるらしい。
  • move_and_slide_with_snap() は斜め床にも対応しているけれど、ジャンプしようとした時も床に吸着されてジャンプできなくなるので、ジャンプ時は吸着用(?)ベクトルを 0 にする。(Vector2.ZERO = Vector2(0, 0))

move_and_slide_with_snap() に渡すパラメータは色々あってややこしいけど、おそらく以下のような内容かなと…。
Vector2 move_and_slide_with_snap ( Vector2 velocity,
                                   Vector2 snap,
                                   Vector2 up_direction,
                                   bool stop_on_slope,
                                   int max_slides,
                                   float floor_max_angle,
                                   bool infinite_inertia )
  • velocity ... 移動ベクトル。単位はピクセル/秒。1秒で何ピクセル移動するか。
  • snap ... 床への吸着用ベクトル。このベクトルの範囲内に床があった場合は床に吸着されるので、斜め床に張り付いたまま動ける。
  • up_direction ... 上方向を指定する。Vector2.UP (= Vector2(0, -1)) を指定。省略時はデフォルト値 Vector2(0, 0) が入る。
  • stop_on_slope ... true なら、Body(?)が静止してる場合に斜面の上で滑らなくなる。デフォルトは false。
  • max_slides ... 衝突してから静止するまで何回スライドするか、らしい。デフォルト値は4。
  • floor_max_angle ... 床として扱う角度を指定。デフォルトは 0.785398ラジアン(45度)。BGアタリに45度の床が混ざってると床として扱われなくなるので、その場合は 45度以上を指定してやると良いらしい。ちなみに、deg2rad(度) で度をラジアンに変換できる。
  • infinite_inertia ... RigidBody2D への反映を変化させるらしいが…よくわからない。

参考ページ。 :

_2D移動の概要 - Godot Engine (stable)の日本語のドキュメント
_キネマティックキャラクター(2D) - Godot Engine (stable)の日本語のドキュメント
_KinematicBody2Dの使用 - Godot Engine (stable)の日本語のドキュメント
_KinematicBody2D - Godot Engine (stable)の日本語のドキュメント
_KinematicBody2D の基本 - Qiita
_Godot Engine - Godot 3.1 will get many improvements to KinematicBody
_godot-demo-projects/player.gd at master - godotengine/godot-demo-projects
_【Godot】TileMapのコリジョンからタイル情報を検出する - 非常口blog
_Difference between move_toward() and lerp() - Godot Engine - Q&A
_Move_and_Slide_With_Snap Failing When Jump From Slope - Godot Engine - Q&A
_Move_and_slide_with_snap() is consistently inconsistent : godot
_Help with Move_and_Slide_with_snap. Wont stay on slope. : godot
_Problem with move and slide with snap function : godot
_move_and_slide_with_snap issue : godot
_KinematicBody2D: move_and_slide_with_snap won't snap to slopes - Issue #26274 - godotengine/godot
_Kinematic body slides off slopes that is supposed to snap to when landing - Issue #30777 - godotengine/godot
_move_and_slide_with_snap 3D KinematicBody not snapping on slopes - Issue #38564 - godotengine/godot
_KinematicBody player with RayShape does not respect snap argument in move_and_slide_with_snap() - Issue #34098 - godotengine/godot
_The player (kinematic body) continues to slide down the slope after I have stopped moving it - Godot Forum

#2 [anime] 「キラメイジャー」田口監督担当回を視聴

ウルトラマンシリーズで活躍している田口清隆監督が東映戦隊シリーズにも参戦とのことで、期待に胸を膨らませつつ視聴。

スゴイ…。奥では巨大ロボットと巨大怪人が、そして手前では等身大の戦隊と敵の戦闘員が戦っていて、しかし時々奥の巨大ロボット戦が手前にも飛び火(?)して、てなシーンに痺れた。奥のほうから巨大な剣が吹っ飛んできて手前の集団のど真ん中に刺さったり。敵巨大怪人の撃った弾が逸れてしまって手前の戦闘員達が軒並み吹き飛ばされたり。

あっちこっちに振りまくるカメラの動きに合わせて奥の着ぐるみ巨大ロボット達もちゃんと合成されてたあたりに感心したりもして。こういうのってどうやって位置合わせするんだろうと…。実写映像をトラッキングしてカメラの画角や動きを算出してCGで作った巨大物を合成するなら分かるのだけど、今回見たソレは手前も奥も実写素材っぽいし…。カメラが動かないカットなら奥に着ぐるみ巨大物が合成されることも珍しくはないけれど…。頓智がありそう…。

ふわふわと飛んでいる巨大ロボットの後ろで敵が大爆発するカットもグッときた。そういう構図もあったかー、みたいな。

何にせよ映像を見て驚きました。最近のライダーや戦隊は凄いことになってるなあ…。

以上、30 日分です。

過去ログ表示

Prev - 2020/11 - Next
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project