製造子彈—儲存預處理物件:

首先,我們需要新增一個靜態的sprite2D,與前一張的Player一樣,用來當作子彈本體。


依圖片順序為:

  1. 場景內選擇新增(+)Node。
  2. 選擇建立靜態的Sprite2D。
  3. 更改名稱為Bullet(子彈)。
  4. 新增上子彈貼圖。
  5. 建立他的Script。

接下來進入他的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裡面有玩家等等很多東西,這邊只有子彈。

與之前的MainScence概念相同,不過MainScence裡面有玩家等等很多東西,這邊只有子彈。

直接往檔案系統扔,就會提示儲存了

直接往檔案系統扔,就會提示儲存了


讓Player射出子彈—PackedScene 呼叫儲存場景

PackedScene功能可以把剛才儲存的子彈場景(bullet.tscn)當作資料資源,然後在程式碼中載入它,並在遊戲中產生一個副本(Instance)

我們需要:

  1. 在Player中先新增PackedScene,並將其命名為bullet

    public partial class Player : Sprite2D
    {
    	public PackedScene bullet;//在Player 底下即可。
    	}
    
  2. 在_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 方法
        // 雖然大多數情況可以省略,但有些情境(例如繼承特定邏輯)會需要保留它以確保原本的初始化邏輯被執行
    }
    
    
  3. 最後,在_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);
	}
}