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 }
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 }
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 }
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 }