Unity初级案例——贪吃蛇

时间:2022-06-09 03:09:10

Unity初级案例——贪吃蛇

Unity初级案例——贪吃蛇

Unity初级案例——贪吃蛇Unity初级案例——贪吃蛇
  1 using System.Collections;
  2 using System.Collections.Generic;
  3 using UnityEngine;
  4 using UnityEngine.UI;
  5 
  6 public class MainUIControl : MonoBehaviour {
  7 
  8     private static MainUIControl _instance;
  9 
 10     public static MainUIControl instance
 11     {
 12         get
 13         {
 14             return _instance;
 15         }
 16     }
 17     public int score = 0;
 18     public int length = 0;
 19     public Text phaseText;
 20     public Text scoreText;
 21     public Text lengthText;
 22     public Image bgImage;    //背景颜色
 23     public Image pauseImage;    
 24     public Sprite[] pauseSprite;    //暂停图标的icon
 25     private Color tempColor;
 26     public bool isPause=false;      //暂停
 27     public bool isLimit = true;     //边界模式
 28 
 29     void Awake()
 30     {
 31         _instance = this;
 32     }
 33 
 34     //启动边界设置判断
 35      void Start()
 36     {
 37         if(PlayerPrefs.GetInt("limit",1)==0)
 38         {
 39             isLimit = false;
 40             //遍历bgImage下的子物体
 41             foreach(Transform t in bgImage.gameObject.transform)
 42             {
 43                 t.gameObject.GetComponent<Image>().enabled = false;
 44             }
 45         }
 46     }
 47 
 48     private void Update()
 49     {
 50         switch(score/100)
 51         {
 52             case 0:
 53             case 1:
 54                 bgImage.color = bgImage.color;
 55                 phaseText.text = "阶段1";
 56                 break;
 57             case 2:
 58                 //把Html里颜色的十六进制值解析
 59                 ColorUtility.TryParseHtmlString("#CCFFDBFF", out tempColor);
 60                 bgImage.color = tempColor;
 61                 phaseText.text = "阶段2";
 62                 break;
 63             case 3:
 64                 ColorUtility.TryParseHtmlString("#EBFFCCFF", out tempColor);
 65                 bgImage.color = tempColor;
 66                 phaseText.text = "阶段3";
 67                 break;
 68             case 4:
 69                 ColorUtility.TryParseHtmlString("#FFF3CCFF", out tempColor);
 70                 bgImage.color = tempColor;
 71                 phaseText.text = "阶段4";
 72                 break;
 73             default:
 74                 ColorUtility.TryParseHtmlString("#FFDACCFF", out tempColor);
 75                 bgImage.color = tempColor;
 76                 phaseText.text = "无尽模式";
 77                 break;
 78         }
 79     }
 80 
 81     
 82     // UI更新
 83     public void UpdateUI(int s=5,int l=1)
 84     {
 85         score += s;
 86         length += l;
 87         scoreText.text = "得分:\n" + score;
 88         lengthText.text = "长度:\n" + length;
 89     }
 90 
 91     //暂停
 92     /*
 93       Edit -> Project Settings -> Input -> Submit -> Alt Positive Button
 94       把spce去掉,否则摁下Space和Enter会导致按键冲突
 95     */
 96     public void Pause()
 97     {
 98         isPause = !isPause;     //状态取反
 99         if(isPause)
100         {
101             Time.timeScale = 0;
102             pauseImage.GetComponent<Image>().sprite = pauseSprite[1];
103         }
104        else
105         {
106             Time.timeScale = 1;
107             pauseImage.GetComponent<Image>().sprite = pauseSprite[0];
108         }
109     }
110 
111     //回到开始界面(需把此方法绑定到Home按钮的Button组件上)
112     //先把两个场景放入File -> Build Settings
113     public void Home()
114     {
115         //加载index[0]的场景(开始界面)
116         UnityEngine.SceneManagement.SceneManager.LoadScene(0);
117         //这里有个bug,摁下Home按钮回到主界面后,虽然勾选的是“边界模式”但是点“开始”后还是*模式
118         //一定要再次点击边界模式后才会正常
119         //因此这里设置为摁Home返回后默认选择界限模式
120         StartUIControl limit = new StartUIControl();
121         limit.LimitMode(true);
122     }
123 }
MainUIControl
Unity初级案例——贪吃蛇Unity初级案例——贪吃蛇
 1 using System.Collections;
 2 using System.Collections.Generic;
 3 using UnityEngine;
 4 using UnityEngine.UI;
 5 
 6 public class StartUIControl : MonoBehaviour
 7 {
 8     public Text lastText;           //上一次分数
 9     public Text bestText;           //最好分数
10     public Toggle blueToggle;       //蓝色蛇
11     public Toggle yellowToggle;     //黄色蛇
12     public Toggle limitToggle;      //边界模式
13     public Toggle freeToggle;       //*模式
14 
15     //在开始界面显示保存的成绩
16     void Awake()
17     {
18         lastText.text = "上次:长度" + PlayerPrefs.GetInt("lastl", 0) + ",分数" + PlayerPrefs.GetInt("lasts", 0);
19         bestText.text = "最好:长度" + PlayerPrefs.GetInt("bestl", 0) + ",分数" + PlayerPrefs.GetInt("bests", 0);
20     }
21 
22     //开始时选择
23     private void Start()
24     {
25         if(PlayerPrefs.GetString("sh","sh01")=="sh01")
26         {
27             BlueSnake(true);
28         }
29         else
30         {
31             YellowSnake(true);
32         }
33         if(PlayerPrefs.GetInt("limit",1)==1)
34         {
35             LimitMode(true);
36         }
37         else
38         {
39             FreeMode(true);
40         }
41     }
42 
43     //选择蓝色蛇
44     public void BlueSnake(bool isOn)
45     {
46         if(isOn)
47         {
48             PlayerPrefs.SetString("sh", "sh01");
49             PlayerPrefs.SetString("sb01", "sb0101");
50             PlayerPrefs.SetString("sb02", "sb0102");
51         }
52     }
53     //选择黄色蛇
54     public void YellowSnake(bool isOn)
55     {
56         if (isOn)
57         {
58             PlayerPrefs.SetString("sh", "sh02");
59             PlayerPrefs.SetString("sb01", "sb0201");
60             PlayerPrefs.SetString("sb02", "sb0202");
61         }
62     }
63     //边界模式
64     public void LimitMode(bool isOn)
65     {
66         if(isOn)
67         {
68             PlayerPrefs.SetInt("limit", 1);
69             PlayerPrefs.SetInt("free", 0);
70         }
71     }
72 
73     //*模式
74     public void FreeMode(bool isOn)
75     {
76         if (isOn)
77         {
78             PlayerPrefs.SetInt("free", 1);
79             PlayerPrefs.SetInt("limit", 0);
80         }
81     }
82 
83     //加载游戏场景(需把此方法绑定到Start按钮的Button组件上)
84     public void StartGame()
85     {
86         UnityEngine.SceneManagement.SceneManager.LoadScene(1);
87     }
88 }
StartUIControl
Unity初级案例——贪吃蛇Unity初级案例——贪吃蛇
  1 using System.Collections;
  2 using System.Collections.Generic;
  3 using UnityEngine;
  4 using UnityEngine.UI;
  5 //using System.Linq;      //List.Last()
  6 
  7 public class SnakeHead : MonoBehaviour
  8 {
  9     public List<Transform> bodyList = new List<Transform>();        //蛇身
 10     public float Speed=0.2f;
 11     public int step = 10;        //移动步长
 12     private int x;          //x,y是移动增量值
 13     private int y;
 14     private Vector3 shPos;
 15     private bool isDie = false;
 16 
 17     public AudioClip dieClip;       //死亡声音
 18     public AudioClip eatClip;       //吃食物声音
 19     public GameObject dieEffect;
 20     public Transform canvas;        //存放蛇身prefabs
 21     public GameObject bodyPrefab;
 22     public Sprite[] bodySprites = new Sprite[2];        //蛇身颜色奇偶
 23 
 24     private void Awake()
 25     {
 26         canvas = GameObject.Find("Canvas").transform;
 27         //在Project项目下创建Rescoures(一定不能拼错)文件夹然后把所需素材放进去
 28         //通过Rescources.Load(string path)方法加载此文件夹下的资源
 29         //由于这里是放在根目录所以不需要加Rescource/及文件扩展名
 30         //把黄色图片赋给蛇头
 31         gameObject.GetComponent<Image>().sprite= Resources.Load<Sprite>(PlayerPrefs.GetString("sh","sh02"));
 32         //把图片赋给蛇身
 33         bodySprites[0] = Resources.Load<Sprite>(PlayerPrefs.GetString("sb01", "sb0201"));
 34         bodySprites[1] = Resources.Load<Sprite>(PlayerPrefs.GetString("sb02", "sb0202"));
 35     }
 36 
 37     private void Start()
 38     {
 39         //重复调用Move方法,通过更改Speed来实现移动速度的变化
 40         InvokeRepeating("Move", 0, Speed);
 41         //开始时,蛇先往上走
 42         x = 0;
 43         y = step;
 44     }
 45 
 46     //上下左右移动,空格加速
 47     private void Update()
 48     {
 49         //暂停时不能控制
 50         //死亡时不能控制
 51         //空格键控制加速
 52         if(Input.GetKeyDown(KeyCode.Space)&&MainUIControl.instance.isPause==false && isDie == false)
 53         {
 54             CancelInvoke();
 55             InvokeRepeating("Move", 0, Speed/2f);
 56         }
 57 
 58         if (Input.GetKeyUp(KeyCode.Space) && MainUIControl.instance.isPause == false && isDie == false)
 59         {
 60             CancelInvoke();
 61             InvokeRepeating("Move", 0, Speed);
 62         }
 63 
 64 
 65         //禁止直接反向移动
 66         if (Input.GetKey(KeyCode.W) && y!=-step && MainUIControl.instance.isPause == false && isDie == false) 
 67         {
 68             
 69             gameObject.transform.localRotation = Quaternion.Euler(0, 0, 0);     //蛇头角度
 70             x = 0;
 71             y = step;
 72         }
 73 
 74         if (Input.GetKey(KeyCode.S) && y != step && MainUIControl.instance.isPause == false && isDie == false) 
 75         {
 76             gameObject.transform.localRotation = Quaternion.Euler(0, 0, 180);
 77             x = 0;
 78             y = -step;
 79         }
 80 
 81         if (Input.GetKey(KeyCode.A) && x != step && MainUIControl.instance.isPause == false && isDie == false) 
 82         {
 83             gameObject.transform.localRotation = Quaternion.Euler(0, 0, 90);
 84             x = -step;
 85             y = 0;
 86         }
 87 
 88         if (Input.GetKey(KeyCode.D) && x != -step && MainUIControl.instance.isPause == false && isDie == false) 
 89         {
 90             gameObject.transform.localRotation = Quaternion.Euler(0, 0, -90);
 91             x = step;
 92             y = 0;
 93         }
 94 
 95         
 96     }
 97 
 98     //蛇身生成
 99     void Grow()
100     {
101         //这里设置为零点播放,实际效果和Camera位置有关【MainCamera(0,0,-10)】(因为AudioListener组件挂在摄像机上)
102         AudioSource.PlayClipAtPoint(eatClip, Vector3.zero);     //播放吃食物声音
103         int index = (bodyList.Count % 2 == 0) ? 0 : 1;     //判断蛇身颜色奇偶
104         //此处设置坐标后prefab还是按照其本身的坐标生成,并不会改变,原因未知
105         //所以只能直接改动prefab的坐标
106         GameObject body = Instantiate(bodyPrefab,canvas); //生成在屏幕外
107         body.GetComponent<Image>().sprite = bodySprites[index];
108         body.transform.SetParent(canvas,false);
109         bodyList.Add(body.transform);
110         
111        
112     }
113 
114     //蛇头以及蛇身节点的移动
115     void Move()
116     {
117         shPos =  gameObject.transform.localPosition;
118         //Ugui本身的canvas的scale有一个缩放值,用position会是它的实际坐标,因此用localposition获得子类物体的本地坐标
119         gameObject.transform.localPosition = new Vector3(shPos.x + x, shPos.y + y, shPos.z);
120 
121         //方法一:把蛇身最后一个元素插入到蛇头位置
122         /*
123          if(bodyList.Count>0)
124         {
125             bodyList.Last().localPosition = shPos;
126             bodyList.Insert(0, bodyList.Last());
127             bodyList.RemoveAt(bodyList.Count - 1);
128         }
129        */
130 
131         //方法二:从后往前,移动到上一个节点
132         
133         for (int i=bodyList.Count-1;i>=1;i--)
134         {
135             bodyList[i].localPosition = bodyList[i - 1].localPosition;
136         }
137         bodyList[0].localPosition = shPos;
138     }
139 
140     //死亡
141     void Die()
142     {
143         AudioSource.PlayClipAtPoint(dieClip,new Vector3(0,0,-10));     //播放死亡声音
144         CancelInvoke();
145         isDie = true;
146         Instantiate(dieEffect);
147         //记录死亡时的长度与分数,键&值
148         PlayerPrefs.SetInt("lastl", MainUIControl.instance.length);
149         PlayerPrefs.SetInt("lasts", MainUIControl.instance.score);
150         //记录最高分
151         if(PlayerPrefs.GetInt("bests",0)<MainUIControl.instance.score)
152         {
153             PlayerPrefs.SetInt("bestl", MainUIControl.instance.length);
154             PlayerPrefs.SetInt("bests", MainUIControl.instance.score);
155         }
156         StartCoroutine(GameOver(2));    //调用协程,2秒后重开
157     }
158 
159     //协程
160     //等待t秒后重开场景
161     IEnumerator GameOver(float t)
162     {
163         yield return new WaitForSeconds(t);
164         UnityEngine.SceneManagement.SceneManager.LoadScene(1);      //重新加载场景
165     }
166 
167     //食物生成与销毁
168     //蛇身碰撞
169     private void OnTriggerEnter2D(Collider2D collision)
170     {
171         //食物
172         //也可以写成collision.gameObject.CompareTag("Food")
173         if(collision.tag=="Food")
174         {
175             Destroy(collision.gameObject);
176             MainUIControl.instance.UpdateUI();      //加分
177             Grow();
178             //控制奖励随机生成
179             SpawnFood.instance.MakeFood((Random.Range(0, 100) < 20)?true:false);
180         }
181 
182         //碰到蛇身死
183         else if(collision.tag=="Body")
184         {
185             Die();
186         }
187 
188         //奖励
189         else if(collision.tag=="Reward")
190         {
191             Destroy(collision.gameObject);
192             MainUIControl.instance.UpdateUI(Random.Range(5,15)*10);     //随机加分
193             Grow();
194         }
195 
196        // */边界 模式
197         else
198         {
199             //出框传送
200             if (MainUIControl.instance.isLimit)
201             {
202                 Die();
203             }
204             else
205             {
206                 //偏移量根据实际界面大小来设置
207                 switch (collision.name)
208                 {
209                     case "Up":
210                         transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y + 17, transform.localPosition.z);
211                         break;
212                     case "Down":
213                         transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y - 17, transform.localPosition.z);
214                         break;
215                     case "Left":
216                         transform.localPosition = new Vector3(-transform.localPosition.x + 125, transform.localPosition.y, transform.localPosition.z);
217                         break;
218                     case "Right":
219                         transform.localPosition = new Vector3(-transform.localPosition.x + 155, transform.localPosition.y, transform.localPosition.z);
220                         break;
221 
222                 }
223             }
224         }
225 
226     }
227 }
SnakeHead
Unity初级案例——贪吃蛇Unity初级案例——贪吃蛇
 1 using System.Collections;
 2 using System.Collections.Generic;
 3 using UnityEngine;
 4 using UnityEngine.UI;
 5 
 6 public class SpawnFood : MonoBehaviour
 7 {
 8     //static静态类可通过类名直接访问,无需再实例化对象
 9     private static SpawnFood _instance;
10 
11     public static SpawnFood instance
12     {
13         get
14         {
15             return _instance;
16         }
17     }
18 
19      void Awake()
20     {
21         _instance = this;
22     }
23     public int yLimit = 5;
24     public int xLimit = 11;
25     public int xOffSet = 6;
26     public GameObject rewardPrefab;
27     public GameObject foodPrefab;
28     public Sprite[] foodSprites;        //食物icon
29     private Transform foodContain;
30 
31     private void Start()
32     {
33         foodContain = GameObject.Find("FoodContain").transform;
34         MakeFood(false);
35     }
36 
37     //生成食物
38     public void MakeFood(bool isReward)
39     {
40         int index = Random.Range(0, foodSprites.Length);
41         GameObject food = Instantiate(foodPrefab);
42         food.GetComponent<Image>().sprite = foodSprites[index];     //赋予icon
43         food.transform.SetParent(foodContain,false);
44         int x = Random.Range(-xLimit + xOffSet, xLimit);
45         int y = Random.Range(-yLimit, yLimit);
46         food.transform.localPosition = new Vector3(x*25, y*25, 0);
47         
48         //生成奖励
49         if (isReward)
50         {
51             GameObject reward = Instantiate(rewardPrefab);
52             reward.transform.SetParent(foodContain, false);
53             x = Random.Range(-xLimit + xOffSet, xLimit);
54             y = Random.Range(-yLimit, yLimit);
55             reward.transform.localPosition = new Vector3(x * 25, y * 25, 0);
56         }
57     }
58 
59 
60 }
SpawnFood