~extremepopcorn/dhlib/dhlib_ep

« back to all changes in this revision

Viewing changes to lib/flashx/ObjectCollider.hx

  • Committer: edA-qa mort-ora-y
  • Date: 2010-02-16 05:36:32 UTC
  • Revision ID: eda-qa@disemia.com-20100216053632-60lt7fndfi3fgblw
first

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* <license>
 
2
 * This file is part of the dis-Emi-A HaXe Library. Copyright (c) edA-qa mort-ora-y
 
3
 * For full copyright and license information please refer to doc/license.txt.
 
4
 * </license> 
 
5
 */
 
6
package flashx;
 
7
 
 
8
import flash.display.DisplayObject;
 
9
import flash.display.Stage;
 
10
import flash.display.BitmapData;
 
11
import flash.display.BitmapDataChannel;
 
12
import flash.geom.Point;
 
13
import flash.geom.Rectangle;
 
14
 
 
15
/**
 
16
 * Performs collisions on specific MovieClips and sprites.  This needs to be
 
17
 * attached to a particular stage in order to work with sprites on that stage.
 
18
 *
 
19
 * This only supports a Bool hit condition, if a version is needed to judge
 
20
 * the degree of overlap then a color transform / blend mode version could
 
21
 * be done and use getColorBoundsRect to determine the size of the 
 
22
 * overlapping area.
 
23
 */
 
24
class ObjectCollider
 
25
{
 
26
        var stage : Stage;
 
27
        var alpha : Float;
 
28
        var filters : Bool;
 
29
        
 
30
        var objx1 : RenderCache;
 
31
        var objx2 : RenderCache;
 
32
        
 
33
        /**
 
34
         * Creates a new collider for the given stage
 
35
         *
 
36
         * @param       astage  [in,keep] in whcih stage the comparisions are done
 
37
         * @param       aalpha  [in] what alpha level match is considered a collision
 
38
         * @param       afilters        [in] use filters in comparision (otherwise they are stripped for comparison)
 
39
         */
 
40
        public function new( astage : Stage, ?aalpha : Null<Float>, ?afilters : Null<Bool> )
 
41
        {
 
42
                alpha = if( aalpha == null ) 0.5 else aalpha;
 
43
                filters = if( afilters == null ) true else afilters;
 
44
                stage = astage;
 
45
                
 
46
                objx1 = new RenderCache( );
 
47
                objx2 = new RenderCache( );
 
48
        }
 
49
        
 
50
        public function createCollisionBitmaps( s1 : DisplayObject, s2 : DisplayObject, forContain : Bool ) : { a : BitmapData, b : BitmapData }
 
51
        {
 
52
                //get the real bounds of each item
 
53
                var r1 = s1.getBounds( stage );
 
54
                var r2 = s2.getBounds( stage );
 
55
                var intr = r1.intersection( r2 );
 
56
                
 
57
                objx1.useFilters = filters;
 
58
                var bd1 = objx1.renderBitmap( s1, intr, forContain, false );
 
59
                objx2.useFilters = filters;
 
60
                var bd2 = objx2.renderBitmap( s2, intr, false, false );
 
61
                
 
62
                return { a : bd1, b: bd2 };
 
63
        }
 
64
        
 
65
        static var originPoint = new Point();
 
66
        public function checkCollision( bd1 : BitmapData, bd2 : BitmapData, alpha : Float ) : Bool
 
67
        {
 
68
                //accounts for about 15% of time in comparison, smaller cached sizes would likely help
 
69
                var a = Math.round( alpha * 0xff );
 
70
                return bd1.hitTest( originPoint, a, bd2, originPoint, a );
 
71
        }
 
72
        
 
73
        /**
 
74
         * Do the two display objects overlap (using pixel tests per-pixel
 
75
         */
 
76
        public function doCollide( s1 : DisplayObject, s2 : DisplayObject ) : Bool
 
77
        {
 
78
                //short-track checking if bounding boxes don't collide
 
79
                if( !s1.hitTestObject( s2 ) )
 
80
                        return false;
 
81
                        
 
82
                var bits = createCollisionBitmaps( s1, s2, false );
 
83
                var ret = checkCollision( bits.a, bits.b, alpha );
 
84
                //might as well use this function... (don't, since we cache them now)
 
85
                //bits.a.dispose();
 
86
                //bits.b.dispose();
 
87
                return ret;
 
88
        }
 
89
        
 
90
        /**
 
91
         * @param       bd1     [in] a bitmap prepared for contains checking as with "forContain" in createCollisionBitmaps
 
92
         * @param       bd2     [in] the bitmap to check if in first bitmap
 
93
         */
 
94
        public function checkContain( bd1 : BitmapData, bd2 : BitmapData, alpha : Float ) :  Bool
 
95
        {
 
96
                //The Flash Documentation/fucntions are just plain wrong.  Almost all of the BitmapData
 
97
                //functions only apply to those pixels which are not transparent.  The other pixels are completely
 
98
                //ignored, even if you actually want to work with them -- this makes working with the alpha
 
99
                //channel very very difficult and confusing...
 
100
                
 
101
                //we copy an arbitrary channel to the ALPHA channel (since the source should be grayscale)
 
102
                //this means the transparency of this image is now the inverse of the original image
 
103
                bd1.copyChannel( bd1, bd1.rect, new Point(0,0), BitmapDataChannel.BLUE, BitmapDataChannel.ALPHA );
 
104
                var a = Math.round( alpha * 0xff );
 
105
                var hit = !bd1.hitTest( originPoint, a, bd2, originPoint, a );
 
106
 
 
107
                return  hit;
 
108
        }
 
109
        
 
110
        /**
 
111
         * Does the entire bounds of s2 reside with s1?
 
112
         */
 
113
        public function aBoxContainsB( s1 : DisplayObject, s2 : DisplayObject ) : Bool
 
114
        {
 
115
                var r1 = s1.getBounds( stage );
 
116
                var r2 = s2.getBounds( stage );
 
117
                return r1.containsRect( r2 );
 
118
        }
 
119
        
 
120
        /**
 
121
         * Does the first object completely contain the second object
 
122
         */
 
123
        public function aContainsB( s1 : DisplayObject, s2 : DisplayObject ) : Bool
 
124
        {
 
125
                if( !aBoxContainsB( s1, s2 ) )
 
126
                        return false;
 
127
                        
 
128
                var bits = createCollisionBitmaps( s1, s2, true );
 
129
                return checkContain( bits.a, bits.b, alpha );
 
130
        }
 
131
}