zoukankan      html  css  js  c++  java
  • 像素精确碰撞算法优化

    1. package  
    2.   
    3. {  
    4.     //像素级精确碰撞算法优化  
    5.     //代码:Aone  
    6.     //2009-10-30  
    7.     import flash.display.BitmapData;  
    8.     import flash.display.BlendMode;  
    9.     import flash.display.DisplayObject;  
    10.     import flash.geom.ColorTransform;  
    11.     import flash.geom.Matrix;  
    12.     import flash.geom.Point;  
    13.     import flash.geom.Rectangle;  
    14.   
    15.   
    16.   
    17.     public class BitmapHitTestPlus  
    18.   
    19.     {  
    20.           
    21.         public static var tileSize:int=20     
    22.         public static function complexHitTestObject(target1:DisplayObject, target2:DisplayObject):Boolean  
    23.         {  
    24.             //横向缩小到tileSize尺寸需要的倍数,也就是期望检测的时候缩小到的尺寸。  
    25.             var scaleX:Number = (target1.width < target2.width ? target1.width : target2.width) / BitmapHitTestPlus.tileSize   
    26.             //纵向缩小到tileSize尺寸需要的倍  
    27.             var scaleY:Number = (target1.height < target2.height ? target1.height : target2.height) / BitmapHitTestPlus.tileSize   
    28.             //  
    29.             //如果倍数小于1则按原始倍率也就是原始尺寸  
    30.             scaleX = scaleX < 1 ? 1 : scaleX  
    31.             scaleY = scaleY < 1 ? 1 : scaleY  
    32.             //draw用point  
    33.             var pt:Point=new Point()  
    34.             //做2次draw时使用的颜色  
    35.             var ct:ColorTransform=new ColorTransform()            
    36.             ct.color=0xFF00000F   
    37.             //原始尺寸下的重叠矩形          
    38.             var oldHitRectangle:Rectangle=intersectionRectangle(target1, target2)  
    39.             //用于存放缩放的重叠矩形  
    40.             var hitRectangle:Rectangle= new Rectangle()  
    41.             return complexIntersectionRectangle(target1, target2 , scaleX , scaleY , pt , ct , oldHitRectangle,hitRectangle,BitmapHitTestPlus.tileSize,BitmapHitTestPlus.tileSize).width != 0;  
    42.   
    43.         }         
    44.   
    45.         public static function intersectionRectangle(target1:DisplayObject, target2:DisplayObject):Rectangle  
    46.   
    47.         {  
    48.   
    49.             // If either of the items don't have a reference to stage, then they are not in a display list  
    50.   
    51.             // or if a simple hitTestObject is false, they cannot be intersecting.  
    52.   
    53.             if (!target1.root || !target2.root || !target1.hitTestObject(target2))  
    54.                 return new Rectangle();  
    55.   
    56.   
    57.   
    58.             // Get the bounds of each DisplayObject.  
    59.   
    60.             var bounds1:Rectangle=target1.getBounds(target1.root);  
    61.   
    62.             var bounds2:Rectangle=target2.getBounds(target2.root);  
    63.   
    64.   
    65.   
    66.             // Determine test area boundaries.  
    67.   
    68.             var intersection:Rectangle=new Rectangle();  
    69.   
    70.             intersection.x=Math.max(bounds1.x, bounds2.x);  
    71.   
    72.             intersection.y=Math.max(bounds1.y, bounds2.y);  
    73.   
    74.             intersection.width=Math.min((bounds1.x + bounds1.width) - intersection.x, (bounds2.x + bounds2.width) - intersection.x);  
    75.   
    76.             intersection.height=Math.min((bounds1.y + bounds1.height) - intersection.y, (bounds2.y + bounds2.height) - intersection.y);  
    77.   
    78.   
    79.                   
    80.             return intersection;  
    81.   
    82.         }  
    83.   
    84.         public static function complexIntersectionRectangle(target1:DisplayObject, target2:DisplayObject, scaleX:Number , scaleY:Number , pt:Point , ct:ColorTransform ,oldhitRectangle:Rectangle,hitRectangle:Rectangle,nowW:int,nowH:int):Rectangle  
    85.   
    86.         {         
    87.             if (!target1.hitTestObject(target2))  
    88.                 return new Rectangle();  
    89.             //根据纵横的缩小倍数来计算缩小的重叠矩形尺寸  
    90.             hitRectangle.x = oldhitRectangle.x  
    91.             hitRectangle.y = oldhitRectangle.y  
    92.             hitRectangle.width = oldhitRectangle.width / scaleX  
    93.             hitRectangle.height = oldhitRectangle.height / scaleY  
    94.             //建立一个用来draw的临时BitmapData对象,尺寸为期望宽nowW,期望高nowH  
    95.             var bitmapData:BitmapData=new BitmapData(nowW,nowH, true0);             
    96.             //绘制对象1其缩放比例和位移量由getDrawMatrix()函数计算,并且把不透明处绘制为ct的颜色  
    97.             bitmapData.draw(target1, BitmapHitTestPlus.getDrawMatrix(target1, hitRectangle , scaleX , scaleY ),ct);  
    98.             //当纵横缩小比例不为1的时候把任何有色像素重新替换成ct的颜色0xFF00000F,原因为缩小的对象在进行纯色绘制的时候会有半透明像素产生,如果不加以重新替换会影响后面对象2的滤镜效果。  
    99.             if(scaleX!=1&&scaleY!=1){  
    100.                 bitmapData.threshold(bitmapData,bitmapData.rect,pt,">",0,0xFF00000F)  
    101.             }  
    102.             //绘制对象2其缩放比例和位移量由getDrawMatrix()函数计算,并且把不透明处绘制为ct的颜色,并且模式为叠加。如此一来两个对象重叠的部分颜色值必定大于0xFF00000F。  
    103.             bitmapData.draw(target2, BitmapHitTestPlus.getDrawMatrix(target2, hitRectangle , scaleX , scaleY ),ct, BlendMode.ADD);  
    104.             //把所有颜色值大于0xFF00000F的部分(也就是重叠部分)重新替换为不透明红色方便后面getColorBoundsRect()方法计算尺寸。这里替换的原因是getColorBoundsRect()不支持范围取色而只支持单色计算。  
    105.             //对象1缩放后可以重新替换掉透明色,但是对象2则无法使用同一方法,但是对象2由于也是经过缩放绘制也会有半透明像素,那么重叠部分虽然全部大于0xFF00000F,但未必是统一的。  
    106.             var hits:int=bitmapData.threshold(bitmapData,bitmapData.rect,pt,">",0xFF00000F,0xFFFF0000)  
    107.             //判断红色区域尺寸  
    108.             var intersection:Rectangle=bitmapData.getColorBoundsRect(0xFFFFFFFF0xFFFF0000);  
    109.             //        
    110.               
    111.             bitmapData = null  
    112.             //如果红色区域宽度不为0,即bitmapData中含有红色像素。此时说明对象1和对象2在此次判定中有重叠有碰撞  
    113.             if(intersection.width!=0){                
    114.                 //如果纵横缩放比例有任意一个不是原始尺寸  
    115.                 if(scaleX>1||scaleY>1){  
    116.                     //并且红色像素的数量比较少,对象1和对象2的碰撞面积比较小的话  
    117.                     if(hits<=(scaleX+scaleY)*1.5){  
    118.                         //由于bitmapData的宽高坐标都是以整数表示,那么经过缩放后取整的区域势必回又可能在取整的时候把真正可能产生碰撞的区域忽略。  
    119.                         //所以要进行下一次检测时候适当的把检测区域扩大xadd和yadd就是这个扩大的系数  
    120.                         var xadd:int=.5  
    121.                         var yadd:int=.5  
    122.                         //下次检测时候bitmapData的期望大小  
    123.                         var nextW:int=BitmapHitTestPlus.tileSize  
    124.                         var nextH:int=BitmapHitTestPlus.tileSize  
    125.                         //如果此次判定发现碰撞区域和bitmapData尺寸相同,那么在计算下次需要判断区域时候会和此次的区域相同,那么判断结果可能会和此次结果相同。这样则会引起堆栈上溢的情况,为了避免该情况发生,将缩小判断的尺寸扩大一倍进行再次检测。  
    126.                         if(intersection.width!=nowW){  
    127.                             nextW=BitmapHitTestPlus.tileSize                      
    128.                         }else{  
    129.                             nextW=nowW*2  
    130.                         }                 
    131.                         if(intersection.height!=nowH){  
    132.                             nextH=BitmapHitTestPlus.tileSize  
    133.                         }else{  
    134.                             nextH=nowH*2  
    135.                         }  
    136.                         //根据检测出来的缩的碰撞区域来计算未缩小的碰撞区域大小以方便下一次计算的时候缩小检测范围。  
    137.                         oldhitRectangle.x += (intersection.x - xadd) * scaleX  
    138.                         oldhitRectangle.y += (intersection.y - yadd) * scaleY  
    139.                         oldhitRectangle.width = (intersection.width + xadd*2) * scaleX  
    140.                         oldhitRectangle.height = (intersection.height + yadd*2)  * scaleY  
    141.                         //根据检测期望缩小到的尺寸重新计算缩小倍率  
    142.                         scaleX = (oldhitRectangle.width / nextW)   
    143.                         scaleY = (oldhitRectangle.height / nextH)  
    144.                         //如果倍率小于2则直接按原始尺寸   
    145.                         scaleX = scaleX < 2 ? 1 : scaleX  
    146.                         scaleY = scaleY < 2 ? 1 : scaleY  
    147.                         //进行下一次判定  
    148.                         intersection=complexIntersectionRectangle(target1,target2, scaleX , scaleY ,pt,ct,oldhitRectangle,hitRectangle,nextW,nextH)                           
    149.                     }  
    150.                 }  
    151.             }  
    152.                   
    153.               
    154.             return intersection;  
    155.   
    156.         }  
    157.   
    158.         protected static function getDrawMatrix(target:DisplayObject, hitRectangle:Rectangle , scaleX:Number , scaleY:Number ):Matrix  
    159.   
    160.         {  
    161.   
    162.             var localToGlobal:Point;  
    163.             var matrix:Matrix;  
    164.             var rootConcatenatedMatrix:Matrix=target.root.transform.concatenatedMatrix;  
    165.   
    166.   
    167.   
    168.             localToGlobal=target.localToGlobal(new Point());  
    169.   
    170.             matrix=target.transform.concatenatedMatrix;  
    171.   
    172.             matrix.tx=(localToGlobal.x - hitRectangle.x) / scaleX;  
    173.   
    174.             matrix.ty=(localToGlobal.y - hitRectangle.y) / scaleY;            
    175.               
    176.             matrix.a=matrix.a / rootConcatenatedMatrix.a / scaleX ;  
    177.             matrix.d=matrix.d / rootConcatenatedMatrix.d / scaleY;        
    178.   
    179.             return matrix;  
    180.   
    181.         }  
    182.   
    183.   
    184.     }  
    185.   
    186.   
    187.   
    188. }  
  • 相关阅读:
    CommonJS、AMD、CMD、NodeJs、RequireJS到底有什么联系?
    微信分享链接获取标题和小图片
    如何利用rem在移动端不同设备上让字体自适应大小
    基于VUE.JS的移动端框架Mint UI
    webpack超详细配置, 使用教程(图文)
    webpack一小时入门
    webpack入门教程
    前端构建工具gulpjs的使用介绍及技巧
    better-scroll在vue中的坑
    在vue 中使用Stylus
  • 原文地址:https://www.cnblogs.com/keng333/p/2439136.html
Copyright © 2011-2022 走看看