Match 3 小项目学习

  1 using UnityEngine;
  2 using System.Collections;
  3 using Holoville.HOTween;
  4
  5 /// <summary>
  6 /// 游戏逻辑
  7 /// </summary>
  8 public class Main:MonoBehaviour {
  9
 10     /// <summary>
 11     /// 点击框预设
 12     /// </summary>
 13     public GameObject _indicator;
 14     /// <summary>
 15     /// 二维方块数组
 16     /// </summary>
 17     public GameObject[,] _arrayOfShapes;
 18     /// <summary>
 19     /// 当前点击框
 20     /// </summary>
 21     private GameObject _currentIndicator;
 22     /// <summary>
 23     /// 第一个选择的物体
 24     /// </summary>
 25     private GameObject _FirstObject;
 26     /// 第二个选择的物体
 27     /// </summary>
 28     private GameObject _SecondObject;
 29     /// <summary>
 30     /// 方块预设列表
 31     /// </summary>
 32     public GameObject[] _listOfGems;
 33     /// <summary>
 34     /// 空物体
 35     /// </summary>
 36     public GameObject _emptyGameobject;
 37     /// <summary>
 38     /// 星星特效
 39     /// </summary>
 40     public GameObject _particleEffect;
 41     /// <summary>
 42     /// 匹配时的特效
 43     /// </summary>
 44     public GameObject _particleEffectWhenMatch;
 45     /// <summary>
 46     /// 能否在对角线上转换
 47     /// </summary>
 48     public bool _canTransitDiagonally = false;
 49     /// <summary>
 50     /// 每次匹配时的增长分数
 51     /// </summary>
 52     public int _scoreIncrement;
 53     /// <summary>
 54     /// 总分
 55     /// </summary>
 56     private int _scoreTotal = 0;
 57     /// <summary>
 58     /// 当前特效
 59     /// </summary>
 60     private ArrayList _currentParticleEffets = new ArrayList();
 61     /// <summary>
 62     /// 匹配时的声音
 63     /// </summary>
 64     public AudioClip MatchSound;
 65     /// <summary>
 66     /// 网格x轴上的格子数量
 67     /// </summary>
 68     public int _gridWidth;
 69     /// <summary>
 70     /// 网格y轴上的格子数量
 71     /// </summary>
 72     public int _gridHeight;
 73
 74
 75     void Start() {
 76         //为2维方块数组分配内存
 77         _arrayOfShapes = new GameObject[_gridWidth,_gridHeight];
 78
 79
 80         //从左到右,从下到上创建格子
 81         for(int i = 0;i <= _gridWidth - 1;i++) {
 82             for(int j = 0;j <= _gridHeight - 1;j++) {
 83                 //var gameObject = GameObject.Instantiate(_listOfGems[Random.Range(0,_listOfGems.Length)] as GameObject,new Vector3(i,j,0),transform.rotation) as GameObject;
 84
 85                 GameObject gameObject = null;
 86                 if(j <= 2) {
 87                     gameObject = GameObject.Instantiate(_listOfGems[0] as GameObject,new Vector3(i,j,0),transform.rotation) as GameObject;
 88                 } else if(j <= 5) {
 89                     gameObject = GameObject.Instantiate(_listOfGems[1] as GameObject,new Vector3(i,j,0),transform.rotation) as GameObject;
 90                 } else {
 91                     gameObject = GameObject.Instantiate(_listOfGems[2] as GameObject,new Vector3(i,j,0),transform.rotation) as GameObject;
 92                 }
 93                 _arrayOfShapes[i,j] = gameObject;
 94             }
 95         }
 96         //Adding the star effect to the gems and call the DoShapeEffect continuously
 97         //InvokeRepeating("DoShapeEffect",1f,0.21F);
 98
 99     }
100
101     void Update() {
102         //是否转换
103         bool shouldTransit = false;
104         //当用户点击按钮且没有动画
105         if(Input.GetButtonDown("Fire1") && HOTween.GetTweenInfos() == null) {
106             //销毁当前选择框
107             Destroy(_currentIndicator);
108             //生成从屏幕中心点到鼠标点击位置的射线
109             Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
110             //发射射线
111             RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition),Vector2.zero);
112             //如果射线碰到物体
113             if(hit.transform != null) {
114                 //第一个选择的物体为空
115                 if(_FirstObject == null) {
116                     //将点击的物体设置为第一个选择物体
117                     _FirstObject = hit.transform.gameObject;
118                 //如果第一个选择的物体不为空
119                 } else {
120                     //将点击的物体设置为第二个选择物体
121                     _SecondObject = hit.transform.gameObject;
122                     //可以转换
123                     shouldTransit = true;
124                 }
125
126                 //根据点击位置创建选择框
127                 _currentIndicator = GameObject.Instantiate(_indicator,new Vector3(hit.transform.gameObject.transform.position.x,hit.transform.gameObject.transform.position.y,-1),transform.rotation) as GameObject;
128                 //如果可以转换
129                 if(shouldTransit) {
130                     //获取两个物体之间的距离
131                     var distance = _FirstObject.transform.position - _SecondObject.transform.position;
132                     //如果x,y的距离 都小于等于1
133                     if(Mathf.Abs(distance.x) <= 1 && Mathf.Abs(distance.y) <= 1) {
134                         //如果不能在斜线上交换
135                         if(!_canTransitDiagonally) {
136                             //
137                             if(distance.x != 0 && distance.y != 0) {
138                                 //销毁选择框
139                                 Destroy(_currentIndicator);
140                                 _FirstObject = null;
141                                 _SecondObject = null;
142                                 return;
143                             }
144                         }
145                         //播放交换动画
146                         DoSwapMotion(_FirstObject.transform,_SecondObject.transform);
147                         //交换在数组中的位置
148                         DoSwapTile(_FirstObject,_SecondObject,ref _arrayOfShapes);
149                     //如果不能转换
150                     } else {
151                         _FirstObject = null;
152                         _SecondObject = null;
153
154                     }
155                     //销毁选择框
156                     Destroy(_currentIndicator);
157
158                 }
159
160             }
161
162         }
163
164
165         //如果没有播放动画
166         if(HOTween.GetTweenInfos() == null) {
167             //查找匹配的格子
168             var Matches = FindMatch(_arrayOfShapes);
169             //如果找到匹配的格子
170             if(Matches.Count > 0) {
171                 //更新分数
172                 _scoreTotal += Matches.Count * _scoreIncrement;
173
174                 //遍历匹配物体
175                 foreach(GameObject go in Matches) {
176                     //播放匹配声音
177                     GetComponent<AudioSource>().PlayOneShot(MatchSound);
178                     //创建匹配特效
179                     var destroyingParticle = GameObject.Instantiate(_particleEffectWhenMatch as GameObject,new Vector3(go.transform.position.x,go.transform.position.y,-2),transform.rotation) as GameObject;
180                     //1秒后销毁特效
181                     Destroy(destroyingParticle,1f);
182                     //用空物体替换匹配物体
183                     _arrayOfShapes[(int)go.transform.position.x,(int)go.transform.position.y] = GameObject.Instantiate(_emptyGameobject,new Vector3((int)go.transform.position.x,(int)go.transform.position.y,-1),transform.rotation) as GameObject;
184                     //0.1秒后删除匹配物体
185                     Destroy(go,0.1f);
186                 }
187                 _FirstObject = null;
188                 _SecondObject = null;
189
190                 DoEmptyDown(ref _arrayOfShapes);
191             }
192             //如果没有找到格子,将格子的位置复位
193             else if(_FirstObject != null && _SecondObject != null) {
194                 //播放交换动画
195                 DoSwapMotion(_FirstObject.transform,_SecondObject.transform);
196                 //交换格子位置
197                 DoSwapTile(_FirstObject,_SecondObject,ref _arrayOfShapes);
198                 _FirstObject = null;
199                 _SecondObject = null;
200             }
201         }
202
203         //更新分数
204         (GetComponent(typeof(TextMesh)) as TextMesh).text = _scoreTotal.ToString();
205     }
206
207     /// <summary>
208     /// 查找匹配
209     /// </summary>
210     /// <param name="cells"></param>
211     /// <returns></returns>
212     private ArrayList FindMatch(GameObject[,] cells) {
213         //存储匹配的方块数组
214         ArrayList stack = new ArrayList();
215         //将列上至少3个颜色相同的方块放进数组中
216         //从左到右
217         for(var x = 0;x <= cells.GetUpperBound(0);x++) {
218             //从下到上
219             for(var y = 0;y <= cells.GetUpperBound(1);y++) {
220                 //当前网格
221                 var thiscell = cells[x,y];
222                 //如果是空物体,忽略
223                 if(thiscell.name == "Empty(Clone)") {
224                     continue;
225                 }
226                 //匹配数量
227                 int matchCount = 0;
228                 //y2 网格列上的最大索引
229                 int y2 = cells.GetUpperBound(1);
230                 //y1 网格列内y格子上方的格子索引
231                 int y1;
232                 //遍历列中其余的格子
233                 for(y1 = y + 1;y1 <= y2;y1++) {
234                     //如果是空物体或者名字不匹配,跳出循环
235                     if(cells[x,y1].name == "Empty(Clone)" || thiscell.name != cells[x,y1].name) {
236                         break;
237                     }
238
239                     //匹配数量加一
240                     matchCount++;
241                 }
242
243                 //如果匹配数量大于等于2
244                 if(matchCount >= 2) {
245                     //限制y1的最小值
246                     y1 = Mathf.Min(cells.GetUpperBound(1),y1 - 1);
247                     //从 y遍历到 y1,
248                     for(var y3 = y;y3 <= y1;y3++) {
249                         //将不重复的格子添加到数组中
250                         if(!stack.Contains(cells[x,y3])) {
251                             stack.Add(cells[x,y3]);
252                         }
253                     }
254                 }
255             }
256         }
257
258
259         //将行上至少3个颜色相同的方块放进数组中
260         //从下到上
261         for(var y = 0;y < cells.GetUpperBound(1) + 1;y++) {
262             //从左到右
263             for(var x = 0;x < cells.GetUpperBound(0) + 1;x++) {
264                 //当前网格
265                 var thiscell = cells[x,y];
266                 //如果是空物体,忽略
267                 if(thiscell.name == "Empty(Clone)") {
268                     continue;
269                 }
270                 //匹配数量
271                 int matchCount = 0;
272                 //x2 网格行上的最大索引
273                 int x2 = cells.GetUpperBound(0);
274                 //x1 网格行内x格子右方的格子索引
275                 int x1;
276                 //遍历行中其余的格子
277                 for(x1 = x + 1;x1 <= x2;x1++) {
278                     //如果是空物体或者名字不匹配,跳出循环
279                     if(cells[x1,y].name == "Empty(Clone)" || thiscell.name != cells[x1,y].name) {
280                         break;
281                     }
282                     //匹配数量加一
283                     matchCount++;
284                 }
285
286                 //如果匹配数量大于等于2
287                 if(matchCount >= 2) {
288                     //限制x1的最小值
289                     x1 = Mathf.Min(cells.GetUpperBound(0),x1 - 1);
290                     //从x遍历到 x1,
291                     for(var x3 = x;x3 <= x1;x3++) {
292                         //将不重复的格子添加到数组中
293                         if(!stack.Contains(cells[x3,y])) {
294                             stack.Add(cells[x3,y]);
295                         }
296                     }
297                 }
298             }
299         }
300         return stack;
301     }
302
303     /// <summary>
304     /// 交换动画
305     /// </summary>
306     void DoSwapMotion(Transform a,Transform b) {
307         Vector3 posA = a.localPosition;
308         Vector3 posB = b.localPosition;
309         TweenParms parms = new TweenParms().Prop("localPosition",posB).Ease(EaseType.EaseOutQuart);
310         HOTween.To(a,0.25f,parms).WaitForCompletion();
311         parms = new TweenParms().Prop("localPosition",posA).Ease(EaseType.EaseOutQuart);
312         HOTween.To(b,0.25f,parms).WaitForCompletion();
313     }
314
315
316     /// <summary>
317     /// 交换网格在数组中的位置
318     /// </summary>
319     void DoSwapTile(GameObject a,GameObject b,ref GameObject[,] cells) {
320         GameObject cell = cells[(int)a.transform.position.x,(int)a.transform.position.y];
321         cells[(int)a.transform.position.x,(int)a.transform.position.y] = cells[(int)b.transform.position.x,(int)b.transform.position.y];
322         cells[(int)b.transform.position.x,(int)b.transform.position.y] = cell;
323     }
324
325     /// <summary>
326     /// 移动网格
327     /// </summary>
328     private void DoEmptyDown(ref GameObject[,] cells) {
329
330         //从左到右
331         for(int x = 0;x <= cells.GetUpperBound(0);x++) {
332             //从下到上
333             for(int y = 0;y <= cells.GetUpperBound(1);y++) {
334                 //当前网格
335                 var thisCell = cells[x,y];
336                 //如果是空网格
337                 if(thisCell.name == "Empty(Clone)") {
338                     //从下往上遍历y轴网格
339                     for(int y2 = y;y2 <= cells.GetUpperBound(1);y2++) {
340                         //如果不是空网格,交换
341                         if(cells[x,y2].name != "Empty(Clone)") {
342                             cells[x,y] = cells[x,y2];
343                             cells[x,y2] = thisCell;
344                             break;
345                         }
346                     }
347                 }
348             }
349         }
350
351         //从左到右
352         for(int x = 0;x <= cells.GetUpperBound(0);x++) {
353             //从下到上
354             for(int y = 0;y <= cells.GetUpperBound(1);y++) {
355                 //如果是空网格
356                 if(cells[x,y].name == "Empty(Clone)") {
357                     //删除空格子
358                     Destroy(cells[x,y]);
359                     //随机创建新格子
360                     cells[x,y] = GameObject.Instantiate(_listOfGems[Random.Range(0,_listOfGems.Length)] as GameObject,new Vector3(x,cells.GetUpperBound(1) + 2,0),transform.rotation) as GameObject;
361                 }
362             }
363         }
364
365         //从左到右
366         for(int x = 0;x <= cells.GetUpperBound(0);x++) {
367             //从下到上
368             for(int y = 0;y <= cells.GetUpperBound(1);y++) {
369                 //将格子移动到指定位置
370                 TweenParms parms = new TweenParms().Prop("position",new Vector3(x,y,-1)).Ease(EaseType.EaseOutQuart);
371                 HOTween.To(cells[x,y].transform,.4f,parms);
372             }
373         }
374     }
375
376     /// <summary>
377     /// 创建闪烁特效
378     /// </summary>
379     void DoShapeEffect() {
380         foreach(GameObject row in _currentParticleEffets) {
381             Destroy(row);
382         }
383         for(int i = 0;i <= 2;i++)
384             _currentParticleEffets.Add(GameObject.Instantiate(_particleEffect,new Vector3(Random.Range(0,_arrayOfShapes.GetUpperBound(0) + 1),Random.Range(0,_arrayOfShapes.GetUpperBound(1) + 1),-1),new Quaternion(0,0,Random.Range(0,1000f),100)) as GameObject);
385     }
386
387
388 }

Main

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

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

时间: 2024-10-13 18:01:25

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

ios学习笔记图片+图片解释(c语言 oc语言 ios控件 ios小项目 ios小功能 swift都有而且笔记完整喔)

下面是目录其中ios文件夹包括了大部分ios控件的介绍和演示,swift的时完整版,可以学习完swift(这个看的是swift刚出来一周的视频截图,可能有点赶,但是完整),c语言和oc语言的也可以完整的学习完所需知识,,其他文件夹的内容如其名说描述一样 没张图片都有文字说明,可以需要该功能的时候搜索一下然后打开图片就可以学习到 网盘下载地址:需要的话给留言我再传上去 http://www.cnblogs.com/langtianya原创 ios学习笔记图片+图片解释(c语言 oc语言 ios控件

Java Web学习(33): 阶段小项目使用MVC模型实现购物车效果

项目概述 前面的时候我写过一个商品浏记录的小例子,这一次我们使用实现购物车效果.前面的例子是: http://blog.csdn.net/erlian1992/article/details/52047258.这一次在此基础上来采用的是MVC三层模型实现 (JSP+Servlet+dao)来实现这个小项目. 三层架构: JSP视图层 Servlet控制层 dao模型层 DB数据库层 编码实现: 首先先来数据库脚本items.sql: /* Navicat MySQL Data Transfer

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

''' 自己独立写一个学员管理系统 表结构: 班级表: -id -grade_name 学生表: -id -student_name -grade 关联外键班级表 老师表: -id -teacher_name -grades (多对多 关联班级表) ''' 在写小项目之前我们先复习一下小知识: 1. form表单提交数据的注意事项: 是form不是from,必须要有method和action 所有获取用户输入的表单标签要放在form表单里面,表单标签必须要有name属性 form表单必须要有su

Android开发不得不看的11个实战小项目

是不是想学Android开发(http://www.maiziedu.com/course/android-px/)却不知道如何下手?懂得一点点入门基础知识却无法应用到实际开发中?看相关资料觉得都懂了实际动手却发现什么都不懂?本地搭建Android开发环境太麻烦? 如果你有以上的各种问题,那么今天小编推荐的Android开发的这11个小项目,你一定要看!! 因为,这些实战项目都是基于google 官方的API Demos制作而成,而且全部配有Android在线开发环境,你可以随时动手跟着课程操作

大四下学期小项目实习总结

小项目:智能家居家电控制面板 时间:2015年4月23号~2015年6月24号,为期两个月 总结:是否认真?0.5 是否具有挑战性?0.1 是否学习到了方法?0.5 是否还可以做得更好?1.0

【招募】golang小项目

最近想用golang写一个小项目: 语言:golang 目标:学习完golang,必须有小项目练手 招募期限:截止到2017年3月28日 人数:4~5人 内容:对标barbican内容 报名方式:直接私信给我

一个特别适合新手练习的Android小项目——每日一妹纸

介绍 每天更新一张精选妹纸图片,第一版目前已完成,本项目会持续更新,遇到任何问题欢迎与我联系^_^ 为什么说这是一个特别适合新手练习的小项目? 服务器API接口功能丰富且无访问次数限制 包含了常见的网络通信,数据缓存等功能 使用了流行的Realm,Retrofit,Glide,Butterknife等开源项目,方便新手学习他们的使用 遵循Material Design规则 示例 项目当然是开源的啦,源码请戳下面的链接 https://github.com/SparkYuan/Meizi ----

ACCESS(VBA)上的一个小项目 —— 2、读取ACCESS表数据到TreeView和ListView

有人问我能不能做一个程序的时候,我第一反应都说“能”. --这次在ACCESS中,借助TreeView和ListView做了一个数据联动的模型. 简析过程: 1)从网上找了一份TreeView学习教程<三小时学会树控件>,了解了TreeView的建立以及节点的使用方法: 2)把数据表中的某列按一定规则生成的数据再按一种规则解析成TreeView中的树结构(VPPS): 3)通过遍历TreeView中节点的折叠状态,通过上述一定规则生成的数据(唯一性)把数据表中的内容读取到ListView中:

小项目创意大集合

每个程序员都可以入手的小项目创意大集合 我经常看有人发帖问关于软件项目创意点子的事,也看到了很多回帖,我自己也回了一些常见的软件项目创意.不过我觉得只列出三两个是远远不够的,因此就收集并这个软件项目创意列表,大家要找简单的编程软件项目创意学习练手的话,可以收藏并扩散本文.这些软件项目创意并不是论文级别的,只是想抛砖引玉让大家能从中受些启发. 下面你们会看到 120 多个个软件项目创意想法,都是我通过头脑风暴得来的.我将其根据主题分成了10 个分类,但有些软件项目创意其实涵盖了不止一个主题. 更新