Big and small greedy snakes
游戏概述
游戏亮点
通过对称的美感,设置两条贪吃蛇吧,其中一条加倍成长以及加倍减少,另一条正常成长以及减少,最终实现两条蛇对整个界面的霸占效果。
过程中不断记录两条蛇的得分情况,以及吃到毒药的记录,所谓一朝被蛇咬,十年怕井绳。
游戏运行的硬件环境
1.运行平台:PC端
2.相关软件:Unity5.4.0f3 2D
3.硬件设备:配置Windows10的笔记本电脑及相关基本设备
游戏的玩法
1.通过鼠标点击加载,登录,键盘输入账号和密码
2.进入游戏,通过上下左右键,进行移动
3.过程中有两条蛇,通过对称的美感,设置两条贪吃蛇,其中一条加倍成长以及加倍减少,另一条正常成长以及减少,最终实现两条蛇对整个界面的霸占效果。
4.过程中不断记录两条蛇的得分情况,以及吃到毒药的记录,所谓一朝被蛇咬,十年怕井绳。最终得分高的胜利。其中毒药有-2以及-1设置,食物有+2以及+1设置。
5.如果失败,那么就进入game over 界面,然后可以选择重新开始,或者关闭程序。重新开始就重新进入游戏,再次失败就往复循环。
场景布置
LOGO开场 界面
设置Canvas Scaler
1.UI Scale Mode
设置为scale with screen size
2.Reference Resolution
调整X为1920,Y为1080
3.Match
修改为1
这个部分主要是调适图片的标准

登录界面
设置UI,Canvas,其中的text以及inputfield
- 设置title,文字为Login,调整位置
 - 窗体,包括两个inputfield,分别输入账号密码,调整大小
 - Error以及botton,根据不同情况设置相应内容
 - 背景图片设置,注意颜色搭配,一般选择绿色
 

游戏主场景

相机设置
修改相机参数 :ClearFlags 设置为SolidColor 让我们游戏中的场景纯颜色显示,Projection设置为Orthographic 正交相机 , size设置相机视角的大小。
游戏背景
设置游戏背景图、四面的墙壁、贪吃蛇的蛇头和食物的组件及属性,还有一个游戏失败和显示分数的UI界面。
背景图,新建2D Object-->Sprite 取名GameBG 设置图片精灵,调整scale大小为30*30。
Food设置
点击 is Trigger
添加Box Collider 2D
其中Size调整为0.7
其他设置同上
关键是把它设置为Prefab预制体

Snake设置
添加Rigidbody 2D
选择 is kinematic
设置Gravity为0
注意Collerction.Generic以及Linq

Restart 界面
设置button,调整重新开始的场景切换
设置text以及背景图,大小以及位置

素材制作
LOGO开场 界面
通过富有王者气质的蛇王形象,作为开场LOGO界面
呈现方式为:淡入淡出
持续时间为1+2+3秒
通过switch选择语句执行

登录界面
常用活泼的贪吃蛇背景图
颜色搭配为黄绿色,轻快明亮
界面设置合理,位置大小适当清晰即可
通过二维数组存储账号密码

游戏主场景
通过两个text记录分数,直观明了
食物丰富,空间丰富,规律合理设置
背景图采用蓝绿色,更加清晰直观
蛇头位置以及动画效果耐人寻味
采用极简风格编写
随机生成数方法 来确定 下边界,上边界
巧妙方法:将最末尾的蛇身移动到头位置,从而不用整体移动,维护数据结构顺序
设置布尔变量,逻辑判断,转换场景

重新开始 界面
通过颜色落差,让人想要再玩一把
通过button按钮重新开始,切换场景
颜色,大小,位置,文字合理设置即可

其他制作
背景音乐
通过拖放背景音乐,使每个场景都是新的背景音乐
使游戏饶有兴趣,更有乐趣,动力,放松,娱乐特性增强。

脚本代码
开场 界面
// LogoEvent.cs
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using System.Collections;
public class LogoEvent : MonoBehaviour {
//设置对象
public Image img;
    public float speed = 0.5f;
    public float waitTime = 1.0f;
//时间等待常量
Public const int HideToShow = 1;
    public const int Wait = 2;
public const int ShowToHide = 3;
//定义条件判断
    int currentState;
    float currentAlpha;
    float waitCount;
//初始化
//颜色以及状态
	void Start () {
        currentState = HideToShow; 
        img.color = new Color(1, 1, 1, currentAlpha);
	}
	void Update () {
//状态更新
switch (currentState)
        {
//展示状态,逐渐显示
            case HideToShow:
                currentAlpha += speed * Time.deltaTime;
                if (currentAlpha > 1) currentAlpha = 1;
                img.color = new Color(1, 1, 1, currentAlpha);
                if (currentAlpha == 1) currentState = Wait;
                break;
//转换状态,逐渐隐藏
           case ShowToHide:
                currentAlpha -= speed * Time.deltaTime;
                if (currentAlpha < 0) currentAlpha = 0;
                img.color = new Color(1, 1, 1, currentAlpha);
                if (currentAlpha == 0)
                    SceneManager.LoadScene("UI_Other");
                break;
//等待状态
            case Wait:
                waitCount += Time.deltaTime;
                if (waitCount >= waitTime) currentState = ShowToHide;
                break;
          
        }
	}
}
        登录界面
//Submit.cs
//采用极简风格编写
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using UnityEngine.SceneManagement;
public class submit : MonoBehaviour {
//设置对象
	public InputField ifID;
	public InputField ifPW;
	public Text error;
//输入数据
	public void Submit(){
		string userID = ifID.text;
		string userPW = ifPW.text;
		if (error.gameObject.activeSelf) {
			error.gameObject.SetActive (false);
		}
	
//空数据
	if (string.IsNullOrEmpty(userID) || string.IsNullOrEmpty(userPW)){
		error.text = "Can't empty";
		error.gameObject.SetActive(true);
		return;
	}
		bool isSucess = false;
//验证是否正确
	for(int i=0;i<Data.ACCOUNT.Length;++i){
		string dataID = Data.ACCOUNT[i][0];
		string dataPW = Data.ACCOUNT[i][1];
		if(dataID.Equals(userID)&&dataPW.Equals(userPW)){
			isSucess = true;
			break;
		}
	}
//验证通过
	if(isSucess){
		SceneManager.LoadScene("other");
	}else{
		error.text = "ID or Password error";
		error.gameObject.SetActive(true);
		return;
	}
}
        账号密码设置
//Data.cs
//通过二维数组存储账号密码
using UnityEngine;
using System.Collections;
public class Data {
//数据结构定义
    public static string[][] ACCOUNT = new string[5][]{
        new string[]{
            "TOM","12345"
        },new string[]{
            "TOM2","12345"
        },new string[]{
            "TOM3","12345"
        },new string[]{
            "TOM4","12345"
        },new string[]{
            "TOM5","12345"
        }
    };
}
        食物毒药界面(游戏主场景)
//Food.cs
//食物
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine.SceneManagement; 
public class Food : MonoBehaviour {
       
        //Borders
        public Transform Top;
        public Transform Bottom;
        public Transform Left;
        public Transform Right;
        //food prefab
        public GameObject Prefab;
    //初始化各种对象
        // Use this for initialization
        void Start () {
                InvokeRepeating ("Form", 3, 4);
            }
    //不断重复调用方法
    //方法名,最初几秒钟以后,每隔多少秒
        
      
        //spawn one piece of food
        void Form(){
        //y position between top &bottom border
                int y = (int)Random.Range(Top.position.y,Bottom.position.y);
        //x position between left &right border
                int x = (int)Random.Range(Left.position.x,Right.position.x);
        //随机生成数方法
        //下边界,上边界
                //instantiate the food at (x,y)
                Instantiate(Prefab,new Vector2(x,y),Quaternion.identity);//default rotation
        //实例化
        //对象,位置,旋转角度
            }
}
//Poison.cs
//毒药
using UnityEngine;
using System.Collections;
public class Poison : MonoBehaviour {
        //Borders
        public Transform Top;
        public Transform Bottom;
        public Transform Left;
        public Transform Right;
        //food prefab
        public GameObject Prefab;
    //初始化各种对象
        // Use this for initialization
        void Start () {
                InvokeRepeating ("Form", 4, 4);
            }
    //不断重复调用方法
    //方法名,最初几秒钟以后,每隔多少秒
        
      
        //spawn one piece of food
        void Form(){
        //y position between top &bottom border
                int y = (int)Random.Range(Top.position.y,Bottom.position.y);
        //x position between left &right border
                int x = (int)Random.Range(Left.position.x,Right.position.x);
        //随机生成数方法
        //下边界,上边界
                //instantiate the food at (x,y)
                Instantiate(Prefab,new Vector2(x,y),Quaternion.identity);//default rotation
        //实例化
        //对象,位置,旋转角度
            }
}
        蛇界面(游戏主场景)
//BigSnake.cs
//大蛇
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class BigSnake : MonoBehaviour {
    Vector2 dir = Vector2.right;
//当前移动方向
//数据结构列表
//存储身体长度
    //keep track of tail
    List<Transform> tail = new List<Transform>();
//是否遇到食物逻辑判断,布尔变量
    bool ate = false;
//设置预制体对象
    public GameObject tailPrefab;
    // Use this for initialization
    void Start () {
        InvokeRepeating ("Move", 0.3f, 0.3f);
    }
//不断重复调用方法
//方法名,最初几秒钟以后,每隔多少秒
//300ms
  
    // Update is called once per frame
    void Update () {
//更改方向
//通过输入赋值
        if (Input.GetKey (KeyCode.RightArrow))
            dir = Vector2.right;
        else if (Input.GetKey (KeyCode.DownArrow))
            dir = - Vector2.up;
        else if (Input.GetKey (KeyCode.LeftArrow))
            dir = - Vector2.right;
        else if (Input.GetKey (KeyCode.UpArrow))
            dir = Vector2.up;
    }
//设置两条蛇的输入参数
//第一条蛇,正常输入
//第二条蛇,完全相反,而且位置对称分布
    void Move(){
//保存蛇头位置v
        Vector2 v = transform.position;
//Do Movement 
        transform.Translate (dir);
//是否是食物
        if (ate) {
            GameObject g = (GameObject)Instantiate (tailPrefab, v, Quaternion.identity);
//实例化
//对象,位置,旋转角度
            tail.Insert (0, g.transform);
//维护数据结构,底部
            ate = false;
//恢复布尔变量逻辑判断
        }else if (tail.Count > 0) {
            tail.Last ().position = v;
//巧妙方法:将最末尾的蛇身移动到头位置,从而不用整体移动
//维护数据结构顺序
            tail.Insert (0, tail.Last ());
            tail.RemoveAt (tail.Count - 1);
//末尾位置,减一是数据结构从0开始的特性
        }
    }
    void OnTriggerEnter2D(Collider2D coll){
            if(coll.name.StartsWith("FoodPrefab")) {
                ate = true;
//碰到食物,逻辑判断
                Destroy(coll.gameObject);
//销毁本体
        }
           
//碰到其他,墙或身体
else{
            //lose
            
            }
    
    }
}
//SmallSnake.cs
//小蛇
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class Snake1 : MonoBehaviour {
	public Text Score;
	Vector2 dir = Vector2.right;
	//当前移动方向
	//数据结构列表
	//存储身体长度
	//keep track of tail
	List<Transform> tail = new List<Transform>();
	//是否遇到食物逻辑判断,布尔变量
	bool ate = false;
	bool ate1 = false;
	//设置预制体对象
	public GameObject Prefab;
	// Use this for initialization
	void Start () {
		InvokeRepeating ("Move", 0.3f, 0.3f);
	}
	//不断重复调用方法
	//方法名,最初几秒钟以后,每隔多少秒
	//300ms
	// Update is called once per frame
	void Update () {
		//更改方向
		//通过输入赋值
		if (Input.GetKey (KeyCode.RightArrow))
			dir = - Vector2.right;
		else if (Input.GetKey (KeyCode.DownArrow))
			dir =  Vector2.up;
		else if (Input.GetKey (KeyCode.LeftArrow))
			dir =  Vector2.right;
		else if (Input.GetKey (KeyCode.UpArrow))
			dir = - Vector2.up;
		Score.text = tail.Count.ToString();
	}
	void Move(){
		//保存蛇头位置v
		Vector2 v = transform.position;
		//Do Movement 
		transform.Translate (dir);
		//是否是食物
		if (ate) {
			GameObject g = (GameObject)Instantiate (Prefab, v, Quaternion.identity);
			//实例化
			//对象,位置,旋转角度
			tail.Insert (0, g.transform);
			//维护数据结构,底部
			ate = false;
			//恢复布尔变量逻辑判断
		}else if (ate1) {
			//实例化
			//对象,位置,旋转角度
			if (tail.Count > 1) {
				
				tail.RemoveAt (tail.Count - 1);
				}
			//维护数据结构,底部
			ate1 = false;
			//恢复布尔变量逻辑判断
		}
		else if (tail.Count > 0) {
			tail.Last ().position = v;
			//巧妙方法:将最末尾的蛇身移动到头位置,从而不用整体移动
			//维护数据结构顺序
			tail.Insert (0, tail.Last ());
			tail.RemoveAt (tail.Count - 1);
		
			//末尾位置,减一是数据结构从0开始的特性
		}
	}
	void OnTriggerEnter2D (Collider2D coll)
	{
		if (coll.name.StartsWith ("Poison")) {
			ate = true;
			//碰到食物,逻辑判断
			Destroy (coll.gameObject);
			//销毁本体
		}
		//碰到其他,墙或身体
		else if (coll.name.StartsWith ("Food1")) {
			ate1 = true;
			//碰到食物,逻辑判断
			Destroy (coll.gameObject);
			//销毁本体
		} else {
			SceneManager.LoadScene("Restart");
		}
	}
}
        重新开始界面
/Restart.cs
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using UnityEngine.SceneManagement;
public class Restart : MonoBehaviour {
    //设置对象
    //输入数据
    public void Submit(){
        
//设置布尔变量
        bool isSucess = true;
//逻辑判断,转换场景
        if(isSucess){
            SceneManager.LoadScene("main");
        }
            
    }
} 
        小结
通过switch选择语句执行
采用极简风格编写
通过二维数组存储账号密码
随机生成数方法 来确定 下边界,上边界
巧妙方法:将最末尾的蛇身移动到头位置,从而不用整体移动,维护数据结构顺序
设置布尔变量,逻辑判断,转换场景