unity 2048Game
将游戏分为四个脚本,将数据和界面分开,这是开发模式常用的类似于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的更多相关文章
- Unity3d入门 - 关于unity工具的熟悉
上周由于工作内容较多,花在unity上学习的时间不多,但总归还是学习了一些东西,内容如下: .1 根据相关的教程在mac上安装了unity. .2 学习了unity的主要的工具分布和对应工具的相关的功 ...
- 聊聊Unity项目管理的那些事:Git-flow和Unity
0x00 前言 目前所在的团队实行敏捷开发已经有了一段时间了.敏捷开发中重要的一个话题便是如何对项目进行恰当的版本管理.项目从最初使用svn到之后的Git One Track策略再到现在的GitFlo ...
- Unity游戏内版本更新
最近研究了一下游戏内apk包更新的方法. ios对于应用的管理比较严格,除非热更新脚本,不太可能做到端内大版本包的更新.然而安卓端则没有此限制.因此可以做到不跳到网页或应用商店,就覆盖更新apk包. ...
- Unity 序列化
Script Serialization http://docs.unity3d.com/Manual/script-Serialization.html 自定义序列化及例子: http://docs ...
- Unity 序列化 总结
查找了 Script Serialization http://docs.unity3d.com/Manual/script-Serialization.html 自定义序列化及例子: http:// ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(64)-补充WebApi与Unity注入-配置文件
系列目录 上一篇演示了WebApi利用Unity注入 很多人问我如何用配置文件来配置注入,本节演示如何利用配置文件来注入,道理是一样的,跳转到上一节下载源码一起来动手! 1.打开源码定位到文件Depe ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(64)-WebApi与Unity注入
系列目录 前言: 有时候我们系统需要开放数据给手机App端或其他移动设备,不得不说Asp.net WebApi是目前首选 本节记录Asp.net MVC WebApi怎么利用Unity注入.系列开头已 ...
- 使用Microsoft的IoC框架:Unity来对.NET应用进行解耦
1.IoC/DI简介 IoC 即 Inversion of Control,DI 即 Dependency Injection,前一个中文含义为控制反转,后一个译为依赖注入,可以理解成一种编程模式,详 ...
- Unity C#最佳实践(上)
本文为<effective c#>的读书笔记,此书类似于大名鼎鼎的<effective c++>,是入门后提高水平的进阶读物,此书提出了50个改进c#代码的原则,但是由于主要针 ...
随机推荐
- 使用命名管道的OVERLAPPED方式实现非阻塞模式编程 .
命令管道是进程间通讯的一种常用方式,对于命令管道的介绍可以参考别的资料和书籍,这里推荐一个<VC++下命名管道编程的原理及实现>这篇博文,写得比较清楚.但是都是介绍了阻塞模式的编程,我这里 ...
- Kafka分布式集群部署
这个是kafka的官网地址:http://kafka.apache.org/ 1.kafka是一个消息系统. 2.kafka对流数据可以高效的实时处理. 3.分布式集群的环境下能够保证数据的安全. k ...
- 把一串数字表示成千位分隔形式——JS正则表达式的应用
梳理思路 要先明白的是,我们将要转换成的数字格式是这样:从个位往左数起,每三位前插入一个千位分隔符,,即可以想象成我们要把每三位数字前面的那个空""匹配出来,并替换成千位分隔符,. ...
- Django中的分页,cookies与session
cookie Cookie的由来 大家都知道HTTP协议是无状态的. 无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不 ...
- oracle提高查询效率的34个方面全解析
oracle提高查询效率的34个方面全解析 在一个数据库中进行操作的时候,效率是很重要的,那么,如何提高oracle的查询效率呢?笔者将从以下几个方面进行详细解析: 1.选择最有效率的表名顺序(只 ...
- 定时任务Job
package com.cfets.ts.u.limitapi.job; import java.text.SimpleDateFormat; import java.util.Date; impor ...
- 关于elment-ui树形控件Tree的使用
如果简单使用的tree树形控件,按照Element ui Tree 树形控件 官方文档使用即可,基本上能够完成大部分的需求. 但是如果需要对树形结构进行额外操作,仅仅根据官方文档提供的方案的话,可能就 ...
- django总结 --》内容(django建project开始的大致流程、ORM简介)
1 安装: pip install django==1.11.9 另外:在pycharm中安装 django,在下图中七步走 2. 新建Django项目 django-admin startpro ...
- 大小端,memcpy和构造函数
问题:memcpy一段内存到std::bitset里,bitset里的内存数据和被拷贝的内存数据对应不上 代码如下: #include <iostream> #include <bi ...
- python数组和矩阵使用总结
python数组和矩阵使用总结 1.数组和矩阵常见用法 Python使用NumPy包完成了对N-维数组的快速便捷操作.使用这个包,需要导入numpy. SciPy包以NumPy包为基础,大大的扩展了n ...