Question

I have a method to swap two pieces in Bejeweled, but the animated swap doesn't appear to the user when they make a swap with no matches.

I.e. When the user tries to swap a jewel and no matches occur, the jewel stays stationary. What should happen is the jewel swaps positions, realises there isn't a match and swaps back.

I believe the issue is that the swaps are happening almost instantly if there isn't a match and there is no animation for the user.

How can I slow down the execution time of the second swap (i.e. the swap back) so the animation of the swap occurs?

// start animated swap of two pieces

public function makeSwap(piece1,piece2:Piece)
{
    swapPieces(piece1,piece2);

    //check to see if move works

    if (lookForMatches().length == 0)
    {
        swapPieces(piece1,piece2); //Swap the piece back
    } 
    else 
    {
        isSwapping = true;
    }
}

// swap two pieces

public function swapPieces(piece1,piece2:Piece) 
{
    // swap row and col values

    var tempCol:uint = piece1.col;
    var tempRow:uint = piece1.row;
    piece1.col = piece2.col;
    piece1.row = piece2.row;
    piece2.col = tempCol;
    piece2.row = tempRow;

    // swap grid positions

    grid[piece1.col][piece1.row] = piece1;
    grid[piece2.col][piece2.row] = piece2;

}
Was it helpful?

Solution

It's not too clear from your code how the animation itself is happening (clearly there are rendering functions elsewhere), but to add a delay to the execution of a function in AS3, you could use either the setTimeout function or the Timer class.

Here's setTimeout:

import flash.utils.setTimeout; //To be added with your other imports

// start animated swap of two pieces

public function makeSwap(piece1:Piece,piece2:Piece):void
{
    swapPieces(piece1,piece2);

    //check to see if move works

    if (lookForMatches().length == 0)
    {
        setTimeout(swapPieces, 500, piece1, piece2); //Swap the piece back, after delay of 500 milliseconds
    } 
    else 
    {
        isSwapping = true;
    }
}

// swap two pieces

public function swapPieces(piece1:Piece,piece2:Piece):void
{
    // swap row and col values

    var tempCol:uint = piece1.col;
    var tempRow:uint = piece1.row;
    piece1.col = piece2.col;
    piece1.row = piece2.row;
    piece2.col = tempCol;
    piece2.row = tempRow;

    // swap grid positions

    grid[piece1.col][piece1.row] = piece1;
    grid[piece2.col][piece2.row] = piece2;

}

And here's Timer:

import flash.utils.Timer; //To be added with your other imports
import flash.events.TimerEvent; //To be added with your other imports

private var _swapBackTimer:Timer = new Timer(500, 1); //Delay of 500 milliseconds, timer running 1 time
private var _delaySwapPiece1:Piece;
private var _delaySwapPiece2:Piece;

// start animated swap of two pieces

public function makeSwap(piece1:Piece,piece2:Piece):void
{
    swapPieces(piece1,piece2);

    //check to see if move works

    if (lookForMatches().length == 0)
    {
        _swapBackTimer.reset();
        _swapBackTimer.addEventListener(TimerEvent.TIMER, swapBackTimer_complete);
        _swapPiece1 = piece1;
        _swapPiece2 = piece2;
        _swapBackTimer.start();
    } 
    else 
    {
        isSwapping = true;
    }
}

private function swapBackTimer_complete(evt:TimerEvent):void
{
    _swapBackTimer.removeEventListener(TimerEvent.TIMER, swapBackTimer_complete);
    swapPieces(_delaySwapPiece1, _delaySwapPiece2);
}

// swap two pieces

public function swapPieces(piece1:Piece,piece2:Piece):void
{
    // swap row and col values

    var tempCol:uint = piece1.col;
    var tempRow:uint = piece1.row;
    piece1.col = piece2.col;
    piece1.row = piece2.row;
    piece2.col = tempCol;
    piece2.row = tempRow;

    // swap grid positions

    grid[piece1.col][piece1.row] = piece1;
    grid[piece2.col][piece2.row] = piece2;

}

One thing to keep in mind with this is the risk of the user changing the game state during the delay period, invalidating delayed actions and introducing bugs. You're maybe managing this already, but just in case, one approach would be to set a flag during any delayed actions, and then ignore any subsequent input during that time. Another method would be to cancel the delayed action, have it execute immediately, then process the new user action from that point.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top