unity3d之貪吃蛇
阿新 • • 發佈:2018-11-10
臨時興起,寫一個貪吃蛇教程吧。
本來覺得會很好寫,結果寫了整整一下午,還是自己程式碼寫的太少,操作起來不靈活,思路會短路。
廢話不多說。先上圖:
邏輯很簡單,但自己本來在明確思路的情況下卻在寫程式碼時走了彎路,核心部分是蛇吃了綠色的食物後,變長。
我的方法是儲存蛇的最後一節身體位置,每次新增新的長度到末尾。
這裡要注意的是採取,從尾至頭的方式移動蛇前進,而不是通常我們理解的從頭至尾。目的就是方便操作同時到達蛇形蜿蜒的效果。
下面是主題程式碼:
using UnityEngine; using System.Collections; public class GameManager : MonoBehaviour { private const int height = 14; private const int width = 14; private Vector2 origin = new Vector2(-1.84f,-1.25f); private const float moveUnit = 0.28f; private bool[,] Meshs = new bool[height,width]; private GameObject[] snakeArray = new GameObject[100]; private GameObject head; private GameObject food = null; private Vector2[] snakePositions = new Vector2[100]; public GameObject[] snakeHead = new GameObject[4]; public GameObject snakeBody; public GameObject food_prefab; public Animator gameover; private int direction; private int head_direction; private int snakeIndex=0; public static bool IsGameOn; // Use this for initialization void Start () { InitGame (); } // Update is called once per frame void Update () { if(Input.GetKeyDown(KeyCode.LeftArrow)){ direction = 0; SnakeMove(); } if(Input.GetKeyDown(KeyCode.RightArrow)){ direction = 1; SnakeMove(); } if(Input.GetKeyDown(KeyCode.UpArrow)){ direction = 2; SnakeMove(); } if(Input.GetKeyDown(KeyCode.DownArrow)){ direction = 3; SnakeMove(); } } private void InitGame(){ IsGameOn = true; for (int k=0; k<100; k++) snakeArray [k] = null; for (int k=0; k<100; k++) snakePositions [k] = Vector2.zero; int i = Random.Range (0,4);//0,1,2,3 represents Left,Right,Up and Down head_direction = i; direction=head_direction; Vector2 originalPosition = new Vector2 (origin.x+moveUnit*7,origin.y+moveUnit*7); snakePositions [0] = new Vector2 (7, 7);//head's axis value head = (GameObject)Instantiate (snakeHead[i],originalPosition,Quaternion.identity); snakeArray [0] = head; SnakeMove (); GenerateFood (); } private void SnakeBodyMove(){ snakePositions[99] = snakePositions[snakeIndex]; for (int i=snakeIndex; i>0; i--) { if(snakePositions[i]!=Vector2.zero){ snakePositions[i] = snakePositions[i-1]; if(snakeArray[i]!=null){ snakeArray[i].transform.position = new Vector2(origin.x + moveUnit *snakePositions[i-1].x,origin.y + moveUnit *snakePositions[i-1].y); } } } } private void SnakeMove(){ CancelInvoke ("SnakeMove"); if (!IsGameOn) return; SnakeBodyMove(); switch(direction){ case 0: //Debug.Log("0position"+snakePositions[99]); checkSnakeHead(); head.transform.Translate(-moveUnit,0,0); snakePositions[0].x--; Invoke("SnakeMove",0.5f); break; case 1: checkSnakeHead(); head.transform.Translate(moveUnit,0,0); //snakePositions[99].x++; snakePositions[0].x++; Invoke("SnakeMove",0.5f); break; case 2: checkSnakeHead(); head.transform.Translate(0,moveUnit,0); //snakePositions[99].y++; snakePositions[0].y++; Invoke("SnakeMove",0.5f); break; case 3: checkSnakeHead(); head.transform.Translate(0,-moveUnit,0); //snakePositions[99].y--; snakePositions[0].y--; Invoke("SnakeMove",0.5f); break; default: break; } if(snakePositions[0].x<0||snakePositions[0].x>13||snakePositions[0].y<0||snakePositions[0].y>13){ IsGameOn=false; gameover.enabled = true; } } private void checkSnakeHead(){ if(direction!=head_direction){ head_direction = direction; GameObject tmp = head; head = (GameObject)Instantiate (snakeHead[head_direction],head.transform.position,Quaternion.identity); snakeArray[0] = head; Destroy(tmp.gameObject); } } public void GenerateFood(){ int i = Random.Range (0,14); int j = Random.Range (0,14); GameObject tmp = food; food = (GameObject)Instantiate (food_prefab,new Vector2(origin.x+moveUnit*j,origin.y+moveUnit*i),Quaternion.identity); if(tmp!= null) Destroy (tmp.gameObject); } public void SnakeGrow(){ snakeIndex++; Vector2 endPosition = new Vector2 (origin.x + moveUnit * snakePositions[99].x, origin.y + moveUnit * snakePositions[99].y); snakeArray[snakeIndex] =(GameObject)Instantiate (snakeBody,endPosition,Quaternion.identity); snakePositions [snakeIndex] = snakePositions [99]; } }