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选择语句执行
采用极简风格编写
通过二维数组存储账号密码
随机生成数方法来确定下边界,上边界
巧妙方法:将最末尾的蛇身移动到头位置,从而不用整体移动,维护数据结构顺序
设置布尔变量,逻辑判断,转换场景