近期用unity3d引擎做了一个拼图游戏,会分几次写完,以此作为总结。

本文基本查找了网上能查到的全部资料作为參考。也算是大家节省了时间。

眼下仅仅完毕了拼图部分,leap motion手势控制部分会在兴许完毕,只是说实话不太看好LM。

项目资源来自 cube454517408 http://blog.csdn.net/cube454517408/article/details/7907247,只是玩法不同,玩法与小夭 

tid=2852">http://game.ceeger.com/forum/read.php?

tid=2852同样。我也重写了前者的程序。部分实现思路不同,两个游戏的project在本文完毕后都会打包上传。

http://download.csdn.net/detail/smilingeyes/8234627

首先是整个游戏须要的模块。

一个拼图游戏大致须要例如以下几个控制模块:碎片显示,碎片随机打乱。随机排序后碎片顺序的合法性检查。移动控制,拼图是否完毕的检查。

游戏实现的思路为。建立N*N个plane。通过控制每一个plane的材质球贴图偏移形成碎片,最后一个plane使用透明贴图。使用数组纪录每一个碎片的偏移位置,和碎片的排列顺序。

移动碎片时。plane位置不发生变化。变化的是此plane贴图的偏移(详见第一部分碎片显示)。

一、碎片显示。

此部分能够有几种选择,第一个就是将每部分碎片单独做成图片,比方这个

http://tieba.baidu.com/p/2053275362   优点是处理比較方便,能够使用GUI处理,缺点是每一个图片都须要前期处理,并且因为前期分片的份数固定,游戏难度不能任意调整,除非每一个图都准备非常多不同难度的切割后的小图。

第二是使用NGUI中的Atlas,对图集中的sprite信息进行重定义。详细參考小夭的程序。当中用到了UISprite类中的outer结构体,outer记录了sprite在图集中的位置信息。可是在NGUI3.6版本号中outer已经不是UISprite的成员变量,是否还能用文中的方法进行改动没有尝试。假设有人尝试请留言告知,在此谢过。

第三是在材质球中设置纹理偏移和缩放,详细做法參考上面cube454517408的帖子。本人也是用的此种方法。

第二和第三种实现方法的优点是能够任意调整图片分成的份数,因此能够非常方便的调整游戏难度。

<span style="font-size:18px;">	Vector2 offset;				\\记录每一块碎片的偏移
offset.x = origin.x + piecesLength * j;
offset.y = origin.y - piecesLength * i;
temp.transform.localPosition = new Vector3 (offset.x*10f,offset.y*10f);
texOffset[k].x = j*transform.localScale.x/row; \\计算纹理偏移
texOffset[k].y = (row-1-i)*transform.localScale.x/row;
temp.renderer.material.mainTextureOffset = texOffset[k]; \\设置纹理偏移
temp.renderer.material.mainTextureScale = new Vector2(transform.localScale.x/row,transform.localScale.x/row); \\设置纹理缩放</span>

由于图源为正方形。所以仅仅考虑了将其分为N*N块的分法,因此偏移和缩放的计算较为简单。

	void Display()
{
for (int i = 0; i < pieces.Length; i++) {
pieces[i].renderer.material.mainTextureOffset = texOffset[squence[i]];
pieces[i].renderer.enabled = isReander[squence[i]];
}
}

void Update ()的最后调用Display(),isRender数组保存了该碎片贴图是否显示,texOffset数组保存了每一个碎片贴图的偏移位置。

碎片显示部分就这么多内容,以下是碎片打乱算法。

二、碎片打乱算法

这里有两种不同的思路。第一种是小夭採用的,将正确排列的碎片随机移动若干次。以达到打乱碎片顺序的目的。该方法的优点是,用这样的方法生成的随机序列一定能够还原,缺点是实现起来较为复杂。详细实现见小夭的文章。

另外一种思路是採用洗牌算法,使用一个数组保存第N个碎片的纹理偏移,从第一个碎片開始与随机一个碎片交换内容,直到数组结束。算法实现起来比較简单,可是并不一定保证能够正确还原。

	void Shuffle()
{
Random.seed = System.Environment.TickCount;
for (int i = 0; i < squence.Length - 1; i++) {
int temp = squence[i];
int randomIndex = Random.Range(0, squence.Length-1);
squence[i] = squence[randomIndex];
squence[randomIndex] = temp;
}
}

三、逆序和检验

通过洗牌算法得到的随机序列,并不一定能够还原成初始的顺序。这是由于在洗牌时改变了数组的逆序和。參加百度百科(不可还原的拼图)……http://baike.baidu.com/link?

url=2ajCBRlh6Ox1I1SPK8gEayd-aAaCITNNQjVSA09qDHDLXZM9Ndrp-thdWdjg-Xt_sRk3PCABt-3LUPDKfTZDy_

lemene对此进行了证明。喜欢数学证明的同学请见 http://www.cppblog.com/lemene/archive/2007/10/04/33405.html

shaomn的解说比較easy明确。http://blog.sina.com.cn/s/blog_4ed8b87701011c6x.html

对于数组squence[],定义其逆序和为sum += (i - j) * (squence [i] - squence [j]) > 0 ? 0 : 1;对于初始序列其逆序和为0,左右移动碎片时sum不变,上下移动时sum +2、-2或不变,可是不管如何移动。逆序和奇偶性是不变的。因此在洗牌算法之后,检验数组逆序和是否为偶数就可以。

	bool Check()
{
int sum = 0;
for (int i = 0; i < squence.Length; i++)
for (int j = 0; j < i; j++)
sum += (i - j) * (squence [i] - squence [j]) > 0 ? 0 : 1;
return sum % 2 == 1;
}

四、移动控制

移动控制有两种思路,第一种是鼠标点击想要移动的碎片,检測碎片周围是否有空位置,假设有交换位置。

另外一种是按方向键。检測空位置周围是否有能够向按键方向移动的碎片。假设有交换位置。全然能够同一时候实现。本文仅仅实现了另外一种。由于要结合leap motion。另外一种操作方式和手势控制比較接近。

		if (Input.GetKeyDown ("left")) {
MoveLeft();
}
if (Input.GetKeyDown ("right")) {
MoveRight();
}
if (Input.GetKeyDown ("down")) {
MoveDown();
}
if (Input.GetKeyDown ("up")) {
MoveUp();
}

其它移动函数与之类似。不一样的是推断条件。首先找到空白碎片(也就是开局时最后一个碎片)当前在的碎片队列中的顺序。将之与要移动的碎片交换在队列中的位置。

	void MoveLeft()
{
int last,temp;
last = FindLastPiece();
if(last%row < row-1)
{
temp = squence[last];
squence[last] = squence[last+1];
squence[last+1] = temp;
}
}
	int FindLastPiece()
{
int i=0;
while(squence[i]!=squence.Length-1)
{
i++;
}
return i;
}

使用leap motion进行手势控制在实现时採用了比較简单的逻辑,仅仅适用于本游戏。假设同一时候须要进行其它手势的推断则须要设计其它的约束条件。此处逻辑为推断手掌移动速度,超过某个方向的最大速度则推断为使碎片向该方向移动。leap motion 与unity结合开发的设置不再介绍。

为了降低误判,设置了一个控制是否启用手势控制的变量update,在检測到手势的0.5s内暂停手势控制。

		Leap.Hand hand = LeapControl.Hand; 

		if (hand != null && update) {

			if (hand.PalmVelocity.x > minVelocity)
{
MoveRight();
update = false;
Invoke("SetUpdate",0.5f);
}
if (hand.PalmVelocity.x < -minVelocity)
{
MoveLeft();
update = false;
Invoke("SetUpdate",0.5f);
}
if (hand.PalmVelocity.y > minVelocity)
{
MoveUp();
update = false;
Invoke("SetUpdate",0.5f);
}
if (hand.PalmVelocity.y < -minVelocity)
{
MoveDown();
update = false;
Invoke("SetUpdate",0.5f);
}
}

五、游戏结束检測

在每次移动过后,检測是否完毕。

	bool Finish()
{
int i=0;
while (i < squence.Length && i == squence[i])
{
i++;
}
if (i == squence.Length) {
Debug.Log("finish!");
return true;
} else
return false;
}


基于unity3d和leap motion的拼图游戏的更多相关文章

  1. Unity3D中使用Leap Motion进行手势控制

    Leap Motion作为一款手势识别设备,相比于Kniect,长处在于准确度. 在我的毕业设计<场景漫游器>的开发中.Leap Motion的手势控制作为重要的一个环节.以此,谈谈开发中 ...

  2. 基于unity3d游戏的android版本逆向初探

    https://bbs.pediy.com/thread-212532.htm [文章标题]: 基于unity3d游戏的android版本逆向初探 [文章作者]: dreaman [作者邮箱]: [e ...

  3. 介绍用C#和VS2015开发基于Unity架构的2D、3D游戏的技术

    [Unity]13.3 Realtime GI示例 摘要: 分类:Unity.C#.VS2015 创建日期:2016-04-19 一.简介 使用简单示例而不是使用实际示例的好处是能让你快速理解光照贴图 ...

  4. 利用Vue.js实现拼图游戏

    之前写过一篇<基于Vue.js的表格分页组件>的文章,主要介绍了Vue组件的编写方法,有兴趣的可以访问这里进行阅读:http://www.cnblogs.com/luozhihao/p/5 ...

  5. 基于Unity3D 的Vuforia SDK开发基础教程

    最新博客地址已转到: http://blog.csdn.net/zzlyw?viewmode=contents   ------------------------------------------ ...

  6. JavaScript写一个拼图游戏

    拼图游戏的代码400行, 有点多了, 在线DEMO的地址是:打开: 因为使用canvas,所以某些浏览器是不支持的: you know: 为什么要用canvas(⊙o⊙)?  因为图片是一整张jpg或 ...

  7. Leap Motion发布新平台,直击下一代移动端VR/AR手部追踪

    2013年,动作捕捉技术公司Leap Motion发布了面向PC的体感控制器,不过销量并不乐观.随着2014年虚拟现实技术的再一次兴起,它发布一款用于Oculus Rift的附加设备,从而正式登上VR ...

  8. atitit.html5 拼图游戏的解决之道.

    atitit.html5 拼图游戏的解决之道. 1. 拼图游戏的操作(点击法and 拖动法) 1 1. 支持键盘上.下.左.右键移动: 1 2. 支持点击空白模块中的上下左右箭头移动: 1 3. 支持 ...

  9. Vue.js实现拼图游戏

    Vue.js实现拼图游戏 之前写过一篇<基于Vue.js的表格分页组件>的文章,主要介绍了Vue组件的编写方法,有兴趣的可以访问这里进行阅读:http://www.cnblogs.com/ ...

随机推荐

  1. iOS系统自带的 UIAlertView 自动旋转的实现

    这里主要解析 UIAlertView 的几个关键功能的实现: 随着设备屏幕的旋转而旋转: Alert弹出框,使用UIWindow来实现,就是说,不用依赖于当前显示在最前面的UIView. 实现源码参考 ...

  2. C#学习之------委托

    1.向窗体中添加控件的最少步骤:                 窗体的句柄为this private System.Windows.Forms.Button button1;             ...

  3. [Swust OJ 137]--波浪数(hash+波浪数构造)

    题目链接:http://acm.swust.edu.cn/problem/137/ Time limit(ms): 1000 Memory limit(kb): 65535   Description ...

  4. cURL实现get、post请求

    1.cURL介绍 cURL 是一个利用URL语法规定来传输文件和数据的工具,支持很多协议,如HTTP.FTP.TELNET等.最爽的是,PHP也支持 cURL 库.本文将介绍 cURL 的一些高级特性 ...

  5. 基于FPGA的DW8051移植(一)

    最近 半个月都在移植8051,看到DW8051内核资料比较齐全又是新思发布的,所以就开始玩弄 可是这半个月的努力几近白费 —— 移植失败了,不知道从何着手这个内核.可能大家能找到不同的版本,我的是最初 ...

  6. hibernate对应的annocation版本

    Hibernate Compatibility Matrix Package Version Core Annotations EntityManager Validator Search Shard ...

  7. 分享一个 CSDN 自动评论角本

    先修改帐户名和密码 import requests from BeautifulSoup import BeautifulSoup import time def commitfunc(source_ ...

  8. hdu-4302-Holedox Eating-线段树-单点更新,有策略的单点查询

    一開始实在是不知道怎么做,后来经过指导,猛然发现,仅仅须要记录某个区间内是否有值就可以. flag[i]:代表i区间内,共同拥有的蛋糕数量. 放置蛋糕的时候非常好操作,单点更新. ip:老鼠当前的位置 ...

  9. INS-30001 ADMIN口令为空

    1.错误描写叙述 2.错误原因 管理口令为空.导致出错 3.解决的方法 填写管理口令和确认口令

  10. ACM第三次比赛UVA11877 The Coco-Cola Store

      Once upon a time, there is a special coco-cola store. If you return three empty bottles to the sho ...