using UnityEngine;
 using System.Collections;
 using Holoville.HOTween;

 /// <summary>
 /// 游戏逻辑
 /// </summary>
 public class Main:MonoBehaviour {

     /// <summary>
     /// 点击框预设
     /// </summary>
     public GameObject _indicator;
     /// <summary>
     /// 二维方块数组
     /// </summary>
     public GameObject[,] _arrayOfShapes;
     /// <summary>
     /// 当前点击框
     /// </summary>
     private GameObject _currentIndicator;
     /// <summary>
     /// 第一个选择的物体
     /// </summary>
     private GameObject _FirstObject;
     /// 第二个选择的物体
     /// </summary>
     private GameObject _SecondObject;
     /// <summary>
     /// 方块预设列表
     /// </summary>
     public GameObject[] _listOfGems;
     /// <summary>
     /// 空物体
     /// </summary>
     public GameObject _emptyGameobject;
     /// <summary>
     /// 星星特效
     /// </summary>
     public GameObject _particleEffect;
     /// <summary>
     /// 匹配时的特效
     /// </summary>
     public GameObject _particleEffectWhenMatch;
     /// <summary>
     /// 能否在对角线上转换
     /// </summary>
     public bool _canTransitDiagonally = false;
     /// <summary>
     /// 每次匹配时的增长分数
     /// </summary>
     public int _scoreIncrement;
     /// <summary>
     /// 总分
     /// </summary>
     ;
     /// <summary>
     /// 当前特效
     /// </summary>
     private ArrayList _currentParticleEffets = new ArrayList();
     /// <summary>
     /// 匹配时的声音
     /// </summary>
     public AudioClip MatchSound;
     /// <summary>
     /// 网格x轴上的格子数量
     /// </summary>
     public int _gridWidth;
     /// <summary>
     /// 网格y轴上的格子数量
     /// </summary>
     public int _gridHeight;

     void Start() {
         //为2维方块数组分配内存
         _arrayOfShapes = new GameObject[_gridWidth,_gridHeight];

         //从左到右,从下到上创建格子
         ;i <= _gridWidth - ;i++) {
             ;j <= _gridHeight - ;j++) {
                 //var gameObject = GameObject.Instantiate(_listOfGems[Random.Range(0,_listOfGems.Length)] as GameObject,new Vector3(i,j,0),transform.rotation) as GameObject;

                 GameObject gameObject = null;
                 ) {
                     gameObject = GameObject.Instantiate(_listOfGems[] ),transform.rotation) as GameObject;
                 } ) {
                     gameObject = GameObject.Instantiate(_listOfGems[] ),transform.rotation) as GameObject;
                 } else {
                     gameObject = GameObject.Instantiate(_listOfGems[] ),transform.rotation) as GameObject;
                 }
                 _arrayOfShapes[i,j] = gameObject;
             }
         }
         //Adding the star effect to the gems and call the DoShapeEffect continuously
         //InvokeRepeating("DoShapeEffect",1f,0.21F);

     }

     void Update() {
         //是否转换
         bool shouldTransit = false;
         //当用户点击按钮且没有动画
         if(Input.GetButtonDown("Fire1") && HOTween.GetTweenInfos() == null) {
             //销毁当前选择框
             Destroy(_currentIndicator);
             //生成从屏幕中心点到鼠标点击位置的射线
             Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
             //发射射线
             RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition),Vector2.zero);
             //如果射线碰到物体
             if(hit.transform != null) {
                 //第一个选择的物体为空
                 if(_FirstObject == null) {
                     //将点击的物体设置为第一个选择物体
                     _FirstObject = hit.transform.gameObject;
                 //如果第一个选择的物体不为空
                 } else {
                     //将点击的物体设置为第二个选择物体
                     _SecondObject = hit.transform.gameObject;
                     //可以转换
                     shouldTransit = true;
                 }

                 //根据点击位置创建选择框
                 _currentIndicator = GameObject.Instantiate(_indicator,),transform.rotation) as GameObject;
                 //如果可以转换
                 if(shouldTransit) {
                     //获取两个物体之间的距离
                     var distance = _FirstObject.transform.position - _SecondObject.transform.position;
                     //如果x,y的距离 都小于等于1
                      && Mathf.Abs(distance.y) <= ) {
                         //如果不能在斜线上交换
                         if(!_canTransitDiagonally) {
                             //
                              && distance.y != ) {
                                 //销毁选择框
                                 Destroy(_currentIndicator);
                                 _FirstObject = null;
                                 _SecondObject = null;
                                 return;
                             }
                         }
                         //播放交换动画
                         DoSwapMotion(_FirstObject.transform,_SecondObject.transform);
                         //交换在数组中的位置
                         DoSwapTile(_FirstObject,_SecondObject,ref _arrayOfShapes);
                     //如果不能转换
                     } else {
                         _FirstObject = null;
                         _SecondObject = null;

                     }
                     //销毁选择框
                     Destroy(_currentIndicator);

                 }

             }

         }

         //如果没有播放动画
         if(HOTween.GetTweenInfos() == null) {
             //查找匹配的格子
             var Matches = FindMatch(_arrayOfShapes);
             //如果找到匹配的格子
             ) {
                 //更新分数
                 _scoreTotal += Matches.Count * _scoreIncrement;

                 //遍历匹配物体
                 foreach(GameObject go in Matches) {
                     //播放匹配声音
                     GetComponent<AudioSource>().PlayOneShot(MatchSound);
                     //创建匹配特效
                     ),transform.rotation) as GameObject;
                     //1秒后销毁特效
                     Destroy(destroyingParticle,1f);
                     //用空物体替换匹配物体
                     _arrayOfShapes[(),transform.rotation) as GameObject;
                     //0.1秒后删除匹配物体
                     Destroy(go,0.1f);
                 }
                 _FirstObject = null;
                 _SecondObject = null;

                 DoEmptyDown(ref _arrayOfShapes);
             }
             //如果没有找到格子,将格子的位置复位
             else if(_FirstObject != null && _SecondObject != null) {
                 //播放交换动画
                 DoSwapMotion(_FirstObject.transform,_SecondObject.transform);
                 //交换格子位置
                 DoSwapTile(_FirstObject,_SecondObject,ref _arrayOfShapes);
                 _FirstObject = null;
                 _SecondObject = null;
             }
         }

         //更新分数
         (GetComponent(typeof(TextMesh)) as TextMesh).text = _scoreTotal.ToString();
     }

     /// <summary>
     /// 查找匹配
     /// </summary>
     /// <param name="cells"></param>
     /// <returns></returns>
     private ArrayList FindMatch(GameObject[,] cells) {
         //存储匹配的方块数组
         ArrayList stack = new ArrayList();
         //将列上至少3个颜色相同的方块放进数组中
         //从左到右
         ;x <= cells.GetUpperBound();x++) {
             //从下到上
             ;y <= cells.GetUpperBound();y++) {
                 //当前网格
                 var thiscell = cells[x,y];
                 //如果是空物体,忽略
                 if(thiscell.name == "Empty(Clone)") {
                     continue;
                 }
                 //匹配数量
                 ;
                 //y2 网格列上的最大索引
                 );
                 //y1 网格列内y格子上方的格子索引
                 int y1;
                 //遍历列中其余的格子
                 ;y1 <= y2;y1++) {
                     //如果是空物体或者名字不匹配,跳出循环
                     if(cells[x,y1].name == "Empty(Clone)" || thiscell.name != cells[x,y1].name) {
                         break;
                     }

                     //匹配数量加一
                     matchCount++;
                 }

                 //如果匹配数量大于等于2
                 ) {
                     //限制y1的最小值
                     y1 = Mathf.Min(cells.GetUpperBound(),y1 - );
                     //从 y遍历到 y1,
                     for(var y3 = y;y3 <= y1;y3++) {
                         //将不重复的格子添加到数组中
                         if(!stack.Contains(cells[x,y3])) {
                             stack.Add(cells[x,y3]);
                         }
                     }
                 }
             }
         }

         //将行上至少3个颜色相同的方块放进数组中
         //从下到上
         ;y < cells.GetUpperBound() + ;y++) {
             //从左到右
             ;x < cells.GetUpperBound() + ;x++) {
                 //当前网格
                 var thiscell = cells[x,y];
                 //如果是空物体,忽略
                 if(thiscell.name == "Empty(Clone)") {
                     continue;
                 }
                 //匹配数量
                 ;
                 //x2 网格行上的最大索引
                 );
                 //x1 网格行内x格子右方的格子索引
                 int x1;
                 //遍历行中其余的格子
                 ;x1 <= x2;x1++) {
                     //如果是空物体或者名字不匹配,跳出循环
                     if(cells[x1,y].name == "Empty(Clone)" || thiscell.name != cells[x1,y].name) {
                         break;
                     }
                     //匹配数量加一
                     matchCount++;
                 }

                 //如果匹配数量大于等于2
                 ) {
                     //限制x1的最小值
                     x1 = Mathf.Min(cells.GetUpperBound(),x1 - );
                     //从x遍历到 x1,
                     for(var x3 = x;x3 <= x1;x3++) {
                         //将不重复的格子添加到数组中
                         if(!stack.Contains(cells[x3,y])) {
                             stack.Add(cells[x3,y]);
                         }
                     }
                 }
             }
         }
         return stack;
     }

     /// <summary>
     /// 交换动画
     /// </summary>
     void DoSwapMotion(Transform a,Transform b) {
         Vector3 posA = a.localPosition;
         Vector3 posB = b.localPosition;
         TweenParms parms = new TweenParms().Prop("localPosition",posB).Ease(EaseType.EaseOutQuart);
         HOTween.To(a,0.25f,parms).WaitForCompletion();
         parms = new TweenParms().Prop("localPosition",posA).Ease(EaseType.EaseOutQuart);
         HOTween.To(b,0.25f,parms).WaitForCompletion();
     }

     /// <summary>
     /// 交换网格在数组中的位置
     /// </summary>
     void DoSwapTile(GameObject a,GameObject b,ref GameObject[,] cells) {
         GameObject cell = cells[(int)a.transform.position.x,(int)a.transform.position.y];
         cells[(int)a.transform.position.x,(int)a.transform.position.y] = cells[(int)b.transform.position.x,(int)b.transform.position.y];
         cells[(int)b.transform.position.x,(int)b.transform.position.y] = cell;
     }

     /// <summary>
     /// 移动网格
     /// </summary>
     private void DoEmptyDown(ref GameObject[,] cells) { 

         //从左到右
         ;x <= cells.GetUpperBound();x++) {
             //从下到上
             ;y <= cells.GetUpperBound();y++) {
                 //当前网格
                 var thisCell = cells[x,y];
                 //如果是空网格
                 if(thisCell.name == "Empty(Clone)") {
                     //从下往上遍历y轴网格
                     );y2++) {
                         //如果不是空网格,交换
                         if(cells[x,y2].name != "Empty(Clone)") {
                             cells[x,y] = cells[x,y2];
                             cells[x,y2] = thisCell;
                             break;
                         }
                     }
                 }
             }
         }

         //从左到右
         ;x <= cells.GetUpperBound();x++) {
             //从下到上
             ;y <= cells.GetUpperBound();y++) {
                 //如果是空网格
                 if(cells[x,y].name == "Empty(Clone)") {
                     //删除空格子
                     Destroy(cells[x,y]);
                     //随机创建新格子
                     cells[x,y] = GameObject.Instantiate(_listOfGems[Random.Range(,_listOfGems.Length)] ) + ,),transform.rotation) as GameObject;
                 }
             }
         }

         //从左到右
         ;x <= cells.GetUpperBound();x++) {
             //从下到上
             ;y <= cells.GetUpperBound();y++) {
                 //将格子移动到指定位置
                 TweenParms parms = )).Ease(EaseType.EaseOutQuart);
                 HOTween.To(cells[x,y].transform,.4f,parms);
             }
         }
     }

     /// <summary>
     /// 创建闪烁特效
     /// </summary>
     void DoShapeEffect() {
         foreach(GameObject row in _currentParticleEffets) {
             Destroy(row);
         }
         ;i <= ;i++)
             _currentParticleEffets.Add(GameObject.Instantiate(_particleEffect,,_arrayOfShapes.GetUpperBound() + ),Random.Range(,_arrayOfShapes.GetUpperBound() + ),-),,,Random.Range(,1000f),)) as GameObject);
     }

 }

Main

视频:https://pan.baidu.com/s/1qXYv2Mw

项目:https://pan.baidu.com/s/1i55JGVj

Match 3 小项目学习的更多相关文章

  1. MOGRE学习笔记(3)--MOGRE小项目练习

    学习OGRE有一段时间了,领导为了检测学习效果,根据已有C++项目,弄一个类似的用c#语言编写的小项目. 配置:win7,DirectX2009,vs2010. 项目要求: 1.有Ogre窗口(尺寸1 ...

  2. 10分钟掌握Python-机器学习小项目

    学习机器学习相关技术的最好方式就是先自己设计和完成一些小项目. Python 是一种非常流行和强大的解释性编程语言.不像 R 语言,Python 是个很完整的语言和平台,你既可以用来做研发,也可以用来 ...

  3. 学习笔记之Python人机交互小项目一:名字管理系统

    2020是一个不平凡的一年,但即使挫折不断,我们每学期的课程实训也没有受到影响,仍旧如期实施.与往年不同的是,今年的实训老师是学校邀请的公司在职人员来给我们实训.今年实训的内容是Python语言,下面 ...

  4. 学习笔记之Python人机交互小项目二:名片管理系统

    继上次利用列表相关知识做了简单的人机交互的小项目名字管理系统后,当学习到字典时,老师又让我们结合列表和字典的知识,结合一起做一个名片管理系统,这里分享给在学习Python的伙伴! 1.不使用函数 1 ...

  5. Java学习笔记三十:Java小项目之租车系统

    Java小项目之租车系统 一:项目背景介绍: 根据所学知识,编写一个控制台版的“呱呱租车系统” 功能: 1.展示所有可租车辆: 2.选择车型.租车量: 3.展示租车清单,包含:总金额.总载货量以及其车 ...

  6. python3开发进阶-Django框架学习前的小项目(一个简单的学员管理系统)

    ''' 自己独立写一个学员管理系统 表结构: 班级表: -id -grade_name 学生表: -id -student_name -grade 关联外键班级表 老师表: -id -teacher_ ...

  7. Flask框架的学习与实战(二):实战小项目

    昨天写了一篇flask开发环境搭建,今天继续,进行一个实战小项目-blog系统. blog系统很简单,只有一个页面,然而麻雀虽小五脏俱全.这里目的不是为了做项目而做项目,这篇文章本意是通过这次练习传达 ...

  8. 【Arduino学习笔记05】Arduino数字输入、输出和脉冲宽带调制 -- 小项目:彩色小台灯

    基本功能: 长按控制按钮开机,长按控制按钮关机(>3s) 通过三个调节按钮调节灯的颜色,每一个按钮分别对应R,G,B值 模式切换:短按控制按钮切换模式(长亮模式/闪烁模式) 元器件清单: Ard ...

  9. 基于vue 、vue-router 、firebase的todolist小项目

    第一次写博客,都不知道改怎么写的好. 本着一颗学习的心,也希望一段时间后再回来在看看自己写的代码,会不会让自己有种不忍直视的念头 *-* 还是先上图吧~ 这是首页,主要是展示所有的列表页面,可以通过输 ...

随机推荐

  1. Android : 获取声卡信息的测试代码

    完整的编译包(android平台): 链接:http://pan.baidu.com/s/1qXMTT7I 密码:2bow /* * ALSA parameter test program * * C ...

  2. 7 Serial Configuration 理解(二)

    *Serial Configuration Mode 串行配置模式分为:Master Serial 和 Slave Serial (如下图)两类: 两者的区别在与CCLK的输入输出方向:主动模式下为输 ...

  3. 对FPGA的时钟资源理解(更新中)

    7系列FPGA中包含了多达24个CMT(时钟管理单元)(实际上V7常见只有20个),MMCM和PLL均为时钟综合器,对外部输入时钟.内部时钟进行处理,生成需要的低抖动时钟.PLL是MMCM的功能子集, ...

  4. DevExpress ASP.NET v18.2新功能详解(二)

    行业领先的.NET界面控件2018年第二次重大更新——DevExpress v18.2日前正式发布,本站将以连载的形式为大家介绍新版本新功能.本文将介绍了DevExpress ASP.NET Cont ...

  5. Map的isEmpty()与==null的区别

    isEmpty()方法判断Map是否有内容(即new分配空间后是否put键值对),若没有内容则true,否则false == null是判断map是否为null(即是否new分配空间,和其中的键值对没 ...

  6. GMT5.4.2 installation

    具体安装步骤参考seisman github gmt5.4.2或是GMT中文社区上的说明:这里只是补充一些可能出现问题的解决方法: 需要将具神标注的可选包也都安装上. 将cmake中的configue ...

  7. python 列表和元组

    一,基本的列表操作 1.该表列表,元素赋值 示例: >>>x = [1,1,1] >>>x[1] = 2 >>>x [1,2,1] 2.删除元素 ...

  8. JavaScript和它父亲的故事

    附赠脱单秘籍:了解一些JavaScript的历史,聊天的时候说不好可以获得更多程序员小妹子的崇拜的哟~ ๑乛◡乛๑~ 阅读本文可以让你更好的理解什么是ECMAScript. 本次文章内容来自:< ...

  9. 栈溢出原理与 shellcode 开发

     ESP:该指针永远指向系统栈最上面一个栈帧的栈顶  EBP:该指针永远指向系统栈最上面一个栈帧的底部 01  修改函数返回地址 #include<stdio.h> #include< ...

  10. CountDownLatch & CyclicBarrier

    CountDownLatch 在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待.用给它的代数初始化CountDownLatch,且计数器无法被重置.当前计数到达0之前,await方 ...