Unity3D_(遊戲)2D坦克大戰 像素版

 

  2D坦克大戰    像素版git

 

遊戲規則: github

  玩家經過上、下、左、右移動坦克,空格鍵發射子彈數組

  敵人AI出身時朝向己方大本營(未防止遊戲快速結束,心臟上方三個單位障礙物設爲剛體)   dom

  當玩家被擊殺次數>=3  或  心臟被子彈擊穿  從新加載遊戲場景ide

  控制遊戲每4秒發射一顆子彈(可本身作修改)  工具

 

  遊戲項目已託管到Github上  傳送門 優化

 

  (文章最下邊有遊戲腳本)動畫

 

場景搭建this

 

  設置Main Camera攝像頭參數spa

 

 

遊戲中製做預製體與動畫

 

  建立一個Cube做爲參照,Cube長寬高都爲1m

  建立一個Player1_0做爲玩家

     將Player1_0製做成預製體

 

  製做遊戲磚塊、鋼鐵、草叢、基地預製體

 

  建立遊戲物體出生動畫Animation

  快速建立動畫:點擊第一張圖片->按住Shift->點擊最後一張圖片

  保存好後場景出現Born_0動畫,修改scale大小爲3 3 3

 

 

  製做坦克出生無敵、坦克爆炸、河流特效

  動畫大小與預製體適配

 

 

控制玩家的移動

 

  添加Player.cs腳本,綁定到Player玩家坦克上

 

  默認移動速度

    public float moveSpeed = 3;

 

  監聽玩家水平軸輸入

    float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
                
    transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);

 

  監聽玩家垂直軸輸入

  float v = Input.GetAxisRaw("Vertical");
   transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);

 

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour {

    public float moveSpeed = 3;

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        //監聽玩家水平軸輸入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);

        //監聽玩家垂直軸輸入
        float v = Input.GetAxisRaw("Vertical");
        transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);
    }
}
Player.cs

 

 

控制圖片的移動和切換

 

  製做坦克渲染

  添加精靈數組的引用

    private SpriteRenderer sr;
    public Sprite[] tankSprite;

 

(上 右 下 左)

 

  玩家按上下左右控制坦克方向的移動

//監聽玩家水平軸輸入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);
        if (h < 0)
        {
            sr.sprite = tankSprite[3];
        }else if (h>0)
        {
            sr.sprite = tankSprite[1];
        }

        //監聽玩家垂直軸輸入
        float v = Input.GetAxisRaw("Vertical");
        transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);
        if (v < 0)
        {
            sr.sprite = tankSprite[2];
        }
        else if (v > 0)
        {
            sr.sprite = tankSprite[0];
        }

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour {

    public float moveSpeed = 3;

    private SpriteRenderer sr;
    public Sprite[] tankSprite; //上 右 下 左

    // Use this for initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    
    // Update is called once per frame
    void Update () {
        //監聽玩家水平軸輸入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);
        if (h < 0)
        {
            sr.sprite = tankSprite[3];
        }else if (h>0)
        {
            sr.sprite = tankSprite[1];
        }

        //監聽玩家垂直軸輸入
        float v = Input.GetAxisRaw("Vertical");
        transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);
        if (v < 0)
        {
            sr.sprite = tankSprite[2];
        }
        else if (v > 0)
        {
            sr.sprite = tankSprite[0];
        }
    }
}
Player.cs

 

 

碰撞器的添加

 

  碰撞檢測

    兩個物體都有碰撞器

    一個物體上掛載剛體組件

 

  給玩家Player添加2D剛體和2D碰撞器

  剛體的Gravity Scale設置爲0,取消重力因素的影響

 

   給Barriar、Wall、River、Heart添加Box Collider 2D碰撞器

 

 

  發現坦克方向座標軸會改變,在Rigidbody 2D中Constraints下的Freeze Rotation Z 進行綁定,當它碰撞到物體時座標不發生偏移

 

  

 

  解決抖動問題

 

  使用private void FixedUpdate()

    FixedUpdate () 和 Update ()     

    同:當MonoBehaviour啓用時,其在每一幀被調用。都是用來更新的

    異:Update()每一幀的時間不固定,即第一幀與第二幀的時間t1和第三幀與第四幀的時間t2不必定相同。FixedUpdate()每幀與每幀之間相差的時間是固定的.

    Update受當前渲染的物體影響,這與當前場景中正在被渲染的物體有關(好比人物的面數,個數等),有時快有時慢,幀率會變化,Update被調用的時間間隔就會發生變化。可是FixedUpdate則不受幀率的變化影響,它是以固定的時間間隔來被調用。

    因此一些物理屬性的更新操做應該放在FxiedUpdate中操做,好比Force,Collider,Rigidbody等。外設的操做也是,好比說鍵盤或者鼠標的輸入輸出Input,由於這樣GameObject的物理表現的更平滑,更接近現實。

    FixedUpdate的時間間隔能夠在項目設置中更改,Edit->Project Setting->time 找到Fixed timestep。就能夠修改了
FixedUpdate () 和 Update ()

 

//監聽玩家水平軸輸入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.Translate(Vector3.right*h*moveSpeed*Time.fixedDeltaTime,Space.World);


 //監聽玩家垂直軸輸入
        float v = Input.GetAxisRaw("Vertical");
        transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);

 

  FixedUpdate()方法留空就行

    private void FixedUpdate()
    {
        
    }

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour {

    public float moveSpeed = 3;

    private SpriteRenderer sr;
    public Sprite[] tankSprite; //上 右 下 左

    // Use this for initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    
    // Update is called once per frame
    void Update () {
        //監聽玩家水平軸輸入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.Translate(Vector3.right*h*moveSpeed*Time.fixedDeltaTime,Space.World);
        if (h < 0)
        {
            sr.sprite = tankSprite[3];
        }else if (h>0)
        {
            sr.sprite = tankSprite[1];
        }

        //監聽玩家垂直軸輸入
        float v = Input.GetAxisRaw("Vertical");
        transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (v < 0)
        {
            sr.sprite = tankSprite[2];
        }
        else if (v > 0)
        {
            sr.sprite = tankSprite[0];
        }
    }

    //
    private void FixedUpdate()
    {
        
    }
}
Player.cs

 

  解決玩家按方向鍵左右的同時按上下

  在監聽玩家垂直軸輸入後對v方向按鍵進行判斷,若是爲0則在Update()中直接返回

 float v = Input.GetAxisRaw("Vertical");
        transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (v < 0)
        {
            sr.sprite = tankSprite[2];
        }
        else if (v > 0)
        {
            sr.sprite = tankSprite[0];
        }

        if(v!=0)
        {
            return;
        }

        //監聽玩家水平軸輸入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.Translate(Vector3.right*h*moveSpeed*Time.fixedDeltaTime,Space.World);
        if (h < 0)
        {
            sr.sprite = tankSprite[3];
        }else if (h>0)
        {
            sr.sprite = tankSprite[1];
        }

 

  整理一下Player.cs腳本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour {

    //屬性值
    public float moveSpeed = 3;

    //引用
    private SpriteRenderer sr;
    public Sprite[] tankSprite; //上 右 下 左


    // Use this for initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    
    // Update is called once per frame
    void Update () {
       

    }

    private void FixedUpdate()
    {
        Move();
    }

    //坦克的移動方法
    private void Move()
    {
        //監聽玩家垂直軸輸入
        float v = Input.GetAxisRaw("Vertical");
        transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (v < 0)
        {
            sr.sprite = tankSprite[2];
        }
        else if (v > 0)
        {
            sr.sprite = tankSprite[0];
        }

        if (v != 0)
        {
            return;
        }

        //監聽玩家水平軸輸入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (h < 0)
        {
            sr.sprite = tankSprite[3];
        }
        else if (h > 0)
        {
            sr.sprite = tankSprite[1];
        }
    }
}
Player.cs

 

 

2D渲染層級

 

  設置遊戲物體的層級

      

 

      

 

 

 

坦克的攻擊

 

  坦克的攻擊方法

private void Attack()
    {
        if(Input.GetKeyDown(KeyCode.Space))
        {
            Instantiate(bullectPrefab,transform.position,transform.rotation);
        }
    }

 

    private void FixedUpdate()
    {
        Move();
        Attack();
    }

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour {

    //屬性值
    public float moveSpeed = 3;

    //引用
    private SpriteRenderer sr;
    public Sprite[] tankSprite; //上 右 下 左
    public GameObject bullectPrefab;

    // Use this for initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    
    // Update is called once per frame
    void Update () {
       

    }

    private void FixedUpdate()
    {
        Move();
        Attack();
    }

    //坦克的攻擊方法
    private void Attack()
    {
        if(Input.GetKeyDown(KeyCode.Space))
        {
            Instantiate(bullectPrefab,transform.position,transform.rotation);
        }
    }

    //坦克的移動方法
    private void Move()
    {
        //監聽玩家垂直軸輸入
        float v = Input.GetAxisRaw("Vertical");
        transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (v < 0)
        {
            sr.sprite = tankSprite[2];
        }
        else if (v > 0)
        {
            sr.sprite = tankSprite[0];
        }

        if (v != 0)
        {
            return;
        }

        //監聽玩家水平軸輸入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (h < 0)
        {
            sr.sprite = tankSprite[3];
        }
        else if (h > 0)
        {
            sr.sprite = tankSprite[1];
        }
    }
}
player.cs

 

  子彈的朝向和移動

  經過按鍵V和H來判斷子彈旋轉的角度

 

  定義子彈旋轉的角度

 private Vector3 bullectEulerAugles;

 

  子彈參數的角度:當前坦克的角度+子彈應該旋轉的角度

Instantiate(bullectPrefab,transform.position,Quaternion.Euler(transform.eulerAngles+bullectEulerAugles));

 

---恢復內容結束---

 

 

未完~

 

完成時會有完整項目展現

 

 

場景搭建

 

  設置Main Camera攝像頭參數

 

 

遊戲中製做預製體與動畫

 

  建立一個Cube做爲參照,Cube長寬高都爲1m

  建立一個Player1_0做爲玩家

     將Player1_0製做成預製體

 

  製做遊戲磚塊、鋼鐵、草叢、基地預製體

 

  建立遊戲物體出生動畫Animation

  快速建立動畫:點擊第一張圖片->按住Shift->點擊最後一張圖片

  保存好後場景出現Born_0動畫,修改scale大小爲3 3 3

 

 

  製做坦克出生無敵、坦克爆炸、河流特效

  動畫大小與預製體適配

 

 

控制玩家的移動

 

  添加Player.cs腳本,綁定到Player玩家坦克上

 

  默認移動速度

    public float moveSpeed = 3;

 

  監聽玩家水平軸輸入

    float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
                
    transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);

 

  監聽玩家垂直軸輸入

  float v = Input.GetAxisRaw("Vertical");
   transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);

 

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour {

    public float moveSpeed = 3;

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        //監聽玩家水平軸輸入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);

        //監聽玩家垂直軸輸入
        float v = Input.GetAxisRaw("Vertical");
        transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);
    }
}
Player.cs

 

 

控制圖片的移動和切換

 

  製做坦克渲染

  添加精靈數組的引用

    private SpriteRenderer sr;
    public Sprite[] tankSprite;

 

(上 右 下 左)

 

  玩家按上下左右控制坦克方向的移動

//監聽玩家水平軸輸入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);
        if (h < 0)
        {
            sr.sprite = tankSprite[3];
        }else if (h>0)
        {
            sr.sprite = tankSprite[1];
        }

        //監聽玩家垂直軸輸入
        float v = Input.GetAxisRaw("Vertical");
        transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);
        if (v < 0)
        {
            sr.sprite = tankSprite[2];
        }
        else if (v > 0)
        {
            sr.sprite = tankSprite[0];
        }

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour {

    public float moveSpeed = 3;

    private SpriteRenderer sr;
    public Sprite[] tankSprite; //上 右 下 左

    // Use this for initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    
    // Update is called once per frame
    void Update () {
        //監聽玩家水平軸輸入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.Translate(Vector3.right*h*moveSpeed*Time.deltaTime,Space.World);
        if (h < 0)
        {
            sr.sprite = tankSprite[3];
        }else if (h>0)
        {
            sr.sprite = tankSprite[1];
        }

        //監聽玩家垂直軸輸入
        float v = Input.GetAxisRaw("Vertical");
        transform.Translate(Vector3.up * v * moveSpeed * Time.deltaTime, Space.World);
        if (v < 0)
        {
            sr.sprite = tankSprite[2];
        }
        else if (v > 0)
        {
            sr.sprite = tankSprite[0];
        }
    }
}
Player.cs

 

 

碰撞器的添加

 

  碰撞檢測

    兩個物體都有碰撞器

    一個物體上掛載剛體組件

 

  給玩家Player添加2D剛體和2D碰撞器

  剛體的Gravity Scale設置爲0,取消重力因素的影響

 

   給Barriar、Wall、River、Heart添加Box Collider 2D碰撞器

 

 

  發現坦克方向座標軸會改變,在Rigidbody 2D中Constraints下的Freeze Rotation Z 進行綁定,當它碰撞到物體時座標不發生偏移

 

  

 

  解決抖動問題

 

  使用private void FixedUpdate()

    FixedUpdate () 和 Update ()     

    同:當MonoBehaviour啓用時,其在每一幀被調用。都是用來更新的

    異:Update()每一幀的時間不固定,即第一幀與第二幀的時間t1和第三幀與第四幀的時間t2不必定相同。FixedUpdate()每幀與每幀之間相差的時間是固定的.

    Update受當前渲染的物體影響,這與當前場景中正在被渲染的物體有關(好比人物的面數,個數等),有時快有時慢,幀率會變化,Update被調用的時間間隔就會發生變化。可是FixedUpdate則不受幀率的變化影響,它是以固定的時間間隔來被調用。

    因此一些物理屬性的更新操做應該放在FxiedUpdate中操做,好比Force,Collider,Rigidbody等。外設的操做也是,好比說鍵盤或者鼠標的輸入輸出Input,由於這樣GameObject的物理表現的更平滑,更接近現實。

    FixedUpdate的時間間隔能夠在項目設置中更改,Edit->Project Setting->time 找到Fixed timestep。就能夠修改了
FixedUpdate () 和 Update ()

 

//監聽玩家水平軸輸入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.Translate(Vector3.right*h*moveSpeed*Time.fixedDeltaTime,Space.World);


 //監聽玩家垂直軸輸入
        float v = Input.GetAxisRaw("Vertical");
        transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);

 

  FixedUpdate()方法留空就行

    private void FixedUpdate()
    {
        
    }

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour {

    public float moveSpeed = 3;

    private SpriteRenderer sr;
    public Sprite[] tankSprite; //上 右 下 左

    // Use this for initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    
    // Update is called once per frame
    void Update () {
        //監聽玩家水平軸輸入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.Translate(Vector3.right*h*moveSpeed*Time.fixedDeltaTime,Space.World);
        if (h < 0)
        {
            sr.sprite = tankSprite[3];
        }else if (h>0)
        {
            sr.sprite = tankSprite[1];
        }

        //監聽玩家垂直軸輸入
        float v = Input.GetAxisRaw("Vertical");
        transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (v < 0)
        {
            sr.sprite = tankSprite[2];
        }
        else if (v > 0)
        {
            sr.sprite = tankSprite[0];
        }
    }

    //
    private void FixedUpdate()
    {
        
    }
}
Player.cs

 

  解決玩家按方向鍵左右的同時按上下

  在監聽玩家垂直軸輸入後對v方向按鍵進行判斷,若是爲0則在Update()中直接返回

 float v = Input.GetAxisRaw("Vertical");
        transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (v < 0)
        {
            sr.sprite = tankSprite[2];
        }
        else if (v > 0)
        {
            sr.sprite = tankSprite[0];
        }

        if(v!=0)
        {
            return;
        }

        //監聽玩家水平軸輸入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.Translate(Vector3.right*h*moveSpeed*Time.fixedDeltaTime,Space.World);
        if (h < 0)
        {
            sr.sprite = tankSprite[3];
        }else if (h>0)
        {
            sr.sprite = tankSprite[1];
        }

 

  整理一下Player.cs腳本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour {

    //屬性值
    public float moveSpeed = 3;

    //引用
    private SpriteRenderer sr;
    public Sprite[] tankSprite; //上 右 下 左


    // Use this for initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    
    // Update is called once per frame
    void Update () {
       

    }

    private void FixedUpdate()
    {
        Move();
    }

    //坦克的移動方法
    private void Move()
    {
        //監聽玩家垂直軸輸入
        float v = Input.GetAxisRaw("Vertical");
        transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (v < 0)
        {
            sr.sprite = tankSprite[2];
        }
        else if (v > 0)
        {
            sr.sprite = tankSprite[0];
        }

        if (v != 0)
        {
            return;
        }

        //監聽玩家水平軸輸入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (h < 0)
        {
            sr.sprite = tankSprite[3];
        }
        else if (h > 0)
        {
            sr.sprite = tankSprite[1];
        }
    }
}
Player.cs

 

 

2D渲染層級

 

  設置遊戲物體的層級

      

 

      

 

 

 

坦克的攻擊

 

  坦克的攻擊方法

private void Attack()
    {
        if(Input.GetKeyDown(KeyCode.Space))
        {
            Instantiate(bullectPrefab,transform.position,transform.rotation);
        }
    }

 

    private void FixedUpdate()
    {
        Move();
        Attack();
    }

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour {

    //屬性值
    public float moveSpeed = 3;

    //引用
    private SpriteRenderer sr;
    public Sprite[] tankSprite; //上 右 下 左
    public GameObject bullectPrefab;

    // Use this for initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    
    // Update is called once per frame
    void Update () {
       

    }

    private void FixedUpdate()
    {
        Move();
        Attack();
    }

    //坦克的攻擊方法
    private void Attack()
    {
        if(Input.GetKeyDown(KeyCode.Space))
        {
            Instantiate(bullectPrefab,transform.position,transform.rotation);
        }
    }

    //坦克的移動方法
    private void Move()
    {
        //監聽玩家垂直軸輸入
        float v = Input.GetAxisRaw("Vertical");
        transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (v < 0)
        {
            sr.sprite = tankSprite[2];
        }
        else if (v > 0)
        {
            sr.sprite = tankSprite[0];
        }

        if (v != 0)
        {
            return;
        }

        //監聽玩家水平軸輸入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (h < 0)
        {
            sr.sprite = tankSprite[3];
        }
        else if (h > 0)
        {
            sr.sprite = tankSprite[1];
        }
    }
}
player.cs

 

  子彈的朝向和移動

  經過按鍵V和H來判斷子彈旋轉的角度

 

  定義子彈旋轉的角度

 private Vector3 bullectEulerAugles;

 

  子彈參數的角度:當前坦克的角度+子彈應該旋轉的角度

Instantiate(bullectPrefab,transform.position,Quaternion.Euler(transform.eulerAngles+bullectEulerAugles));

 

    private void Attack()
    {
        if(Input.GetKeyDown(KeyCode.Space))
        {
            //子彈參數的角度:當前坦克的角度+子彈應該旋轉的角度
            Instantiate(bullectPrefab,transform.position,Quaternion.Euler(transform.eulerAngles+bullectEulerAugles));
            timeVal = 0;
        }
    }

 

  給子彈添加方向速度

    public float moveSpeed = 10;

 

  給子彈添加判斷是不是友軍

    public bool isPlayerBullect;

 

    void Update () {
        transform.Translate(transform.up*moveSpeed*Time.deltaTime,Space.World);
    }

 

  添加子彈攻擊CD間隔

        if (timeVal>=0.4f)
        {
            //間隔大於0.4的時候纔有攻擊效果
            Attack();
        }
        else
        {
            timeVal += Time.deltaTime;
        }

 

 

 

 

  給組件添加標籤

  

 

  給子彈添加碰撞體和觸發器

 

  添加Heart.cs腳本,當Heart心臟被子彈攻擊時,切換死亡圖片

    private SpriteRenderer sr;

    public Sprite BrokenSprite;   

    // Use this for initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }

 

  添加Heart.cs心臟死亡時方法

    private void Die()
    {
        sr.sprite = BrokenSprite; 
    }

 

  添加Explosion.cs腳本

  當坦克銷燬時觸發腳本

public class Explosion : MonoBehaviour {

    // Use this for initialization
    void Start () {
        //坦克銷燬後0.167秒銷燬爆炸特效
        Destroy(gameObject,0.167f);
    }
    
    // Update is called once per frame
    void Update () {
        
    }
}

 

  子彈觸發碰撞檢測

  當子彈碰撞到物體時觸發OnTriggerEnter2D(Collider2D collision)方法

  子彈碰到「Tank」判斷是不是友軍,不是的話擊毀本身

  子彈碰到"Wall"時,銷燬子彈自身

  子彈碰到"Heart"時,觸發基地死亡方法

  子彈碰到"Barrier"剛體時,銷燬子彈

 

private void OnTriggerEnter2D(Collider2D collision)
    {
        switch(collision.tag)
        {
            case "Tank":
                if(!isPlayerBullect)
                {
                    collision.SendMessage("Die");
                }
                break;
            case "Heart":
                collision.SendMessage("Die");
                Destroy(gameObject);
                break;
            case "Enemy":
                break;
            case "Wall":
                //銷燬自身和牆
                Destroy(collision.gameObject);
                Destroy(gameObject);
                break;
            case "Barrier":
                Destroy(gameObject);
                break;
            default:
                break;
        }
    }

 

  

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour {

    //屬性值
    public float moveSpeed = 3;
    private Vector3 bullectEulerAugles;
    public float timeVal;
    private float defendTimeVal=1;
    private bool isDefended=true;

    //引用
    private SpriteRenderer sr;
    public Sprite[] tankSprite; //上 右 下 左
    public GameObject bullectPrefab;
    public GameObject explosionPrefab;
    public GameObject defendEffectPrefab;

    // Use this for initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    
    // Update is called once per frame
    void Update () {
        //保護是否處於無敵狀態
        if(isDefended)
        {
            defendEffectPrefab.SetActive(true);
            defendTimeVal -= Time.deltaTime;
            if (defendTimeVal<=0)
            {
                isDefended = false;
                defendEffectPrefab.SetActive(false);
            }
        }

        //攻擊的CD
        if (timeVal>=0.4f)
        {
            //間隔大於0.4的時候纔有攻擊效果
            Attack();
        }
        else
        {
            timeVal += Time.deltaTime;
        }
    }

    private void FixedUpdate()
    {
        Move();
    }

    //坦克的攻擊方法
    private void Attack()
    {
        if(Input.GetKeyDown(KeyCode.Space))
        {
            //子彈參數的角度:當前坦克的角度+子彈應該旋轉的角度
            Instantiate(bullectPrefab,transform.position,Quaternion.Euler(transform.eulerAngles+bullectEulerAugles));
            timeVal = 0;
        }
    }

    //坦克的移動方法
    private void Move()
    {
        //監聽玩家垂直軸輸入
        float v = Input.GetAxisRaw("Vertical");
        transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (v < 0)
        {
            sr.sprite = tankSprite[2];
            bullectEulerAugles = new Vector3(0, 0, -180);
        }
        else if (v > 0)
        {
            sr.sprite = tankSprite[0];
            bullectEulerAugles = new Vector3(0, 0, 0);
        }

        if (v != 0)
        {
            return;
        }

        //監聽玩家水平軸輸入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (h < 0)
        {
            sr.sprite = tankSprite[3];
            bullectEulerAugles = new Vector3(0, 0, 90);
        }
        else if (h > 0)
        {
            sr.sprite = tankSprite[1];
            bullectEulerAugles = new Vector3(0, 0, -90);
        }
    }

    //坦克的死亡方法
    private void Die()
    {
        if(isDefended)
        {
            return;
        }
        //產生爆炸特效
        Instantiate(explosionPrefab, transform.position, transform.rotation);
        //死亡
        Destroy(gameObject);
    }
}
Player.cs

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Explosion : MonoBehaviour {

    // Use this for initialization
    void Start () {
        //坦克銷燬後0.167秒銷燬爆炸特效
        Destroy(gameObject,0.167f);
    }
    
    // Update is called once per frame
    void Update () {
        
    }
}
Explosion.cs

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Heart : MonoBehaviour {

    private SpriteRenderer sr;

    public Sprite BrokenSprite;   

    // Use this for initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    

    private void Die()
    {
        sr.sprite = BrokenSprite; 
    }
}
Heart

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Bullect : MonoBehaviour {

    public float moveSpeed = 10;

    public bool isPlayerBullect;

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        transform.Translate(transform.up*moveSpeed*Time.deltaTime,Space.World);
    }

    //子彈觸發碰撞檢測
    private void OnTriggerEnter2D(Collider2D collision)
    {
        switch(collision.tag)
        {
            case "Tank":
                if(!isPlayerBullect)
                {
                    collision.SendMessage("Die");
                }
                break;
            case "Heart":
                collision.SendMessage("Die");
                Destroy(gameObject);
                break;
            case "Enemy":
                break;
            case "Wall":
                //銷燬自身和牆
                Destroy(collision.gameObject);
                Destroy(gameObject);
                break;
            case "Barrier":
                Destroy(gameObject);
                break;
            default:
                break;
        }
    }

}
Bullect.cs

 

 

敵人的製做

 

  Ctrl+D一份玩家,修改圖片渲染,製做敵人

 

  添加敵人腳本Enemy.cs

  玩家的移動和敵人的移動差很少,把Player.cs腳本中內容複製到Enemy.cs當中

  

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Enemy : MonoBehaviour {

    //屬性值
    public float moveSpeed = 3;
    private Vector3 bullectEulerAugles;
    public float timeVal;
    private float defendTimeVal = 1;
    private bool isDefended = true;

    //引用
    private SpriteRenderer sr;
    public Sprite[] tankSprite; //上 右 下 左
    public GameObject bullectPrefab;
    public GameObject explosionPrefab;
    public GameObject defendEffectPrefab;

    // Use this for initialization
    void Start()
    {
        sr = GetComponent<SpriteRenderer>();
    }

    // Update is called once per frame
    void Update()
    {
        //保護是否處於無敵狀態
        if (isDefended)
        {
            defendEffectPrefab.SetActive(true);
            defendTimeVal -= Time.deltaTime;
            if (defendTimeVal <= 0)
            {
                isDefended = false;
                defendEffectPrefab.SetActive(false);
            }
        }

        //攻擊的CD
        if (timeVal >= 0.4f)
        {
            //間隔大於0.4的時候纔有攻擊效果
            Attack();
        }
        else
        {
            timeVal += Time.deltaTime;
        }
    }

    private void FixedUpdate()
    {
        Move();
    }

    //坦克的攻擊方法
    private void Attack()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            //子彈參數的角度:當前坦克的角度+子彈應該旋轉的角度
            Instantiate(bullectPrefab, transform.position, Quaternion.Euler(transform.eulerAngles + bullectEulerAugles));
            timeVal = 0;
        }
    }

    //坦克的移動方法
    private void Move()
    {
        //監聽玩家垂直軸輸入
        float v = Input.GetAxisRaw("Vertical");
        transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (v < 0)
        {
            sr.sprite = tankSprite[2];
            bullectEulerAugles = new Vector3(0, 0, -180);
        }
        else if (v > 0)
        {
            sr.sprite = tankSprite[0];
            bullectEulerAugles = new Vector3(0, 0, 0);
        }

        if (v != 0)
        {
            return;
        }

        //監聽玩家水平軸輸入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (h < 0)
        {
            sr.sprite = tankSprite[3];
            bullectEulerAugles = new Vector3(0, 0, 90);
        }
        else if (h > 0)
        {
            sr.sprite = tankSprite[1];
            bullectEulerAugles = new Vector3(0, 0, -90);
        }
    }

    //坦克的死亡方法
    private void Die()
    {
        if (isDefended)
        {
            return;
        }
        //產生爆炸特效
        Instantiate(explosionPrefab, transform.position, transform.rotation);
        //死亡
        Destroy(gameObject);
    }
}
Enemy.cs

(由於敵人沒有出生無敵3s,運行時無敵預製體defendEffectPrefab會出現報空)

 

  添加基地死亡時動畫

    public GameObject explosionPrefab;

 

private void Die()
    {
        sr.sprite = BrokenSprite;
        Instantiate(explosionPrefab,transform.position,transform.rotation);
    }

 

  (關閉項目後爆炸腳本失活了,最後的時候再作一個補上)

 

  添加一個玩家出生時腳本Born.cs

  延時玩家出生和死亡動畫

    public GameObject playerPrefab;

    // Use this for initialization
    void Start () {
        Invoke("BornTank",1f);
        Destroy(gameObject,1f);
    }
    

    private void BornTank()
    {
        Instantiate(playerPrefab,transform.position,Quaternion.identity);
    }

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Born : MonoBehaviour {

    public GameObject playerPrefab;

    // Use this for initialization
    void Start () {
        Invoke("BornTank",0.8f);
        Destroy(gameObject,0.8f);
    }
    
    // Update is called once per frame
    void Update () {
        
    }

    private void BornTank()
    {
        Instantiate(playerPrefab,transform.position,Quaternion.identity);
    }
}
Born.cs

 

  製做大坦克和小坦克,添加坦克方向變化時改變坦克方向圖片

  坦克改變方向順序按上、右、下、左進行添加

 

  小敵人同打敵人設置當坦克方向改變時切換自身圖片

  將大敵人和小敵人設置成預製體

  小敵人速度調大一些,改成5

 

  編寫Born.cs腳本判斷是否產生敵人

    public bool createPlay;

 

    private void BornTank()
    {
        if (createPlay)
        {
            Instantiate(playerPrefab, transform.position, Quaternion.identity);
        }
        else
        {
            int num = Random.Range(0, 2);
            Instantiate(enemyPrefabList[num], transform.position, Quaternion.identity);
        }
    }

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Born : MonoBehaviour {

    public GameObject playerPrefab;

    public GameObject[] enemyPrefabList;

    //判斷是否產生敵人
    public bool createPlay;

    // Use this for initialization
    void Start () {
        Invoke("BornTank",1f);
        Destroy(gameObject,1f);
    }

    private void Update()
    {

    }

    private void BornTank()
    {
        if (createPlay)
        {
            Instantiate(playerPrefab, transform.position, Quaternion.identity);
        }
        else
        {
            int num = Random.Range(0, 2);
            Instantiate(enemyPrefabList[num], transform.position, Quaternion.identity);
        }
    }
}
Born.cs

 

 

編寫敵人AI

 

  子彈間3s攻擊一次

 void Update()
    {
        //攻擊的時間間隔
        if (timeVal >= 0.3f)
        {
            //間隔大於0.4的時候纔有攻擊效果
            Attack();
        }
        else
        {
            timeVal += Time.deltaTime;
        }
    }

 

    //坦克的攻擊方法
    private void Attack()
    {
         //子彈參數的角度:當前坦克的角度+子彈應該旋轉的角度
         Instantiate(bullectPrefab, transform.position, Quaternion.Euler(transform.eulerAngles + bullectEulerAugles));
         timeVal = 0;
    }

 

  坦克的移動不須要按下上下左右鍵盤,只須要管理V和H的值對敵人AI進行方向的控制

  定義兩個計時器

    public float timeVal;
    public float timeValChangeDirection;

 

  修改敵人移動的方法

  

private void Move()
    {

        if(timeValChangeDirection>=4)
        {
            int num = Random.Range(0,8);
            if(num>5)
            {
                v = -1;
                h = 0;
            }else if (num == 0)
            {
                v = 1;
                h = 0;
            }else if (num > 0 && num <= 2)
            {
                h = -1;
                v = 0;
            }else if (num > 2 && num <= 4)
            {
                h = 1;
                v = 0;
            }

            timeValChangeDirection = 0;
        }
        else
        {
            timeValChangeDirection += Time.fixedDeltaTime;
        }

        //監聽玩家垂直軸輸入
      
        transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);

        if (v < 0)
        {
            sr.sprite = tankSprite[2];
            bullectEulerAugles = new Vector3(0, 0, -180);
        }
        else if (v > 0)
        {
            sr.sprite = tankSprite[0];
            bullectEulerAugles = new Vector3(0, 0, 0);
        }

        if (v != 0)
        {
            return;
        }

        //監聽玩家水平軸輸入
     
        transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (h < 0)
        {
            sr.sprite = tankSprite[3];
            bullectEulerAugles = new Vector3(0, 0, 90);
        }
        else if (h > 0)
        {
            sr.sprite = tankSprite[1];
            bullectEulerAugles = new Vector3(0, 0, -90);
        }
    }

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Enemy : MonoBehaviour {

    //屬性值
    public float moveSpeed = 3;
    private Vector3 bullectEulerAugles;
    private float v;
    private float h;

    //引用
    private SpriteRenderer sr;
    public Sprite[] tankSprite; //上 右 下 左
    public GameObject bullectPrefab;
    public GameObject explosionPrefab;

    //計時器
    public float timeVal;
    public float timeValChangeDirection=4;

    // Use this for initialization
    void Start()
    {
        sr = GetComponent<SpriteRenderer>();
    }

    // Update is called once per frame
    void Update()
    {
        //攻擊的時間間隔
        if (timeVal >= 0.3f)
        {
            //間隔大於0.4的時候纔有攻擊效果
            Attack();
        }
        else
        {
            timeVal += Time.deltaTime;
        }
    }

    private void FixedUpdate()
    {
        Move();
    }

    //坦克的攻擊方法
    private void Attack()
    {
         //子彈參數的角度:當前坦克的角度+子彈應該旋轉的角度
         Instantiate(bullectPrefab, transform.position, Quaternion.Euler(transform.eulerAngles + bullectEulerAugles));
         timeVal = 0;
    }

    //坦克的移動方法
    private void Move()
    {

        if(timeValChangeDirection>=4)
        {
            int num = Random.Range(0,8);
            if(num>5)
            {
                v = -1;
                h = 0;
            }else if (num == 0)
            {
                v = 1;
                h = 0;
            }else if (num > 0 && num <= 2)
            {
                h = -1;
                v = 0;
            }else if (num > 2 && num <= 4)
            {
                h = 1;
                v = 0;
            }

            timeValChangeDirection = 0;
        }
        else
        {
            timeValChangeDirection += Time.fixedDeltaTime;
        }

        //監聽玩家垂直軸輸入
      
        transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);

        if (v < 0)
        {
            sr.sprite = tankSprite[2];
            bullectEulerAugles = new Vector3(0, 0, -180);
        }
        else if (v > 0)
        {
            sr.sprite = tankSprite[0];
            bullectEulerAugles = new Vector3(0, 0, 0);
        }

        if (v != 0)
        {
            return;
        }

        //監聽玩家水平軸輸入
     
        transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (h < 0)
        {
            sr.sprite = tankSprite[3];
            bullectEulerAugles = new Vector3(0, 0, 90);
        }
        else if (h > 0)
        {
            sr.sprite = tankSprite[1];
            bullectEulerAugles = new Vector3(0, 0, -90);
        }
    }

    //坦克的死亡方法
    private void Die()
    {
        //產生爆炸特效
        Instantiate(explosionPrefab, transform.position, transform.rotation);
        //死亡
        Destroy(gameObject);
    }
}
Enemy.cs

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Bullect : MonoBehaviour {

    public float moveSpeed = 10;

    public bool isPlayerBullect;

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        transform.Translate(transform.up*moveSpeed*Time.deltaTime,Space.World);
    }

    //子彈觸發碰撞檢測
    private void OnTriggerEnter2D(Collider2D collision)
    {
        switch(collision.tag)
        {
            case "Tank":
                if(!isPlayerBullect)
                {
                    collision.SendMessage("Die");
                }
                Destroy(gameObject);
                break;
            case "Heart":
                collision.SendMessage("Die");
                Destroy(gameObject);
                break;
            case "Enemy":
                if(isPlayerBullect)
                {
                    collision.SendMessage("Die");
                }
                Destroy(gameObject);
                break;
            case "Wall":
                //銷燬自身和牆
                Destroy(collision.gameObject);
                Destroy(gameObject);
                break;
            case "Barrier":
                Destroy(gameObject);
                break;
            default:
                break;
        }
    }

}
Bullect.cs

 

 

初始化地圖工具

 

  判斷地圖長度

 

  地圖大小:長20  寬16

 

  添加MapCreation.cs地圖管理器來控制草和地圖等建築物

public class MapCreation : MonoBehaviour {

    //用來裝飾初始化地圖所需物體的數組
    //0.老家  1.牆  2.障礙  3.出生效果  4.河流    5.草  6.空氣牆
    public GameObject[] item;
    
}

 

 

  製做老家心臟和心臟周圍的圍牆

private void Awake()
    {
        //實例化老家
        Instantiate(item[0], new Vector3(0, -8, -0), Quaternion.identity);
        //用牆把老家圍起來
        Instantiate(item[1], new Vector3(-1, -8, -0), Quaternion.identity);
        Instantiate(item[1], new Vector3(1, -8, -0), Quaternion.identity);
        for(int i=-1;i<2;i++)
        {
            Instantiate(item[1],new Vector3(i,-7,0),Quaternion.identity);
        }
    }

 

 

  對同一個位置上進行判斷,判斷是否有障礙物在上面,若是在上面那再也不額外生成其它建築物

  已經有東西位置的列表

 private List<Vector3> itemPositionList = new List<Vector3>();

 

    private void CreateItem(GameObject createGameObject,Vector3 createPosition,Quaternion createRotate)
    {
        GameObject itemGo = Instantiate(createGameObject, createPosition, createRotate);
        itemGo.transform.SetParent(gameObject.transform);
        itemPositionList.Add(createPosition);
    }

 

  製做外圍牆,也就是遊戲邊界

 for(int i=-11;i<12;i++)
        {
            CreateItem(item[6], new Vector3(i, 9, 0), Quaternion.identity);
        }
        for(int i=-11;i<12;i++)
        {
            CreateItem(item[6], new Vector3(i, -9, 0), Quaternion.identity);
        }
        for(int i=-8;i<9;i++)
        {
            CreateItem(item[6], new Vector3(-11, i, 0), Quaternion.identity);
        }
        for(int i=-8;i<9;i++)
        {
            CreateItem(item[6], new Vector3(-11, i, 0), Quaternion.identity);
        }

 

  產生隨機位置的方法

 private Vector3 CreateRamdomPosition()
    {
        //不生成x=-10,10的兩列,y=-8和8這兩行的位置
        while(true)
        {
            Vector3 createPosition = new Vector3(Random.Range(-9, 10), Random.Range(-7, 8),0);
            if(!HasThePosition(createPosition))
            {
                return createPosition;
            }
          
        }
    }

 

  用來判斷位置列表中是否有這個位置

private bool HasThePosition(Vector3 createPos)
    {
        for(int i=0;i<itemPositionList.Count;i++)
        {
            if(createPos==itemPositionList[i])
            {
                return true;
            }
        }
        return false;
    }

 

 

  修復子彈觸發碰撞檢測

private void OnTriggerEnter2D(Collider2D collision)
    {
        switch(collision.tag)
        {
            case "Tank":
                if(!isPlayerBullect)
                {
                    collision.SendMessage("Die");
                    Destroy(gameObject);
                }
                break;
            case "Heart":
                collision.SendMessage("Die");
                Destroy(gameObject);
                break;
            case "Enemy":
                if(isPlayerBullect)
                {
                    collision.SendMessage("Die");
                    Destroy(gameObject);
                }
                break;
            case "Wall":
                //銷燬自身和牆
                Destroy(collision.gameObject);
                Destroy(gameObject);
                break;
            case "Barrier":
                Destroy(gameObject);
                break;
            default:
                break;
        }
    }

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Bullect : MonoBehaviour {

    public float moveSpeed = 10;

    public bool isPlayerBullect;

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        transform.Translate(transform.up*moveSpeed*Time.deltaTime,Space.World);
    }

    //子彈觸發碰撞檢測
    private void OnTriggerEnter2D(Collider2D collision)
    {
        switch(collision.tag)
        {
            case "Tank":
                if(!isPlayerBullect)
                {
                    collision.SendMessage("Die");
                    Destroy(gameObject);
                }
                break;
            case "Heart":
                collision.SendMessage("Die");
                Destroy(gameObject);
                break;
            case "Enemy":
                if(isPlayerBullect)
                {
                    collision.SendMessage("Die");
                    Destroy(gameObject);
                }
                break;
            case "Wall":
                //銷燬自身和牆
                Destroy(collision.gameObject);
                Destroy(gameObject);
                break;
            case "Barrier":
                Destroy(gameObject);
                break;
            default:
                break;
        }
    }

}
Bullect.cs

 

  實例化地圖

for(int i=0;i<20;i++)
        {
            CreateItem(item[1], CreateRamdomPosition(), Quaternion.identity);
        }
        for(int i=0;i<20;i++)
        {
            CreateItem(item[2], CreateRamdomPosition(), Quaternion.identity);
        }
        for (int i = 0; i < 20; i++)
        {
            CreateItem(item[4], CreateRamdomPosition(), Quaternion.identity);
        }
        for (int i = 0; i < 20; i++)
        {
            CreateItem(item[5], CreateRamdomPosition(), Quaternion.identity);
        }

 

  

 

  初始化玩家

GameObject go = Instantiate(item[3], new Vector3(-2, -8, 0), Quaternion.identity);
go.GetComponent<Born>().createPlay = true;

 

  產生敵人

CreateItem(item[3], new Vector3(-10,8,0),Quaternion.identity);
CreateItem(item[3], new Vector3(0, 8, 0), Quaternion.identity);
CreateItem(item[3], new Vector3(10, 8, 0), Quaternion.identity);

 

  實例化地圖而且讓圍牆的數量儘量的多

for (int i=0;i<60;i++)
        {
            CreateItem(item[1], CreateRamdomPosition(), Quaternion.identity);
        }
        for(int i=0;i<20;i++)
        {
            CreateItem(item[2], CreateRamdomPosition(), Quaternion.identity);
        }
        for (int i = 0; i < 20; i++)
        {
            CreateItem(item[4], CreateRamdomPosition(), Quaternion.identity);
        }
        for (int i = 0; i < 20; i++)
        {
            CreateItem(item[5], CreateRamdomPosition(), Quaternion.identity);
        }

 

  產生敵人的方法

 private void CreateEnemy()
    {
        int num = Random.Range(0, 3);
        Vector3 EnemyPos = new Vector3();
        if(num==0)
        {
            EnemyPos = new Vector3(-10, 8, 0);
        }else if(num==1)
        {
            EnemyPos = new Vector3(0, 8, 0);
        }
        else
        {
            EnemyPos = new Vector3(10, 8, 0);
        }

        CreateItem(item[3],EnemyPos,Quaternion.identity);
    }

 

  每隔5s產生一波敵人

 InvokeRepeating("CreateEnemy",4,5);

 

  優化一下敵人AI

  敵人AI碰到一塊兒時切換一次方向

private void OnCollisionEnter2D(Collision2D collision)
    {
        if(collision.gameObject.tag=="Enemy")
        {
            timeValChangeDirection = 4;
        }
    }

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour {

    //屬性值
    public float moveSpeed = 3;
    private Vector3 bullectEulerAugles;
    public float timeVal;
    private float defendTimeVal=3;
    private bool isDefended=true;

    //引用
    private SpriteRenderer sr;
    public Sprite[] tankSprite; //上 右 下 左
    public GameObject bullectPrefab;
    public GameObject explosionPrefab;
    public GameObject defendEffectPrefab;

    // Use this for initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    
    // Update is called once per frame
    void Update () {
        //保護是否處於無敵狀態
        if(isDefended)
        {
            defendEffectPrefab.SetActive(true);
            defendTimeVal -= Time.deltaTime;
            if (defendTimeVal<=0)
            {
                isDefended = false;
                defendEffectPrefab.SetActive(false);
            }
        }

        //攻擊的CD
        if (timeVal>=0.4f)
        {
            //間隔大於0.4的時候纔有攻擊效果
            Attack();
        }
        else
        {
            timeVal += Time.deltaTime;
        }
    }

    private void FixedUpdate()
    {
        Move();
    }

    //坦克的攻擊方法
    private void Attack()
    {
        if(Input.GetKeyDown(KeyCode.Space))
        {
            //子彈參數的角度:當前坦克的角度+子彈應該旋轉的角度
            Instantiate(bullectPrefab,transform.position,Quaternion.Euler(transform.eulerAngles+bullectEulerAugles));
            timeVal = 0;
        }
    }

    //坦克的移動方法
    private void Move()
    {
        //監聽玩家垂直軸輸入
        float v = Input.GetAxisRaw("Vertical");
        transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (v < 0)
        {
            sr.sprite = tankSprite[2];
            bullectEulerAugles = new Vector3(0, 0, -180);
        }
        else if (v > 0)
        {
            sr.sprite = tankSprite[0];
            bullectEulerAugles = new Vector3(0, 0, 0);
        }

        if (v != 0)
        {
            return;
        }

        //監聽玩家水平軸輸入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (h < 0)
        {
            sr.sprite = tankSprite[3];
            bullectEulerAugles = new Vector3(0, 0, 90);
        }
        else if (h > 0)
        {
            sr.sprite = tankSprite[1];
            bullectEulerAugles = new Vector3(0, 0, -90);
        }
    }

    //坦克的死亡方法
    private void Die()
    {
        if(isDefended)
        {
            return;
        }
        //產生爆炸特效
        Instantiate(explosionPrefab, transform.position, transform.rotation);
        //死亡
        Destroy(gameObject);
    }
}
Player.cs

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MapCreation : MonoBehaviour {

    //用來裝飾初始化地圖所需物體的數組
    //0.老家  1.牆  2.障礙  3.出生效果  4.河流    5.草  6.空氣牆
    public GameObject[] item;

    //已經有東西位置的列表
    private List<Vector3> itemPositionList = new List<Vector3>();

    private void Awake()
    {
        //實例化老家
        CreateItem(item[0], new Vector3(0, -8, -0), Quaternion.identity);
        //用牆把老家圍起來
        CreateItem(item[1], new Vector3(-1, -8, -0), Quaternion.identity);
        CreateItem(item[1], new Vector3(1, -8, -0), Quaternion.identity);
        for(int i=-1;i<2;i++)
        {
            Instantiate(item[1],new Vector3(i,-7,0),Quaternion.identity);
        }
        //實例化外圍牆
        for(int i=-11;i<12;i++)
        {
            CreateItem(item[6], new Vector3(i, 9, 0), Quaternion.identity);
        }
        for(int i=-11;i<12;i++)
        {
            CreateItem(item[6], new Vector3(i, -9, 0), Quaternion.identity);
        }
        for(int i=-8;i<9;i++)
        {
            CreateItem(item[6], new Vector3(-11, i, 0), Quaternion.identity);
        }
        for(int i=-8;i<9;i++)
        {
            CreateItem(item[6], new Vector3(11, i, 0), Quaternion.identity);
        }

        //初始化玩家
        GameObject go = Instantiate(item[3], new Vector3(-2, -8, 0), Quaternion.identity);
        go.GetComponent<Born>().createPlay = true;

        //產生敵人
        CreateItem(item[3], new Vector3(-10,8,0),Quaternion.identity);
        CreateItem(item[3], new Vector3(0, 8, 0), Quaternion.identity);
        CreateItem(item[3], new Vector3(10, 8, 0), Quaternion.identity);

        //第一次調用CreateEnemy用4s,每隔5s開調用
        InvokeRepeating("CreateEnemy",4,5);

        //實例化地圖
        for (int i=0;i<60;i++)
        {
            CreateItem(item[1], CreateRamdomPosition(), Quaternion.identity);
        }
        for(int i=0;i<20;i++)
        {
            CreateItem(item[2], CreateRamdomPosition(), Quaternion.identity);
        }
        for (int i = 0; i < 20; i++)
        {
            CreateItem(item[4], CreateRamdomPosition(), Quaternion.identity);
        }
        for (int i = 0; i < 20; i++)
        {
            CreateItem(item[5], CreateRamdomPosition(), Quaternion.identity);
        }
    }

 

    private void CreateItem(GameObject createGameObject,Vector3 createPosition,Quaternion createRotate)
    {
        GameObject itemGo = Instantiate(createGameObject, createPosition, createRotate);
        itemGo.transform.SetParent(gameObject.transform);
        itemPositionList.Add(createPosition);
    }

    //產生隨機位置的方法
    private Vector3 CreateRamdomPosition()
    {
        //不生成x=-10,10的兩列,y=-8和8這兩行的位置
        while(true)
        {
            Vector3 createPosition = new Vector3(Random.Range(-9, 10), Random.Range(-7, 8),0);
            if(!HasThePosition(createPosition))
            {
                return createPosition;
            }
          
        }
    }

    //用來判斷位置列表中是否有這個位置
    private bool HasThePosition(Vector3 createPos)
    {
        for(int i=0;i<itemPositionList.Count;i++)
        {
            if(createPos==itemPositionList[i])
            {
                return true;
            }
        }
        return false;
    }

    //產生敵人的方法
    private void CreateEnemy()
    {
        int num = Random.Range(0, 3);
        Vector3 EnemyPos = new Vector3();
        if(num==0)
        {
            EnemyPos = new Vector3(-10, 8, 0);
        }else if(num==1)
        {
            EnemyPos = new Vector3(0, 8, 0);
        }
        else
        {
            EnemyPos = new Vector3(10, 8, 0);
        }

        CreateItem(item[3],EnemyPos,Quaternion.identity);
    }

}
MapCreation.cs

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Born : MonoBehaviour {

    public GameObject playerPrefab;

    public GameObject[] enemyPrefabList;

    //判斷是否產生敵人
    public bool createPlay;

    // Use this for initialization
    void Start () {
        Invoke("BornTank",1f);
        Destroy(gameObject,1f);
    }

    private void Update()
    {

    }

    private void BornTank()
    {
        if (createPlay)
        {
            Instantiate(playerPrefab, transform.position, Quaternion.identity);
        }
        else
        {
            int num = Random.Range(0, 2);
            Instantiate(enemyPrefabList[num], transform.position, Quaternion.identity);
        }
    }
}
Born.cs

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Enemy : MonoBehaviour {

    //屬性值
    public float moveSpeed = 3;
    private Vector3 bullectEulerAugles;
    private float v;
    private float h;

    //引用
    private SpriteRenderer sr;
    public Sprite[] tankSprite; //上 右 下 左
    public GameObject bullectPrefab;
    public GameObject explosionPrefab;

    //計時器
    public float timeVal;
    public float timeValChangeDirection=4;

    // Use this for initialization
    void Start()
    {
        sr = GetComponent<SpriteRenderer>();
    }

    // Update is called once per frame
    void Update()
    {
        //攻擊的時間間隔
        if (timeVal >= 0.3f)
        {
            //間隔大於0.4的時候纔有攻擊效果
            Attack();
        }
        else
        {
            timeVal += Time.deltaTime;
        }
    }

    private void FixedUpdate()
    {
        Move();
    }

    //坦克的攻擊方法
    private void Attack()
    {
         //子彈參數的角度:當前坦克的角度+子彈應該旋轉的角度
         Instantiate(bullectPrefab, transform.position, Quaternion.Euler(transform.eulerAngles + bullectEulerAugles));
         timeVal = 0;
    }

    //坦克的移動方法
    private void Move()
    {

        if(timeValChangeDirection>=4)
        {
            int num = Random.Range(0,8);
            if(num>5)
            {
                v = -1;
                h = 0;
            }else if (num == 0)
            {
                v = 1;
                h = 0;
            }else if (num > 0 && num <= 2)
            {
                h = -1;
                v = 0;
            }else if (num > 2 && num <= 4)
            {
                h = 1;
                v = 0;
            }

            timeValChangeDirection = 0;
        }
        else
        {
            timeValChangeDirection += Time.fixedDeltaTime;
        }

        //監聽玩家垂直軸輸入
      
        transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);

        if (v < 0)
        {
            sr.sprite = tankSprite[2];
            bullectEulerAugles = new Vector3(0, 0, -180);
        }
        else if (v > 0)
        {
            sr.sprite = tankSprite[0];
            bullectEulerAugles = new Vector3(0, 0, 0);
        }

        if (v != 0)
        {
            return;
        }

        //監聽玩家水平軸輸入
     
        transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (h < 0)
        {
            sr.sprite = tankSprite[3];
            bullectEulerAugles = new Vector3(0, 0, 90);
        }
        else if (h > 0)
        {
            sr.sprite = tankSprite[1];
            bullectEulerAugles = new Vector3(0, 0, -90);
        }
    }

    //坦克的死亡方法
    private void Die()
    {
        //產生爆炸特效
        Instantiate(explosionPrefab, transform.position, transform.rotation);
        //死亡
        Destroy(gameObject);
    }

    //優化敵人AI
    private void OnCollisionEnter2D(Collision2D collision)
    {
        if(collision.gameObject.tag=="Enemy")
        {
            timeValChangeDirection = 4;
        }
    }

}
Enemy.cs

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Explosion : MonoBehaviour {

    // Use this for initialization
    void Start () {
        //坦克銷燬後0.167秒銷燬爆炸特效
        Destroy(gameObject,0.167f);
    }
    
    // Update is called once per frame
    void Update () {
        
    }
}
Explosion

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Heart : MonoBehaviour {

    private SpriteRenderer sr;
    public GameObject explosionPrefab;

    public Sprite BrokenSprite;   

    // Use this for initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    

    private void Die()
    {
        sr.sprite = BrokenSprite;
        Instantiate(explosionPrefab,transform.position,transform.rotation);
    }
}
Heart.cs

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Bullect : MonoBehaviour {

    public float moveSpeed = 10;

    public bool isPlayerBullect;

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        transform.Translate(transform.up*moveSpeed*Time.deltaTime,Space.World);
    }

    //子彈觸發碰撞檢測
    private void OnTriggerEnter2D(Collider2D collision)
    {
        switch(collision.tag)
        {
            case "Tank":
                if(!isPlayerBullect)
                {
                    collision.SendMessage("Die");
                    Destroy(gameObject);
                }
                break;
            case "Heart":
                collision.SendMessage("Die");
                Destroy(gameObject);
                break;
            case "Enemy":
                if(isPlayerBullect)
                {
                    collision.SendMessage("Die");
                    Destroy(gameObject);
                }
                break;
            case "Wall":
                //銷燬自身和牆
                Destroy(collision.gameObject);
                Destroy(gameObject);
                break;
            case "Barrier":
                Destroy(gameObject);
                break;
            default:
                break;
        }
    }
    

}
Bullect.cs

 

 

玩家狀態管理

 

  遊戲中添加空物體PlayerManager對象

  添加遊戲的屬性值

    public int lifeVale = 3;
    public int playerScore = 0;
    public bool isDead;

 

  坦克的死亡方法

private void Die()
    {
        if(isDefended)
        {
            return;
        }

        PlayerManager.Instance.isDead = true;

        //產生爆炸特效
        Instantiate(explosionPrefab, transform.position, transform.rotation);
        //死亡
        Destroy(gameObject);
    }

 

  玩家狀態管理類監聽玩家狀態,當玩家被子彈擊中時,生命值開始下降

void Update () {
        if(isDead)
        {
            Recover();
        }
    }

    private void Recover()
    {
        if (lifeVale < 0)
        {
            //遊戲失敗,返回主界面

            SceneManager.LoadScene("Game");
        }
        else
        {
            lifeVale--;
            GameObject go = Instantiate(born,new Vector3(-2,-8,0),Quaternion.identity);
            go.GetComponent<Born>().createPlay = true;
            isDead = false;
        }
    }

 

 

 

遊戲源代碼

 

  

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour {

    //屬性值
    public float moveSpeed = 3;
    private Vector3 bullectEulerAugles;
    public float timeVal;
    private float defendTimeVal=3;
    private bool isDefended=true;

    //引用
    private SpriteRenderer sr;
    public Sprite[] tankSprite; //上 右 下 左
    public GameObject bullectPrefab;
    public GameObject explosionPrefab;
    public GameObject defendEffectPrefab;

    // Use this for initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    
    // Update is called once per frame
    void Update () {
        //保護是否處於無敵狀態
        if(isDefended)
        {
            defendEffectPrefab.SetActive(true);
            defendTimeVal -= Time.deltaTime;
            if (defendTimeVal<=0)
            {
                isDefended = false;
                defendEffectPrefab.SetActive(false);
            }
        }

    }

    private void FixedUpdate()
    {
        if(PlayerManager.Instance.isDefeat)
        {
            return;
        }
        Move();
        //攻擊的CD
        if (timeVal >= 0.4f)
        {
            //間隔大於0.4的時候纔有攻擊效果
            Attack();
        }
        else
        {
            timeVal += Time.fixedDeltaTime;
        }
    }

    //坦克的攻擊方法
    private void Attack()
    {
        if(Input.GetKeyDown(KeyCode.Space))
        {
            //子彈參數的角度:當前坦克的角度+子彈應該旋轉的角度
            Instantiate(bullectPrefab,transform.position,Quaternion.Euler(transform.eulerAngles+bullectEulerAugles));
            timeVal = 0;
        }
    }

    //坦克的移動方法
    private void Move()
    {
        //監聽玩家垂直軸輸入
        float v = Input.GetAxisRaw("Vertical");
        transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (v < 0)
        {
            sr.sprite = tankSprite[2];
            bullectEulerAugles = new Vector3(0, 0, -180);
        }
        else if (v > 0)
        {
            sr.sprite = tankSprite[0];
            bullectEulerAugles = new Vector3(0, 0, 0);
        }

        if (v != 0)
        {
            return;
        }

        //監聽玩家水平軸輸入
        float h = Input.GetAxisRaw("Horizontal");    //返回-1 0 1
        transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (h < 0)
        {
            sr.sprite = tankSprite[3];
            bullectEulerAugles = new Vector3(0, 0, 90);
        }
        else if (h > 0)
        {
            sr.sprite = tankSprite[1];
            bullectEulerAugles = new Vector3(0, 0, -90);
        }
    }

    //坦克的死亡方法
    private void Die()
    {
        if(isDefended)
        {
            return;
        }

        PlayerManager.Instance.isDead = true;

        //產生爆炸特效
        Instantiate(explosionPrefab, transform.position, transform.rotation);
        //死亡
        Destroy(gameObject);
    }
}
Player.cs 遊戲玩家

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class PlayerManager : MonoBehaviour {

    //屬性值
    public int lifeVale = 3;
    public int playerScore = 0;
    public bool isDead=false;
    public bool isDefeat;

    //引用
    public GameObject born;

    //單例
    private static PlayerManager instance;

    public static PlayerManager Instance
    {
        get
        {
            return instance;
        }

        set
        {
            instance = value;
        }
    }

    public void Awake()
    {
        Instance = this;
    }

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        if(isDead)
        {
            Recover();
        }
    }

    private void Recover()
    {
        if (lifeVale < 0)
        {
            //遊戲失敗,返回主界面

            SceneManager.LoadScene("Game");
        }
        else
        {
            lifeVale--;
            GameObject go = Instantiate(born,new Vector3(-2,-8,0),Quaternion.identity);
            go.GetComponent<Born>().createPlay = true;
            isDead = false;
        }
    }
}
PlayerManager.cs 遊戲玩家狀態管理

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MapCreation : MonoBehaviour {

    //用來裝飾初始化地圖所需物體的數組
    //0.老家  1.牆  2.障礙  3.出生效果  4.河流    5.草  6.空氣牆
    public GameObject[] item;

    //已經有東西位置的列表
    private List<Vector3> itemPositionList = new List<Vector3>();

    private void Awake()
    {
        //實例化老家
        CreateItem(item[0], new Vector3(0, -8, -0), Quaternion.identity);
        //用牆把老家圍起來
        CreateItem(item[1], new Vector3(-1, -8, -0), Quaternion.identity);
        CreateItem(item[1], new Vector3(1, -8, -0), Quaternion.identity);
        for(int i=-1;i<2;i++)
        {
            Instantiate(item[1],new Vector3(i,-7,0),Quaternion.identity);
        }

        //坦克一開始就向下太難了,就直接給老家前面加了一頂牆
        CreateItem(item[2], new Vector3(0, -4, -0), Quaternion.identity);

        //實例化外圍牆
        for (int i=-11;i<12;i++)
        {
            CreateItem(item[6], new Vector3(i, 9, 0), Quaternion.identity);
        }
        for(int i=-11;i<12;i++)
        {
            CreateItem(item[6], new Vector3(i, -9, 0), Quaternion.identity);
        }
        for(int i=-8;i<9;i++)
        {
            CreateItem(item[6], new Vector3(-11, i, 0), Quaternion.identity);
        }
        for(int i=-8;i<9;i++)
        {
            CreateItem(item[6], new Vector3(11, i, 0), Quaternion.identity);
        }

        //初始化玩家
        GameObject go = Instantiate(item[3], new Vector3(-2, -8, 0), Quaternion.identity);
        go.GetComponent<Born>().createPlay = true;

        //產生敵人
        CreateItem(item[3], new Vector3(-10,8,0),Quaternion.identity);
        CreateItem(item[3], new Vector3(0, 8, 0), Quaternion.identity);
        CreateItem(item[3], new Vector3(10, 8, 0), Quaternion.identity);

        //第一次調用CreateEnemy用4s,每隔5s開調用
        InvokeRepeating("CreateEnemy",4,5);

        //實例化地圖
        for (int i=0;i<60;i++)
        {
            CreateItem(item[1], CreateRamdomPosition(), Quaternion.identity);
        }
        for(int i=0;i<20;i++)
        {
            CreateItem(item[2], CreateRamdomPosition(), Quaternion.identity);
        }
        for (int i = 0; i < 20; i++)
        {
            CreateItem(item[4], CreateRamdomPosition(), Quaternion.identity);
        }
        for (int i = 0; i < 20; i++)
        {
            CreateItem(item[5], CreateRamdomPosition(), Quaternion.identity);
        }
    }

 

    private void CreateItem(GameObject createGameObject,Vector3 createPosition,Quaternion createRotate)
    {
        GameObject itemGo = Instantiate(createGameObject, createPosition, createRotate);
        itemGo.transform.SetParent(gameObject.transform);
        itemPositionList.Add(createPosition);
    }

    //產生隨機位置的方法
    private Vector3 CreateRamdomPosition()
    {
        //不生成x=-10,10的兩列,y=-8和8這兩行的位置
        while(true)
        {
            Vector3 createPosition = new Vector3(Random.Range(-9, 10), Random.Range(-7, 8),0);
            if(!HasThePosition(createPosition))
            {
                return createPosition;
            }
          
        }
    }

    //用來判斷位置列表中是否有這個位置
    private bool HasThePosition(Vector3 createPos)
    {
        for(int i=0;i<itemPositionList.Count;i++)
        {
            if(createPos==itemPositionList[i])
            {
                return true;
            }
        }
        return false;
    }

    //產生敵人的方法
    private void CreateEnemy()
    {
        int num = Random.Range(0, 3);
        Vector3 EnemyPos = new Vector3();
        if(num==0)
        {
            EnemyPos = new Vector3(-10, 8, 0);
        }else if(num==1)
        {
            EnemyPos = new Vector3(0, 8, 0);
        }
        else
        {
            EnemyPos = new Vector3(10, 8, 0);
        }

        CreateItem(item[3],EnemyPos,Quaternion.identity);
    }

}
MapCreation.cs 初始化地圖

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Born : MonoBehaviour {

    public GameObject playerPrefab;

    public GameObject[] enemyPrefabList;

    //判斷是否產生敵人
    public bool createPlay;

    // Use this for initialization
    void Start () {
        Invoke("BornTank",1f);
        Destroy(gameObject,1f);
    }

    private void Update()
    {

    }

    private void BornTank()
    {
        if (createPlay)
        {
            Instantiate(playerPrefab, transform.position, Quaternion.identity);
        }
        else
        {
            int num = Random.Range(0, 2);
            Instantiate(enemyPrefabList[num], transform.position, Quaternion.identity);
        }
    }
}
Born.cs 玩家敵人坦克出生

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Enemy : MonoBehaviour {

    //屬性值
    public float moveSpeed = 3;
    private Vector3 bullectEulerAugles;
    private float v=-1;
    private float h;

    //引用
    private SpriteRenderer sr;
    public Sprite[] tankSprite; //上 右 下 左
    public GameObject bullectPrefab;
    public GameObject explosionPrefab;

    //計時器
    public float timeVal;
    public float timeValChangeDirection=0;

    // Use this for initialization
    void Start()
    {
        sr = GetComponent<SpriteRenderer>();
    }

    // Update is called once per frame
    void Update()
    {
        //攻擊的時間間隔
        if (timeVal >= 0.3f)
        {
            //間隔大於0.4的時候纔有攻擊效果
            Attack();
        }
        else
        {
            timeVal += Time.deltaTime;
        }
    }

    private void FixedUpdate()
    {
        Move();
    }

    //坦克的攻擊方法
    private void Attack()
    {
         //子彈參數的角度:當前坦克的角度+子彈應該旋轉的角度
         Instantiate(bullectPrefab, transform.position, Quaternion.Euler(transform.eulerAngles + bullectEulerAugles));
         timeVal = 0;
    }

    //坦克的移動方法
    private void Move()
    {

        if(timeValChangeDirection>=4)
        {
            int num = Random.Range(0,8);
            if(num>5)
            {
                v = -1;
                h = 0;
            }else if (num == 0)
            {
                v = 1;
                h = 0;
            }else if (num > 0 && num <= 2)
            {
                h = -1;
                v = 0;
            }else if (num > 2 && num <= 4)
            {
                h = 1;
                v = 0;
            }

            timeValChangeDirection = 0;
        }
        else
        {
            timeValChangeDirection += Time.fixedDeltaTime;
        }

        //監聽玩家垂直軸輸入
      
        transform.Translate(Vector3.up * v * moveSpeed * Time.fixedDeltaTime, Space.World);

        if (v < 0)
        {
            sr.sprite = tankSprite[2];
            bullectEulerAugles = new Vector3(0, 0, -180);
        }
        else if (v > 0)
        {
            sr.sprite = tankSprite[0];
            bullectEulerAugles = new Vector3(0, 0, 0);
        }

        if (v != 0)
        {
            return;
        }

        //監聽玩家水平軸輸入
     
        transform.Translate(Vector3.right * h * moveSpeed * Time.fixedDeltaTime, Space.World);
        if (h < 0)
        {
            sr.sprite = tankSprite[3];
            bullectEulerAugles = new Vector3(0, 0, 90);
        }
        else if (h > 0)
        {
            sr.sprite = tankSprite[1];
            bullectEulerAugles = new Vector3(0, 0, -90);
        }
    }

    //坦克的死亡方法
    private void Die()
    {
        PlayerManager.Instance.playerScore++;
        //產生爆炸特效
        Instantiate(explosionPrefab, transform.position, transform.rotation);
        //死亡
        Destroy(gameObject);
    }

    //優化敵人AI
    private void OnCollisionEnter2D(Collision2D collision)
    {
        if(collision.gameObject.tag=="Enemy")
        {
            timeValChangeDirection = 4;
        }
    }

}
Enemy.cs 敵人坦克

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Explosion : MonoBehaviour {

    // Use this for initialization
    void Start () {
        //坦克銷燬後0.167秒銷燬爆炸特效
        Destroy(gameObject,0.167f);
    }
    
    // Update is called once per frame
    void Update () {
        
    }
}
Explosion.cs 遊戲銷燬特效

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Heart : MonoBehaviour {

    private SpriteRenderer sr;
    public GameObject explosionPrefab;

    public Sprite BrokenSprite;   

    // Use this for initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    

    private void Die()
    {
        sr.sprite = BrokenSprite;
        Instantiate(explosionPrefab,transform.position,transform.rotation);
        PlayerManager.Instance.isDefeat = true;
    }
}
Heart.cs 心臟

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class Bullect : MonoBehaviour {

    public float moveSpeed = 10;

    public bool isPlayerBullect;

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        transform.Translate(transform.up*moveSpeed*Time.deltaTime,Space.World);
    }

    //子彈觸發碰撞檢測
    private void OnTriggerEnter2D(Collider2D collision)
    {
        switch(collision.tag)
        {
            case "Tank":
                if(!isPlayerBullect)
                {
                    collision.SendMessage("Die");

                    Destroy(gameObject);
                }
                break;
            case "Heart":
                collision.SendMessage("Die");
                Destroy(gameObject);
                SceneManager.LoadScene("Game");
                break;
            case "Enemy":
                if(isPlayerBullect)
                {
                    collision.SendMessage("Die");
                    Destroy(gameObject);
                }
                break;
            case "Wall":
                //銷燬自身和牆
                Destroy(collision.gameObject);
                Destroy(gameObject);
                break;
            case "Barrier":
                Destroy(gameObject);
                break;
            default:
                break;
        }
    }
    

}
Bullect.cs 子彈
相關文章
相關標籤/搜索