首先,我們需要新增一個靜態的sprite2D,與前一張的Player一樣,用來當作子彈本體。
依圖片順序為:
接下來進入他的Script,
我們的子彈會是由下向上射擊,因此需要賦予速度(1000,Player的兩倍), movement(子彈的速度 * 遊戲的流速(delta))
給予他一個位置=vector2(x軸不動,Y軸相減)
一個物件建立的標準流程。
public double speed = 1000;
// Called every frame. 'delta' is the elapsed time since the previous frame.
public override void _Process(double delta)
{
float movement = (float)(speed * delta);
this.Position +=new Vector2(0, -movement);
}
最後,儲存此script後,將Bullet此Node,整個丟進新增的Prefab資料夾中(自己創建)。
最後
另存為自己一個單獨的Tscn檔案。
這就是Godot的預處理物件的概念了。
與之前的MainScence概念相同,不過MainScence裡面有玩家等等很多東西,這邊只有子彈。
直接往檔案系統扔,就會提示儲存了
PackedScene
呼叫儲存場景PackedScene
功能可以把剛才儲存的子彈場景(bullet.tscn)當作資料資源,然後在程式碼中載入它,並在遊戲中產生一個副本(Instance)。
我們需要:
在Player中先新增PackedScene
,並將其命名為bullet
public partial class Player : Sprite2D
{
public PackedScene bullet;//在Player 底下即可。
}
在_Ready中載入PackedScence,並指定tscn的路徑。
public override void _Ready()
{
bullet = GD.Load<PackedScene>("res://Prefab/bullet.tscn");
// 這行程式的目的是:從檔案系統中載入一個場景資源(bullet.tscn)
// `GD.Load<PackedScene>()` 是 Godot 提供的泛型載入函式,用來載入特定型別的資源
// 這裡的意思是:「從路徑 res://Prefab/bullet.tscn 載入一個 PackedScene 類型的資源」
// 載入後會儲存在 bullet 變數中(通常 bullet 是類別的私有變數,型別為 PackedScene)
base._Ready();
// base._Ready() 是呼叫父類別(基底類)的 _Ready 方法
// 雖然大多數情況可以省略,但有些情境(例如繼承特定邏輯)會需要保留它以確保原本的初始化邏輯被執行
}
最後,在_Process的Class進程中去新增物件(PlayerFire),使用Instance呼叫此tscn。 並且指定MainScence節點新增PlayerFire節點。
public override void _Process(double delta)
{
// 每幀檢查是否按住 "Shoot" 動作對應的按鍵(例如空白鍵)
// 第二個參數 true 表示忽略 UI 控件干擾
if (Input.IsActionJustPressed("Shoot", true))
{
// 建立一個子彈的場景實例(從 PackedScene 實體化)
var Playerfire = this.bullet.Instantiate();
// 將子彈加入到場景樹中(這裡加到根節點)
this.GetTree().Root.AddChild(Playerfire);
//或者也可以加到MainScence節點中
this.GetTree().Root.GetNode("MainScence").AddChild(Playerfire);
// 將子彈加入到場景中的指定節點(MainScence),比較能夠確保層級正確
}
}
但是,目前的子彈命沒有位置資訊,也不會跟著Player移動,
所以我們需要先將PlayerFire as為Node2D
var Playerfire = this.bullet.Instantiate() as Node2D;//後方增加as Node2D
並且指定PlayerFire 的Position = Player的 Postition
if (Input.IsActionJustPressed("Shoot", true))
{
// GD.Print("Shoot");
var Playerfire = this.bullet.Instantiate() as Node2D;
Playerfire.Position = this.Position;//讓他們的位置相同
this.GetTree().Root.GetNode("MainScence").AddChild(Playerfire);
}
這樣就完成了子彈射擊、子彈產生位置了
<aside> 🔥
如果想要讓子彈在身前產生:
PlayerFire.Position = this.Position + new Vector2(0, -30);
// 往上偏移 30 像素
</aside>
當然,你也可以這樣寫
public override void _Ready()
{
// 預先載入子彈的場景(Bullet.tscn)
// 這個場景裡已經綁好了我們自己寫的 Bullet 腳本
PlayerFire = GD.Load<PackedScene>("res://Profab/Bullet.tscn");
}
public override void _Process(double delta)
{
if (Input.IsActionJustPressed("Shoot", true))
{
// 當玩家按下射擊鍵(Shoot)時觸發,這只會在按下當下那一幀觸發一次
// 用我們事先載入的 PlayerFire 場景,生成一個新的子彈
// <Bullet> 表示這顆子彈是使用我們自己寫的 Bullet 腳本類別
var bullet = PlayerFire.Instantiate<Bullet>();
// 把子彈的初始位置設在玩家正上方一點(避免重疊)
bullet.Position = this.Position + new Vector2(0, -100);
// 把子彈加入場景中,讓它正式出現在畫面上
GetTree().Root.AddChild(bullet);
}
}