前面的随笔提到了地图加载的方法,就把原来写的这个方法贴过来

发发自己关于写地图加载的思想

---------------前言,用来申明一些东西 避免不必要的麻烦------------------

1.为什么写这些?

今天开会,听同事主讲了<怎么样写出高质量代码?>.里面同事说到了"仿照国外的博客,公开自己写的有意思的代码或者思想"等等的建议.

因为很佩服他所讲的这些,所以决定尝试下 抛玉引砖 ,不再潜水了.

顺便记录一下自己的编程成长经历.

2.抛玉引砖

抛出自己认为是玉的那部分,当然也希望在别人眼里也能够是玉.或者通过别人指点,能将这个璞玉雕琢的更加完美.

3.绪论

主要写一下地图的加载算法和想法.本人接触AS3 比较晚,去年7月毕业后才开始接触,到现在快满一年了.所以对AS 甚至编程中的很多东西都不明了,希望高手能指点.

最开始的地图算法是去年8月参照一个策划的方法(多加载一行一列地图切片,移动时将最左边不用的移动到最右边更新)写的,然后自创了一套新的制作思想(关键字 做标记)和算法.

这套方法 做个简单的比喻下就是拿代数题的方法去解决几何问题.

这个思想 初中老师就已经教过了,所以非常简单

比如用代数方法解决几何学题目

I.建立直角坐标系

II.利用三角函数进行计算解题

 

准备分A,B两个部分写 A: 1.地图的预加载; (纯粹的多加载一圈地图切片)

                                       2.地图的移动; (这里就讲我自己想到的方法)

                                       3. 极限值 ;  (利用极限值 其实可以制作出很AI的东西,但这里只讲下自己怎么控制极限值让程序不报错...)

                                 B: 还没优化完,暂时保密.A部分是以前写的,B部分是最近优化A部分的衍生物.

如果对此类思想感兴趣的话可以email我 互相讨论下

 

AS3地图加载---A1.地图的预加载

1.为什么要多预加载一圈?
见图...
蓝色的就是地图了,由一块一块的大小为100 x 100 px的切片组成
红色的框就代表 swf的显示框 大小为 300 x 300 px ,用户只能看到红框里面的内容
黑色的框 表示 必须加载的切片范围 4 x 4 枚 切片(少于这个数量 用户会在红框内看到空白背景)
绿色的框 表示 预加载多一圈的范围 6 x 6 (左右上下 各多加1个切片)
青色的是辅助线 请无视
 当移动地图后 swf 在如图所示的位置
 
因为地图往往会比swf的显示范围大的多,一次全部加载速度很慢
而且很占用资源,所以为了满足需求最少要在swf显示范围上预加载一圈
 
因为不知道用户向四周哪个方向移动地图
在移动地图时 会需要加载新的图片
预加载一圈的话,用户会先看到预加载的外围贴片,
如果不预加载,新的图片还在加载中没有显示
用户就会直接看到swf的空白背景,这样的使用体验不太友善
 
------------------------------------------------------------------------------
例图里都是纯色切片,实际地图肯定每个切片都不一样的
可以根据swf在地图上的相对坐标 加载6 x 6 张 对应地图切片
 
简单介绍下当时的需求
接下来就是重点了
→ A2.地图的移动
AS3地图加载---A2.地图的移动
因为拖动地图的频率是跟踪MouseMove事件,所以触发时间短,频率高.为了满足和提高用户体验度,在移动加载地图要保证动画的连贯性,同时保证加载多次的内存开销少.
我参考了谷歌地图的模式,制定了解决方案:
1.设定加载切片的loader的数量,因为太多loader一起load的时候很容易出现某一些loader 的load中止,并且不提示出错.
2.缓存一部分切片的图像数据BitmapData.使用队列的方式设置最大缓存数量.(删除最前面的,将最新的加到队列最后)
3.地图的拖动方式 在当时使用的是startDarg.(可以拖动的最大范围即swf的显示框的对角线长度)
 
上面只是解决方案,下面主要讲地图移动后的逻辑判断.
 
 
举例: 移动前 需要加载的切片位置 标记为 白色的A  设其范围为RectA
         移动后 需要加载的切片位置 标记为 黑色的B 设其范围为RectB
 
在移动地图后就需要加载只有B标记的切片地图,然后将只有A标记的切片从显示中删除
标记有AB切片的地图不需要做操作.
实现上述需求的老方法(几何方法)是
1.获取地图坐标
2.通过对比坐标来确定新切片满足 不在RectA中
3.而在RectB中 得到需要加载的切片对象
4和5.然后同理得到需要从先是列表中删除的切片对象.
(当然不一定是删除,根据项目不同的需求设置显示对象载体的变更方式,删除或者移动位置)
 
下面说说新方法(代数方法) 方法主要利用了集合和逻辑思想.
AS3中数组类型没那么多方便的集合操作方法,所以这里还要加上标记才能更简单的实现集合操作.
在地图加载的最开始设置一个Boolean型的标记flag,标记当前位置的切片是否显示.
即当前RectA中的切片的flag全部标记为true;
1.获取地图坐标
2.判断RectB中的flag , if(flag) 则flag = false , else flag = true; 并加载切片.(当然里面省略了很多缓存的判断操作,如果有缓存则直接拿缓存,没有则用loader加..老方法也会判断所以这里不做比较)
3. 判断RectA中的flag, if(flag) flag = false;并删除切片显示对象,else flag = true;

到这里去年8月新方法结束.

经过逻辑判断,不管用户怎么样拖动地图,最后也只有三种情况
RectA 和RectB  相同,相交,完全不相交
因为有预加载部分 所以第三种可能也比较少.
新方法也完全能用于这三种情况,而且不复杂可以方便的扩展新的功能.

写成数字描述会更简单

 
但是地图加载在性能上还是有别的地方可以进行优化
如 难道每次mouseMove都要进行新方法的判断吗?
是可以灵活的操作极限值来减少的.
简单的说明区别就是
过去mouseMove中进行新方法判断是以X = n轴 或 Y = n轴 即用一条线的比较来取舍是否来进行新方法.
灵活利用极限值的话可以将这一方法扩展为 用多条线组成的一个范围区域来取舍是否进行新方法.
使用线的话 在线的临界 来回拖动的话就会每次都进行新方法.
使用范围的话 在固定范围内不再会对新方法做2次执行,同样也能满足需求
详细请见
A3.极限值 //等待写好后在这里添加链接
AS3地图加载---A3.极限值
地图操作中会碰到很多临界情况
要设置很多极限值去防止溢出的操作.
多预加载一圈切片将带来了更多新的问题.
在上图的示例中,预加载的绿色方框包含了没有地图切片的地方.
为了不使程序报错,必须要设置一个极限值去限制加载切片的位置.
 
但这里主要要说的不是这个问题,而是要控制mouseMove事件中要发生的事情
想象一下绿色的预加载框开始向左移动100px,
假设它的注册点是左上角.
那么在移动前它的位置就是(100,0)  ,那么它的目标就是(0,0)
在mouseMove中,我们会去加载图片,如果用我上一篇日志中的标记的方法.
那么在移动过程中的多次mouseMove中只要判断新切片位置的标记 就可以达到目标切片只加载一次的目的了.
 
但是假如出现下图中的情况,程序仍可能会一直处于 "忙".

青色的辅助线就表示我们的临界值,

我们判断地图坐标时

会将地图坐标和临界值对比,然后决定是否加载新的切片.

但是绿色的预加载框在图中 白线 左右移动时,会不断的触发我们的加载方法.

特别是当绿色的预加载框在需求中要非常大的时候...程序可能会因为忙而未响应,甚至导致程序出错.

(图片停止加载,请注意这时原本的切片很可能已经在逻辑判断中删除了,

那么用户就会看到地图上的一块或几块"空地"".

如果没有删除,用户则会看到位置错误的切片.)

 

为了提高性能,我们需要在使用临界值判断之前增加一个范围判断.

增加一个鼠标相对位移是否在这个范围内的判断,

假如在这个的范围内,则不继续执行复杂的加载方法.反之,则执行.

请注意:这里的范围不能是一个固定值!

因为如果是固定值的话,每次鼠标相对位移都在范围内,程序将永远都不加载新的图片.

 

这个范围的大小将和地图坐标有密切的关系,而且最大不能超过一个切片大小.

这里的判断讲起来比较复杂,但实际上非常简单.所以只写下大概的思路.

鼠标的位移是根据地图的左右移动决定的,是有正负之分的.

正负情况要分开考虑,决定这个范围靠近切片的左边界还是右边界.

范围大小由地图坐标和临界值决定.

 

以上以左右移动地图为例讨论了极限值,但请不要忘记了实际操作地图还有上下移动.

但因为很相似所以就写到这里吧..

A部分结束.

 
-----------------------------------------------------
实际上极限值这里部分可以运用AS3的 startDrag API 代替
 
posted @ 2010-06-18 16:14  yinaak  阅读(936)  评论(0编辑  收藏  举报