全部博文(921)
分类: 架构设计与优化
2015-05-12 21:13:11
先抛开网上的那些45度深度下的消隐算法。
开篇引章,在这我要先说说我的这个消隐算法的完成前的一个设想:
说这个设想前我们要说说这个设想要成立的一个条件:
【 Function :
getOnlyDepthFunc(target:DisplayObject,source:Array):Object】
target --物品列表中的某一物品。
source --物品列表(包含target)
这个条件方法的最终结果是要返回当前某一物品在一个物品列表中的 唯一确定深度 【itemDepth】以及除去了 target 的剩余物品列表【residualSource】。(可以不需考虑其他物品的深度变化,因为这里只关心target的深度,而事实上因为每次确定一个物品的深度时都有可能导致剩余物品的深度变化所以也是不需要考虑其他物品深度变化的)
好,先不要问这个方法怎么实现,具体实现下边会提到。下边说说我的这个算法的设想
假如现在有一个长度为n的物品列表
【sourceN:Array】,因为假设的已知条件方法【getOnlyDepthFunc】可以返回某一物品在物品列表中的确定深度,我们是否可以
通过逸代这个【getOnlyDepthFunc】方法
并且 参数target 以每次执行完后得到的剩余物品列表【residualSource】的某一个物品,source
则以每次执行完后得到的剩余物品列表【residualSource】去赋值,并且把每次得到的在该片段物品列表中target的唯一确定深度
【itemDepth】储存并整理还原为原物品列表
【sourceN:Array】所对应的物品深度,那么我们就应该可以得到最总我们想要的深度已经排好序的物品新数组了。
上边就是我的设想,这里为了方便大家理解,这里再点一下要注意的一些地方。方法【getOnlyDepthFunc】返回的深度只是参数source列表里的确定深度,但由于每次逸代的
剩余物品列表【residualSource】是总物品列表【sourceN】的剩余片段列表,所以他们存在一个耦合性。
处理上我是这么做的,在排序我前先声明一个跟【sourceN】一样长度的空数组【rebackSource】;然后从第一次开始,以第一次得到的深度为索引
,将索引对应的物品赋值给【rebackSource】数组对应的位上。然后逸代下一次。因为第2次开始已经是剩余物品列表。所以得出的深度【itemDepth】只是相对于每次返回的剩余物品列表
【residualSource】的对应唯一深度。但正因为是剩余物品列表,所以我们可以通过从开始项到得到的深度索引【itemDepth】项,不为undefiend的项数,来得到在总列表中的位置。也就是【residualSource】列表的具体项。然后把这次的target赋值给该位置。逸代一共执行品列表
【sourceN:Array】长度次。不用考虑效率,因为每次都是剩余列表的长度都在减少,而且不用排序,是一个高效的嵌套循环。
流程大致可以这样表示:
假设第一次的结果为3总物品数为6
【residualSource】=[undefined,undefined,undefined,【第一次的结果】,undefined,undefined,undefined]
.
.
第2次假设得到的结果也是3,这里因为这次的参数列表是剩余列表,也就只要在剩下的6个undefiend中找到第4个undefiend的位置就可以了(因为数组是从0开始的所以3其实相对于第4位)
【residualSource】=[undefined,undefined,undefined,【第一次的结果】,【第二次结果】,undefined,undefined]
.
.
第3次假设得到的结果是0
【residualSource】=[【第三次结果】,undefined,undefined,【第一次的结果】,【第二次结果】,undefined,undefined]
.
.
.
.
第7次结束
就这样一直逸代下去直到循环结束
优化:优化方法我采用的是2分法。
怎么个分法?就是当我们找到了第一个物品并确定了他的深度时,再对得到的前后两组内容进行以上的步骤,知道排序完毕。这样做有什么好处?一,我们可以大大节省下判断的循环的次数。二。当然是更加准确,但要注意的是,在我们得到结果时要怎么插值法,这个才是效率提高的关键点。
下边说说关键条件方法实现的原理
要实现这个方法有一个前提条件就是我们必须知道每个物品4个在45度视角下的边界方格位置(原因可看下边)。具体实现我就不说了,因为这样说也没完了,这里只是说原理。而且查找4边界方格位置也是做45度地图的基本工。
下边继续
怎么查找一个物品的唯一深度呢,实现也不难,就是确定一个是深度比自己小的
所有物品的数组dephtMin,或者深度比自己大的多有物品的数组depthMax数组
这样就可以知道该物品的深度了。该物品的深度就是
dephtMin元素个数加1,或者depthMax元素个数减一
方法可以用9宫格法
怎么实现9宫格法,途径很多种,我用的是通过不断推敲得到的算法,下边是参考片段
简要说明下
{[L]}{x,y}{[T]}
{x,y}{x,y}{x,y}
{[B]}{x,y}{[R]}
[L],[T],[R],[B]对应一个物品的4个45度下的边界坐标点也就是我之前说的【getOnlyDepthFunc】方法必要的条件
item是【getOnlyDepthFunc】循环 列表的非target的对象,
target为【getOnlyDepthFunc】的target参数
公式:
item.sideR=(target.[B].y-item.[L].y)
item.sideL=(item.[B].y-target.[L].y)
item.sideB=(target.[T].x-item.minZ.[L].x)
item.sideT=(item.[T].x-target.[L].x)
当item.sideR<0时,item于target的右边;
当item.sideL<0时,item于target的左边;
当item.sideT<0时,item于target的上边;
当item.sideB<0时,item于target的下边;
当item.sideL<0且item.sideT<0时,item于target的左上边;
当item.sideL<0且item.sideB<0时,item于target的左下边;
当item.sideR<0且item.sideT<0时,item于target的右上边;
当item.sideR<0且item.sideB<0时,item于target的右下边;
当上边4值任意为-1时,target于item的对应边界
通过这个算法,我们就可以简易的确定出以target为中心的相对于target与物品列表其他物品位置关系的一个9宫格分布了。也就是下边的图示
得到了这个9宫格然后怎么办了,这里再罗嗦下 45度下的深度排布,也就是画家算法的基本原理;
{6}{3}{0}
{7}{4}{1}
{8}{5}{2}
45度下的物品深度由低到高应该是这样的。越越视角深度越低,越高视角深度则越高
像上边的图示,target应该的位置就是{4} 而之前我们提到的两个数组dephtMin 跟dephtMax
就应该等于
dephtMin
=【{0},{1},{2},{3}】
dephtMax=【{5},{6},{7},{8}】
当然这两个数组的个数根据我上边给出的公式得到的具体数目决定,
好了教程到此结束,不明白的地方可以回复或者,mes 我,
欢迎大家谈论,还有上边的设想我是已经实现的了碍与项目保密性就不发例子了,但可以说效果很好,所以特发此教程跟大家一起分享下 要转载的请表明下谢谢
原文链接