将游戏分为四个脚本,将数据和界面分开,这是开发模式常用的类似于mvc模式,但由于我们只用一个二位数组就可以保存数据,所以讲m省略

GameControllor 控制游戏数据的脚本,

using UnityEngine;
using System.Collections; public enum DIR_TYPE
{
TOP,
LEFT,
RIGHT,
BOTTOM
}
public class GameControllor : MonoBehaviour { public int[,] datas; //游戏数据
public int row = ;
public int col = ;
bool isOver;
bool isWin;
int score;
int emptyNumber; // 空格子数
int[] temp;//一个临时数组,存放十六个位置数据
DIR_TYPE type = DIR_TYPE.TOP;
void Awake()
{
datas = new int[row,col];
isOver = false;
isWin = false;
emptyNumber = row * col ;
score = ;
temp = new int[row+];//一个临时数组,存放十六个位置数据
RandomNumber();
}
void RandomNumber()
{ if( emptyNumber == row * col )
{
for(int i = ; i < ; ++i)
{
RandomCell();
} }
else if( emptyNumber > )
{
RandomCell();
}
IsOver();
IsWin();
} void RandomCell()
{
int r = Random.Range(,row);
int c = Random.Range(,col);
if( == datas[r,c] )
{
datas[r,c] = ;
emptyNumber--;
}
else{
RandomCell ();
}
}
// Update is called once per frame
void Update () {
KeyboardListenEvt();
}
void KeyboardListenEvt()
{
if( Input.GetKeyDown(KeyCode.W) )
{
GameRun(DIR_TYPE.TOP );
}
if( Input.GetKeyDown(KeyCode.S) )
{
GameRun( DIR_TYPE.BOTTOM );
}
if( Input.GetKeyDown(KeyCode.A) )
{
GameRun( DIR_TYPE.LEFT );
}
if( Input.GetKeyDown(KeyCode.D) )
{
GameRun( DIR_TYPE.RIGHT );
} }
void Swap(ref int a, ref int b)
{
a = (a + b) - (b = a);
}
//玩家可以选择上下左右四个方向,若棋盘内的数字出现位移或合并,视为有效移动
public int GameMove( )
{
int change = ;
int i = ;
int j = ;
do //去掉中间的0
{
for (i = ; i < ; ++i )
{
if ( == temp[i])//玩家选择的方向行或列前方有空格则出现位移
{
if (temp[i] != temp[i + ])//不相等移动
{
change = ;//有效移动
}
temp[i] = temp[i + ];
temp[i + ] = ;
}
}
j++;
} while (j < ); for (i = ; i < ; ++i )
{
//玩家选择的方向上若有相同的数字则合并,每次有效移动可以同时合并,但不可以连续合并
if (temp[i] == temp[i - ])//相同的数字则合并
{
if ( != temp[i])
{
change = ;
score += temp[i];
emptyNumber++;
}
temp[i - ] += temp[i - ];//前一个数字乘自己
temp[i] = ;// 后一个位置 置0
} } do //去掉中间的0
{
for (i = ; i < ; ++i )
{
if ( == temp[i])//玩家选择的方向行或列前方有空格则出现位移
{
if (temp[i] != temp[i + ])//不相等移动
{
change = ;//有效移动
}
temp[i] = temp[i + ];
temp[i + ] = ;
}
}
j++;
} while (j < );
return change;
}
void GameRun(DIR_TYPE type)
{ int i = ;
int j = ;
int change = ;/*判断格子中的数是否改变,0不变*/ if (type == DIR_TYPE.LEFT || type == DIR_TYPE.RIGHT)
{
for (i = ; i < row; ++i)
{
for (j = ; j < col; ++j)
{
if (type == DIR_TYPE.LEFT)
{
temp[j] = datas[i, j];//把每一行数据放到临时数组中
}
else
{
temp[j] = datas[i, - j];
}
}
//temp[4] = 0; change += GameMove();//处理每一行数据,进行移除中间的0,合并相同数字,根据change的值可以产生随机数 for (j = ; j < col; ++j)
{
if (type == DIR_TYPE.LEFT)
{
datas[i, j] = temp[j];// 把每一行处理完的数据在放回到地图中
}
else
{
datas[i, - j] = temp[j];
}
}
}
}
else
{ for (i = ; i < row; ++i)
{
for (j = ; j < col; ++j)
{ if (type == DIR_TYPE.TOP)
{
temp[j] = datas[j, i];//把每一列数据存进去
}
else if (type == DIR_TYPE.BOTTOM)
{
temp[j] = datas[ - j, i];
} }
temp[row] = ;
change += GameMove(); for (j = ; j < col; ++j)
{
if (type == DIR_TYPE.TOP)
{
datas[j, i] = temp[j]; //把处理好的中间变量移回来
}
else if (type == DIR_TYPE.BOTTOM)
{
datas[ - j, i] = temp[j];
}
}
}
} if (change > )
{
RandomNumber();
}
}
public bool IsOver()
{
if( == emptyNumber)
{
bool shoultOver = true;
for (int i = ; i < row - ; i++) {
for (int j = ; j < col - ; j++) {
if( datas[i,j] == datas[i + ,j] ){
shoultOver = false;
break;
}
if( datas[i,j] == datas[i,j + ] ){
shoultOver = false;
break;
}
}
if(!shoultOver)
break;
}
isOver = shoultOver;
}
return isOver;
}
public int GetScore()
{
return score;
}
public bool IsWin()
{
for (int i = ; i < row; i++) {
for (int j = ; j < col; j++) {
if(datas[i,j] >= )
{
isWin = true;
}
}
}
return isWin;
}
}

将单元格图片 绘制到背景图片上

using UnityEngine;
using System.Collections; public class BackGroundScript : MonoBehaviour { public GameObject cell; //单元格
static Vector2 startPos = new Vector2(-1.65f, 1.65f); // 起始位置
static float offetX = 1.1f; // 左右单元格的间隔
static float offsetY = 1.1f; // 上下两个单元的间隔 //public Sprite sprite;
// 在这之前把摄像机调整为正交模式(Orthographic)并且把bg层级调整为-1 Order in layer
void Awake()
{
DrawMapCell();
} // 绘制地图格子
void DrawMapCell()
{
// 排列出背景单元格
for( int i = ; i< ; ++i )
{
for (int j = ; j < ; j++) {
// 从预设体实例化游戏对象
GameObject c = Instantiate(cell, GetPos(i,j), Quaternion.identity) as GameObject;
// 设置游戏对象的父对象
c.transform.parent = transform;
}
}
}
// 获取位置
public static Vector2 GetPos(int r, int c)
{
// 计算每个单元个位置
float x = startPos.x + c * offetX ;
float y = startPos.y - r * offsetY ;
Vector2 pos = new Vector2(x, y);
return pos;
}
}

控制显示界面,直接调用GameControl里的数据,在Update里每帧刷新一次界面,来检测数据是否需要更新

using UnityEngine;
using System.Collections; public class ViewControllor : MonoBehaviour { public GameObject cell;// 单元格预设体文件
GameObject[,] cells;// 保存所有界面上cell
GameControllor gameControl;
//
void Awake()
{
// 获取游戏控制器的脚本组件
gameControl = GameObject.FindGameObjectWithTag("GameController").GetComponent<GameControllor>() ;
cells = new GameObject[gameControl.row,gameControl.col];
} // Update is called once per frame
void Update () {
RefreshView();
}
// 刷新界面
void RefreshView()
{
// 检测数据变化来刷新界面
for (int i = ; i < gameControl.row; i++) {
for (int j = ; j < gameControl.col; j++) {
// 遍历数据数组中的每一个元素的值
int data = gameControl.datas[i,j];
// 判断是否要创建一个cell
// 数据本身不是0
if( != data && cells[i,j] == null )
{
// 在具体位置创建新的游戏对象 创建新的cell 并保存起来
GameObject c = Instantiate(cell, BackGroundScript.GetPos(i,j), Quaternion.identity) as GameObject;
c.transform.parent = transform;// viewControl shi tade
cells[i,j] = c;
}
// 判断界面上以显示的cell
else if( null != cells[i,j] && cells[i,j].GetComponent<CellScript> ().num != data )
{
cells[i,j].GetComponent<CellScript> ().ChangeNumber(data);
}
}
} }
void OnGUI()
{
GUI.skin.label.fontSize = ;
GUI.color = Color.red;
if(gameControl.IsOver())
GUI.Label(new Rect(Screen.width >> ,Screen.height >> ,,),"Game over!");
if(gameControl.IsWin())
GUI.Label(new Rect(Screen.width >> ,Screen.height >> ,,),"Game Win!");
GUI.Label(new Rect(100f,,,),gameControl.GetScore().ToString());
}
}

这个类的作用是给预设体添加一个脚本,预设体里的精灵数组保存的用到的十张数字图

using UnityEngine;
using System.Collections;
// 这个类的作用是给预设体添加一个脚本,预设体里的精灵数组保存的用到的十张数字图
public class CellScript : MonoBehaviour { public Sprite[] sprites; // 精灵数组
public int index; // 当前下标
public int num; // 当前cell显示的数字
void Awake()
{
num = ;
}
// 改变cell当前显示的数字
public void ChangeNumber(int number)
{
num = number;
// 如果是0就干掉cell
if( == number )
{
Destroy(transform.gameObject);
}
// 如果不是0 就替换图片
else{
// 该数字是 数组对应的下标 2 的 number 次方
index = (int)Mathf.Log(number , ) - ;
transform.GetComponent<SpriteRenderer> ().sprite = sprites[index];
} }
}

unity 2048Game的更多相关文章

  1. Unity3d入门 - 关于unity工具的熟悉

    上周由于工作内容较多,花在unity上学习的时间不多,但总归还是学习了一些东西,内容如下: .1 根据相关的教程在mac上安装了unity. .2 学习了unity的主要的工具分布和对应工具的相关的功 ...

  2. 聊聊Unity项目管理的那些事:Git-flow和Unity

    0x00 前言 目前所在的团队实行敏捷开发已经有了一段时间了.敏捷开发中重要的一个话题便是如何对项目进行恰当的版本管理.项目从最初使用svn到之后的Git One Track策略再到现在的GitFlo ...

  3. Unity游戏内版本更新

    最近研究了一下游戏内apk包更新的方法. ios对于应用的管理比较严格,除非热更新脚本,不太可能做到端内大版本包的更新.然而安卓端则没有此限制.因此可以做到不跳到网页或应用商店,就覆盖更新apk包. ...

  4. Unity 序列化

    Script Serialization http://docs.unity3d.com/Manual/script-Serialization.html 自定义序列化及例子: http://docs ...

  5. Unity 序列化 总结

    查找了 Script Serialization http://docs.unity3d.com/Manual/script-Serialization.html 自定义序列化及例子: http:// ...

  6. ASP.NET MVC5+EF6+EasyUI 后台管理系统(64)-补充WebApi与Unity注入-配置文件

    系列目录 上一篇演示了WebApi利用Unity注入 很多人问我如何用配置文件来配置注入,本节演示如何利用配置文件来注入,道理是一样的,跳转到上一节下载源码一起来动手! 1.打开源码定位到文件Depe ...

  7. ASP.NET MVC5+EF6+EasyUI 后台管理系统(64)-WebApi与Unity注入

    系列目录 前言: 有时候我们系统需要开放数据给手机App端或其他移动设备,不得不说Asp.net WebApi是目前首选 本节记录Asp.net MVC WebApi怎么利用Unity注入.系列开头已 ...

  8. 使用Microsoft的IoC框架:Unity来对.NET应用进行解耦

    1.IoC/DI简介 IoC 即 Inversion of Control,DI 即 Dependency Injection,前一个中文含义为控制反转,后一个译为依赖注入,可以理解成一种编程模式,详 ...

  9. Unity C#最佳实践(上)

    本文为<effective c#>的读书笔记,此书类似于大名鼎鼎的<effective c++>,是入门后提高水平的进阶读物,此书提出了50个改进c#代码的原则,但是由于主要针 ...

随机推荐

  1. C# webbrowser遍历网页元素

    //不引用其他单元  foreach(HtmlElement ele in WB1.Document.All)                 {                   if(ele.I ...

  2. Android Studio设置自动导包

    Android Studio设置自动导包. 步骤: (1)找到File->Settings (2)找到Editor->General->Auto Import (3)依照上图勾选几个 ...

  3. Linux性能优化 第八章 实用工具:性能工具助手

    8.1性能工具助手 Linux有丰富的工具,这些工具组合来使用会更加强大.性能工具也一样,单独使用虽然也没有问题,但是和其他的工具组合起来就能显著提高有效性和易用性. 8.1.1 自动执行和记录命令 ...

  4. nvm use 指定版本后无效 win7

    如图所示,nvm install 6.12.3之后,使用命令nvm use 6.12.3,提示切换成功,但是执行node app.js时,报错没有node命令,执行nvm ls查看,发现没有任何版本是 ...

  5. TessorFlow学习 之 手写数字识别的搭建

    手写数字识别的搭建

  6. python基础易错总结

    1.python安装配置环境变量 [右键计算机]------->[属性]------->[高级系统设置]------->[高级]------->[环境变量]--------&g ...

  7. 20165205 2017-2018-2 《Java程序设计》 第三周学习总结

    20165205 2017-2018-2 <Java程序设计>第三周学习总结 教材学习内容总结 学习类的概念(类体,成员变量,方法) 学会构造方法(默认和自定义构造方法) 学会创建.使用对 ...

  8. elk收集windows日志

    参考网站:https://www.secpulse.com/archives/55636.html https://blog.csdn.net/qq_38094271/article/details/ ...

  9. ThinkPHP同时操作多个数据库

    除了在预先定义数据库连接和实例化的时候指定数据库连接外,我们还可以在模型操作过程中动态的切换数据库,支持切换到相同和不同的数据库类型.用法很简单, 只需要调用Model类的db方法,用法: $this ...

  10. __file__ 作用以及模块导入方法

    python 执行py 文件的时候,默认就会把当前目录增加到sys.path中 import os print(__file__) #打印文件当前的位置 直接在目录里面执行,结果显示当前文件(pych ...