views:

480

answers:

2

Hey everyone,

I'm making small interactive games in flash to learn AS3, now I ran into a problem that I need some help with.

I need to check the collision between the player and the wall which is normally simple using the hitTestObject function.

But now I made a wall object totally surrounding the player with corridors and turn, a collision playground so to speak.

Now when I use the hitTestObject function to check whether the player is in collision with the wall it tells me it always collides supposedly because the player object is within the bounds of the wall object.

So assuming that I'm correct about the error: How can I prevent getting a collision when I'm inside the bounds of the wall object but not touching the actual walls in that object?

+1  A: 

You'll need to use a library for that, I use this class:

package 
{
    import flash.display.BitmapData;
    import flash.display.BitmapDataChannel;
    import flash.display.BlendMode;
    import flash.display.DisplayObject;
    import flash.display.DisplayObjectContainer;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.geom.Rectangle;

    /**
     * Use isColliding to test for a collision between two sprites.
     *
     * @author Troy Gilbert
     * @author Alexander Schearer <[email protected]>
     */
    public class CollisionDetection
    {
        /** Get the collision rectangle between two display objects. **/
        public static function getCollisionRect(target1:DisplayObject, target2:DisplayObject, commonParent:DisplayObjectContainer, pixelPrecise:Boolean = true, tolerance:Number = 0):Rectangle
        {
            // get bounding boxes in common parent's coordinate space
            var rect1:Rectangle = target1.getBounds(commonParent);
            var rect2:Rectangle = target2.getBounds(commonParent);
            // find the intersection of the two bounding boxes
            var intersectionRect:Rectangle = rect1.intersection(rect2);
            if (intersectionRect.size.length> 0)
            {
                if (pixelPrecise)
                {
                    // size of rect needs to integer size for bitmap data
                    intersectionRect.width = Math.ceil(intersectionRect.width);
                    intersectionRect.height = Math.ceil(intersectionRect.height);
                    // get the alpha maps for the display objects
                    var alpha1:BitmapData = getAlphaMap(target1, intersectionRect, BitmapDataChannel.RED, commonParent);
                    var alpha2:BitmapData = getAlphaMap(target2, intersectionRect, BitmapDataChannel.GREEN, commonParent);
                    // combine the alpha maps
                    alpha1.draw(alpha2, null, null, BlendMode.LIGHTEN);
                    // calculate the search color
                    var searchColor:uint;
                    if (tolerance <= 0)
                    {
                        searchColor = 0x010100;
                    }
                    else
                    {
                        if (tolerance> 1) tolerance = 1;
                        var byte:int = Math.round(tolerance * 255);
                        searchColor = (byte <<16) | (byte <<8) | 0;
                    }
                    // find color
                    var collisionRect:Rectangle = alpha1.getColorBoundsRect(searchColor, searchColor);
                    collisionRect.x += intersectionRect.x;
                    collisionRect.y += intersectionRect.y;
                    return collisionRect;
                }
                else
                {
                    return intersectionRect;
                }
            }
            else
            {
                // no intersection
                return null;
            }
        }

        /** Gets the alpha map of the display object and places it in the specified channel. **/
        private static function getAlphaMap(target:DisplayObject, rect:Rectangle, channel:uint, commonParent:DisplayObjectContainer):BitmapData
        {
            // calculate the transform for the display object relative to the common parent
            var parentXformInvert:Matrix = commonParent.transform.concatenatedMatrix.clone();
            parentXformInvert.invert();
            var targetXform:Matrix = target.transform.concatenatedMatrix.clone();
            targetXform.concat(parentXformInvert);
            // translate the target into the rect's space
            targetXform.translate(-rect.x, -rect.y);
            // draw the target and extract its alpha channel into a color channel
            var bitmapData:BitmapData = new BitmapData(rect.width, rect.height, true, 0);
            bitmapData.draw(target, targetXform);
            var alphaChannel:BitmapData = new BitmapData(rect.width, rect.height, false, 0);
            alphaChannel.copyChannel(bitmapData, bitmapData.rect, new Point(0, 0), BitmapDataChannel.ALPHA, channel);
            return alphaChannel;
        }

        /** Get the center of the collision's bounding box. **/
        public static function getCollisionPoint(target1:DisplayObject, target2:DisplayObject, commonParent:DisplayObjectContainer, pixelPrecise:Boolean = false, tolerance:Number = 0):Point
        {
            var collisionRect:Rectangle = getCollisionRect(target1, target2, commonParent, pixelPrecise, tolerance);
            if (collisionRect != null && collisionRect.size.length> 0)
            {
                var x:Number = (collisionRect.left + collisionRect.right) / 2;
                var y:Number = (collisionRect.top + collisionRect.bottom) / 2;
                return new Point(x, y);
            }
            return null;
        }

        /** Are the two display objects colliding (overlapping)? **/
        public static function isColliding(target1:DisplayObject,
                target2:DisplayObject,
                commonParent:DisplayObjectContainer,
                pixelPrecise:Boolean = false,
                tolerance:Number = 0):Boolean
        {
            var collisionRect:Rectangle = getCollisionRect(target1, target2, commonParent, pixelPrecise, tolerance);
            if (collisionRect != null && collisionRect.size.length> 0) return true;
            else return false;
        }
    }
}
M28
I'm not really familiar with the package and classes system of AS3.Would you mind explaining me how to implement that library in my project?
Pieter888
CollisionDetection.isColliding(target1,target2,commomParent,pixelPrecise, alphaTolerance);
M28
+1  A: 

The class provided by M28 is actually an Intersection and not a collision class ( Grant Skinner was the first that provided one back in AS 2.0 )

You can go with that for a small project but remember that it doesn't do CCD ( Continuous Collision Detecting )

That being said, if your player's speed is greater than the wall width you can see him magically pass trough the wall.

If you consider that your project is more complex I believe you could use a 2d physics engine that has CCD like Box2DFlash

http://box2dflash.boristhebrave.com/

Oliver