1. 程式人生 > >unity3d之貪吃蛇

unity3d之貪吃蛇



臨時興起,寫一個貪吃蛇教程吧。

本來覺得會很好寫,結果寫了整整一下午,還是自己程式碼寫的太少,操作起來不靈活,思路會短路。

廢話不多說。先上圖:

邏輯很簡單,但自己本來在明確思路的情況下卻在寫程式碼時走了彎路,核心部分是蛇吃了綠色的食物後,變長。

我的方法是儲存蛇的最後一節身體位置,每次新增新的長度到末尾。

這裡要注意的是採取,從尾至頭的方式移動蛇前進,而不是通常我們理解的從頭至尾。目的就是方便操作同時到達蛇形蜿蜒的效果。

下面是主題程式碼:

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


	}