一种将展示与检测控制分离的方法

前段时间游戏中需要做一个人物选择,角色创建的界面。人物选择的界面是在一个背景图片上,有游戏中可供选择的人物角色形象,形象相互重叠。需要做到的是,当鼠标移动到某一个角色的形象上时,这个形象就需要高亮,以后可能还需要来一段动画效果。最开始的时候,美术那边提供的只是一张图片,以及各自的高亮图片。重点就是要做到对鼠标的检测,然后再更换上相对应的高亮图片。

其实最简单的方法是将每个角色的形象从背景图片中抠出来,做成按钮。当时由于时间和工作量的问题,美术那边説忙不过来,没有办法提供。于是就上网去寻找其他解决办法。幸运地找到了一种叫像素级精确选择对象法—蓝图法方法。这个方法的思路給我带来了一种新的视角,虽然最后由于scaleform未能提供对bitmapData类的支持,使得放弃这个方法,但是方法的思路还是很有益的,所以在此记录一下。

方法需要在检测之前根据展示图完成一张蓝图。那什么叫蓝图呢?怎么来做蓝图呢?蓝图其实是一个与展示图片同大小,专门用于存储鼠标检测区域的数据容器。不明白?一个最简单的例子就是,你获取到鼠标在展示图上的坐标位置为(x, y),然后到蓝图上去找到相对应的(x, y)坐标点,问一下,这个点是不是鼠标响应点,它所对应的对象是哪一个。OK?那怎样来做出一张蓝图呢?有几个关键的东西:BitmapData类,ColorTransform类。

1、初始化对象。
2、建立对象索引表或者把需要判断的对象addChild到相应容器中。
3、创建一个蓝图的bitmapData尺寸是场景大小。
4、遍历某一层级容器下的显示列表比如stage的,前提是这个容器必须是DisplayObjectContainer子类。同时利用ColorTransform类和DisplayObject对象的transform.colorTransform属性把对象设置成单色,颜色值等于层深值。由于深度值在这个层级下肯定是唯一的,那么每个对象就变成了有唯一颜色的单色对象(完全透明区域不会变色,仍然保持完全透明)。
5、把单色对象按深度从小到大的顺序向蓝图bitmapData里draw(),draw()完再次设置DisplayObject对象的transform.colorTransform属性为空把对象颜色恢复正常。最终循环完成的时一张蓝黑色的图片也就是蓝图就生成了。
6、生成的蓝图并不需要显示或者addChild到任何地方存在即可。
7、用enterFrame或者鼠标事件或者setInterval来作为触发来获得当前鼠标的X,Y坐标。
8、用bitmapData的getPixel(x,y)方法从蓝图中获取相应坐标的颜色值,也就是获得当前鼠标下那点的蓝图颜色。而这个颜色就是一个深度,那么直接stage.getChildAt()就可以方便的返回这个深度的对象了。

(注:上面的第4步可修改为:在向bitmapData里draw()时,将colorTransform作为参数一起传入,而不需要两次来改变colorTransform属性)

(注:以上方法转自http://bbs.9ria.com/forum.php?mod=viewthread&tid=16763&page=1

按照这个方法,可以很快地完成像素级的精确物体的定位了。正当我欢天喜地地运行实现出来的效果后,再用scaleform打开时,一个晴天霹雳,scaleform不支持bitmapData。上网苦苦搜寻,未果。也想过自己来实现一个bitmapData,可是对draw()方法无从下手,真是郁闷。

不过这个方法还是有些小缺点吧。首先占用的资源增加了,相同大小的bitmapData,其次,这只是对静态物体的检测,若对动态物体的检测,还需要不断地去重新计算bitmapData。

不过这些都只是表层的东西,对于这个方法,我觉得更重要的是其隐含的思想,一种将展示与检测分开,或者是説显示与数据分开的思想。以前所学的MVC模式等等,也有这样提到过,但是自己都没有完全领会到。而现在我才发现,原来如此小的地方其实都可以应用这样的思想,这让我觉得太美妙了,实在是妙不可言~~

posted @ 2012-10-22 13:23  骑着单车滑翔  阅读(192)  评论(0编辑  收藏  举报