0
votes

I am currently working on a new Flash Game that is a sliding puzzle game. However, most of the pieces are not shaped like squares as in a standard sliding puzzle game, which makes the collision detection between the pieces much harder. I decided to try to program the collision detection between the Yellow L and the White L piece, each of which are a 100X100 squares with a 50X50 square cut off of the corner. Is there anyway to give them collision detection so that they cannot overlap each other?

var YellowLClicked: Boolean=false;

addEventListener(Event.ENTER_FRAME,onEnterFrameHandler);
YellowL.addEventListener(MouseEvent.MOUSE_DOWN, dragYellowL); 
YellowL.addEventListener(MouseEvent.MOUSE_UP, DoNotdragYellowL);
YellowL.addEventListener(MouseEvent.ROLL_OUT, DoNotdragYellowL);

function dragYellowL(e:MouseEvent): void{
    YellowLClicked=true;
}
function DoNotdragYellowL(e:MouseEvent): void{
    YellowLClicked=false;
}
function onEnterFrameHandler(e:Event): void{
    if(YellowLClicked){
           YellowL.startDrag();
    } else YellowL.stopDrag();

    //Can you help with this code here?
    if(YellowL.hitTestObject(WhiteL)) trace("true"); else trace(false);
}
1
Two options. You can either use some 2D physics framework which allows you to collide whatever shapes you want, or you can use something like Tetris 2D matrix where any shape occupies a list of cells determined by shape's position and rotation and if you want to move the shape you are to check the matrix if all the destination cells are free. - Organis
I just did this exact thing last week (built Tetris). It takes some work but I finally got a robust cell based set of classes working. I think that's the "better" option. Let me know if you want me to post a bit of that code for you. - Neal Davis
Posting the code will work for me. - Gary Lu KOTH
Sorry for the delay. I'll try to get to it tonight. - Neal Davis

1 Answers

0
votes

This is the collision check I use in my tetris-style game. It is in my Main.as file.

    private function checkCollision(f:GameField):Boolean{
        var p:Piece = f.activePiece;
        var a:Array = f.blockArray;
        for (var j:int = 0; j < p.numChildren; j++){
            var b:Block = p.getChildAt(j) as Block;
            // check walls, your will probably have four instead of 3
            if (b.hitTestObject(f.leftWall) || b.hitTestObject(f.rightWall) || b.row + b.rowLocal >= f._rows){
                return true;
            }
        }
        // check all the blocks in f.blockArray
        for (var i:int = 0; i < a.length; i++){
            // check the moving PIECE against all other BLOCKS
            if (p.hitTestObject(a[i])){
                // check every child of the PIECE (these will be the blocks) 
                for (var j:int = 0; j < p.numChildren; j++){
                    // excluding the BLOCKS in the moving PIECE
                    if (p.getChildAt(j).parent != a[i].parent){
                        var b:Block = p.getChildAt(j) as Block;
                        // finally, BLOCK vs BLOCK collision check
                        if (b.hitTestObject(a[i])){
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

This is the constructor for my Piece class:

    public function Piece(f:GameField,shape:Array,color:uint) 
    {
        makeGrid();
        f.addChild(this);
        // the shape array passed to this constructor is shown at the end of my post
        _shape = shape;
        addBlocks(f,shape,color);
    }

    private function addBlocks(f:GameField, shape:Array, color:uint):void{
        _shape = shape;
        for (var i:int = 0; i < shape.length; i++){
            var b:Block = new Block(color);

            // this uses the Array passed as var "shape" to tell where the block will be in relation to the center of rotation of the Piece instance
            b.rowLocal = shape[i].y+2;
            b.columnLocal = shape[i].x+2;

            // this tells the brick its starting column and row are 
            b.row = -2;
            b.column = 3;

            // this is the sum of the local and global coordinates
            b.y = (b.rowLocal + b.row) * Main.UNIT_SIZE;
            b.x = (b.columnLocal + b.column) * Main.UNIT_SIZE;

            // put the block on the display list
            addChild(b);

            // add the block to the array to use for collision checks in the Main doc
            f.blockArray.push(b);
        }
    }

And the Block class just extends sprite and draws a square (mine has some goodies that don't need to be applied here, so I won't post it).

And finally the calling of the Piece constructor and an example of the shape array that gets passed to it.

        var newP:Piece = new Piece(f, arr, color);

and the shape Array:

        _shapeArray = [
        {shape:new Array(new Point (-2, 0), new Point (-1, 0), new Point (0, 0), new Point (1, 0)),color:_colorArray[0]}, // I
        {shape:new Array(new Point (-1, -1), new Point (-1, 0), new Point (0, 0), new Point (0, -1)),color:_colorArray[1]}, // O
        {shape:new Array(new Point (-2, -1), new Point (-1, -1), new Point (-1, 0), new Point (0, 0)),color:_colorArray[2]}, // Z
        {shape:new Array(new Point (-2, 0), new Point (-1, 0), new Point (-1, -1), new Point (0, -1)),color:_colorArray[3]}, // S
        {shape:new Array(new Point (-2, 0), new Point (-1, 0), new Point (0, 0), new Point (-2, -1)),color:_colorArray[4]}, // J
        {shape:new Array(new Point (-2, 0), new Point (-1, 0), new Point (0, 0), new Point (0, -1)),color:_colorArray[5]}, // L
        {shape:new Array(new Point (-2, 0), new Point (-1, 0), new Point (0, 0), new Point (-1, -1)),color:_colorArray[6]}  // T
        ];

To summarize:

  1. Make a Block class that extends Sprite
  2. Make a Piece class that contains Block instances arranged in a shape that you choose.
  3. Run a collision check between pertinent Block pieces.

edit

This looks like it could work. However, I have one more question: checkCollision() returns a boolean but what I do with that boolean? If the boolean is true, how do I make the objects unable to cross?

This is how I implemented that. Allow the objects to cross each other and then call

if (checkCollision(f)) {
    // check collision returned true
    // so reverse the last move 
    // before finishing this game loop
}