Unity貪吃蛇遊戲演算法研究_程式碼的設計構思_活用Tag做碰撞觸發
貪吃蛇遊戲規則:
一個蛇頭上下左右移動
碰到食物就多增加一節身體(碰撞偵測)--->RigidBody
碰到牆壁就GameOver
結果影片
控制Snake 頭部的 程式腳本
HeadController.cs
使用到的 物理公式定理
速度 = 位移 / 時間 (m/s)
---> 時間(s) = 位移(m) / 速度(m/s)
_Timer >= (1f/speed)
添加於身體Prefab
Body.cs
一個蛇頭上下左右移動
碰到食物就多增加一節身體(碰撞偵測)--->RigidBody
碰到牆壁就GameOver
結果影片
控制Snake 頭部的 程式腳本
HeadController.cs
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | using UnityEngine; using System.Collections; public enum SnakeHeadDirection{ Up, Down, Left, Right, } public class HeadController : MonoBehaviour { public GameObject foodPrefab; public GameObject bodyPrefab; //第一節身體的參考引用 private Body _FirstBody; //最後一節身體之參考引用 private Body _LastBody; //Step1.先定義速度 public float speed;//移動之速 (m/s) private float _Timer = 0f; private SnakeHeadDirection _CurrentDir = SnakeHeadDirection.Up;//預設朝上 private SnakeHeadDirection _NextDir = SnakeHeadDirection.Up;//下一步移動方向 private bool _IsOver = false; //Step3.食物生成 /// <summary> /// Creates the food. /// </summary> public void CreateFood(){ //食物隨機位置生成 float x = Random.Range(-9.5f,9.5f); float z = Random.Range(-9.5f,9.5f); GameObject obj = Instantiate (foodPrefab,new Vector3(x,0f,z),Quaternion.identity) as GameObject; } /// <summary> /// Raises the trigger enter event. /// </summary> /// <param name="other">Other.</param> public void OnTriggerEnter(Collider other){ //若碰到邊界 遊戲結束 if (other.tag.Equals ("Bound")) { _IsOver = true; } //若碰到食物 ,將該食物除去 ,蛇身體增加一節 if (other.tag.Equals ("Food")) { Destroy (other.gameObject); Grow (); CreateFood (); } } //身體增長一節 private void Grow(){ //先故意生成再螢幕看不到的位置 , 等觸碰到有食物Tag的物件 再位移 GameObject obj = Instantiate (bodyPrefab, new Vector3 (1000f,1000f,1000f), Quaternion.identity) as GameObject; Body b = obj.GetComponent<Body> ();//取得身體 prefab上的腳本 // 如果頭部後面還未有身體 if(_FirstBody == null){ _FirstBody = b;//目前所生出的身體就是第一節身體部分 } //若有最後一節身體 if (_LastBody != null) { _LastBody.next = b;//就將新創見的身體掛後頭 } _LastBody = b;//更新最後一節身體部分 } void Start(){ //遊戲一開始就生成食物 CreateFood (); } // Update is called once per frame void Update () { //只要遊戲還未結束 , 就繼續執行更新遊戲循環 if (!_IsOver) { Turn (); Move (); } } //Step2.每隔一段時間往前移動一個單位 /// <summary> /// Move this instance. /// </summary> private void Move() { _Timer += Time.deltaTime; //判定當前的frame是否該移動 if(_Timer >= (1f/speed)) { //讓蛇轉彎 switch(_NextDir){ case SnakeHeadDirection.Up: transform.forward = Vector3.forward; _CurrentDir = SnakeHeadDirection.Up; break; case SnakeHeadDirection.Down: transform.forward = Vector3.back; _CurrentDir = SnakeHeadDirection.Down; break; case SnakeHeadDirection.Left: transform.forward = Vector3.left; _CurrentDir = SnakeHeadDirection.Left; break; case SnakeHeadDirection.Right: transform.forward = Vector3.right; _CurrentDir = SnakeHeadDirection.Right; break; } //紀錄頭部移動之前的位置 Vector3 nextPos = transform.position; transform.Translate (Vector3.forward);//每frame都會移動一單位 _Timer = 0f;//Reset 計時器 //如果有身體子部分 就讓它移動 if(_FirstBody != null){ //讓第一節身體移動 _FirstBody.Move (nextPos); } } } /// <summary> /// Turn this instance. /// </summary> private void Turn() { //在PC端先實踐 以鍵盤作為Input的移動 if (Input.GetKey (KeyCode.W)) {//上 _NextDir = SnakeHeadDirection.Up; //判斷按鈕是否生效 if (_CurrentDir == SnakeHeadDirection.Down) {//若按下之鍵盤值無效就修正 _NextDir = _CurrentDir; } } if (Input.GetKey (KeyCode.S)) {//下 _NextDir = SnakeHeadDirection.Down; //判斷按鈕是否生效 if (_CurrentDir == SnakeHeadDirection.Up) {//若按下之鍵盤值無效就修正 _NextDir = _CurrentDir; } } if (Input.GetKey (KeyCode.A)) {//左 _NextDir = SnakeHeadDirection.Left; //判斷按鈕是否生效 if (_CurrentDir == SnakeHeadDirection.Right) {//若按下之鍵盤值無效就修正 _NextDir = _CurrentDir; } } if (Input.GetKey (KeyCode.D)) {//右 _NextDir = SnakeHeadDirection.Right; //判斷按鈕是否生效 if (_CurrentDir == SnakeHeadDirection.Left) {//若按下之鍵盤值無效就修正 _NextDir = _CurrentDir; } } } } |
使用到的 物理公式定理
速度 = 位移 / 時間 (m/s)
---> 時間(s) = 位移(m) / 速度(m/s)
_Timer >= (1f/speed)
添加於身體Prefab
Body.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | using UnityEngine; using System.Collections; public class Body : MonoBehaviour { public Body next;//身體的參考引用 //促使我們目前的身體跟著前一個移動 public void Move(Vector3 pos) { //紀錄移動前之位置 Vector3 nextPos = transform.position; //先位移 transform.position = pos;//移動目前身體 //再檢查後面還有沒有身體 if (next != null) {//若後面還跟著有身體 next.Move (nextPos);//讓身體下一節移動 } } } |
留言
張貼留言