見張り兵を作る
新しいステージの作成
ステージに必要なのは、以下の要素
Root
Player
Tilemap
CanvasModule
Cameras
xN
Guards
xN
これのRootを TemplateLevelとしてSceneで保存。
以後、新しいLevel(ステージ)を作るには、これを継承して作る。
Scene > New Inherited Scene > TemplateLevel.tscn
Guard Scene
Character.tscnを継承した新しいシーンを作る
https://gyazo.com/e47a7c05c1fb14ee5647fc86e609a9c6
Script
code: guard.py
extends "res://Character/NPCs/PlayerDetect.gd"
GuardのKinematicBody2Dに、PlayerDetect.gdを継承するだけで
監視カメラのbodyに付けたスクリプトと同じ働きをする
(共通点として、Kinematicbody > Light2D を親子として持つ)
Guardの動き
移動先のリストを持っている
ランダムに移動先を選んで移動する
プレイヤーの半分の速度
移動先についたら3sec停止、その後再移動する
立ち往生したら、新しい移動先をpickする
stuck = 立ち往生
Navigationの方法
NPCに移動ルートを提供する方法
2つある
NavigationInstancePolygon
Tilemap
どちらも、Navigation2D ノードの 子 or 孫 でなければならない
(2階層下までの子供)
NavigationInstancePolygon
1つのShapeを持つ
mapの構造と齟齬が内容に作る
エディタ上で編集できる
Tilemap での Navigation
Navigation shapeは個別のタイルに対して描写する
Navigation shapeは完璧に端っこをあわせないと行けない(pixel perfect)
上書きしない
隙間がない
デバッグ実行中に編集することができる
移動先リストの例
https://gyazo.com/ca295f2667cf71b215097d22389752d8
これらは、Vector2の配列として保存される
Navigation2D Node
Navigationが設定された
NavigationInstancePolygon
Tilemap
のどちらかを使う
get_simple_path()メソッドでパスを生成する。
パスはVector2の配列
リストの位置へ順番に移動
NavigationPolygonを作成する
https://gyazo.com/8132537de733eeb045258952ee6c3e41
壁にめり込んだところにNavigationの範囲を含むと、NPCは衝突しながらも
移動しようとするので、壁を含まないようにする。
この方法では、大雑把にナビゲーションを作れるが、
壁のタイルマップを変更したときなどに手動で直さなければならないので非効率
TilemapにNavigationを追加する
NavigationをTilemapの親にする前に注意
Tilemapをテンプレートシーンとして作成していて、それを継承したシーンをすでに作っているとき、
TileMap を Navigation2D の子要素にすると、タイルマップを貼っている状態が
デフォルトに上書きされる。
それを避けるために、
TileMapをコピー > コピーしたものをNavigation2Dの子要素にする
継承先のSceneで、コピーしてNavigationの子になっているTileMapを元のTilemapにトレースする
TileSet Navigation
Tilemap > インスペクタ > Tilesetリソースを選択
タイルセットの中のfloorx を選択して、Navigationを押す。
設定は、Collision や Occlusion と全く同じ
Priorityで出てこないタイルもあるけど、とりあえず全部Rectangleで塗っとく
https://gyazo.com/aa20b864b974b2e76f7897d6c842d68f
Destinations
TemplateのNavigation2Dノードの下に、空のNodeを追加
名前をDestinationsにしておく。
継承したLevelの中で、Position2D Nodeを、Destinationsの中に作っていく
名前をDestination0にrenameして、連番の数字にする
Position2D Node
エディタ上で、2D位置のヒントを表示するNode2Dオブジェクト
エディタ上でマークが見えるだけ(実行時は見えなくなる)
主に、Navigationの移動先ポイントに使われる(3D版もある)
チャレンジ
NavigationがセットされているTilemapのfloorエリアに、
Destination(Position2D)をたくさんおいてみる
get_simple_path( )
Navigation2Dのメソッド
get_simple_path(from, to, optimized(=bool))
戻り値はArray<Vector2>
Paths
経路は、Vector2の配列として返される。
パス0 に向かう > 到着 > パス0をremove > 繰り返し
で目的地に向かう
https://gyazo.com/f19893429ae4e71ee1fac4ce19c0df14
Pathsのサイズが1になったら、Timerで3sec数えて新しいパスを生成する
onready
グローバルでvarキーワードで変数を初期化するとき、
多くのケースでシーンツリーが読み込まれていないので
初期化が失敗する時がある。
onready var キーワードを使うと、func _onready()の中で初期化したときと
同じような挙動になる。
Timer
GuardにTimerノードを追加
timeout()シグナルをスクリプトに接続
WaitTime = 3
OneShot = true にしておく(終わったあとに再起動するのを防ぐ)
AutoStart = false