2
votes

I'm using a tutorial I found on Google - which works well. However, I have a few issues to make it work how I would like.

I tried to get the second card to hang on for a short time, so the kid (player) can see the match when there is a match.

Unfortunately, my code gave me a TypeError: Error #2007: Parameter child must be non-null runtime error in my matching game, and when I click on a new card before the set is removed the matching couple is turned back and the new clicked card is removed (on its own). I would appreciate any help.

This is the error and after that my code:

  TypeError: Error : Parameter child must be non-null.
        at flash.display::DisplayObjectContainer/removeChild()
        at MatchingGameObject9/remove_tiles()
        at flash.events::EventDispatcher/dispatchEventFunction()
        at flash.events::EventDispatcher/dispatchEvent()
        at flash.utils::Timer/tick()
package {
  import flash.display.*;
  import flash.events.*;
  import flash.text.*;
  import flash.utils.getTimer;
  import flash.utils.Timer;


  public class MatchingGameObject9 extends MovieClip {
      // game constants
        private static const boardWidth:uint = 6;
      private static const boardHeight:uint = 5;
      private static const cardHorizontalSpacing:Number = 87;
      private static const cardVerticalSpacing:Number = 87;
      private static const boardOffsetX:Number = 20;
      private static const boardOffsetY:Number = 45;
      private static const pointsForMatch:int = 100;
      private static const pointsForMiss:int = -5;

      private var firstCard:Card;
      private var secondCard:Card;
      private var cardsLeft:uint;
      private var gameScore:int;
      private var gameStartTime:uint;
      private var gameTime:uint;
      private var pause_timer:Timer;
      private var gameScoreField:TextField;
      private var gameTimeField:TextField;

      public function MatchingGameObject9():void {
        // make a list of card numbers
        var cardlist:Array = new Array();
        for(var i:uint=0;i<boardWidth*boardHeight;i++) {
            cardlist.push(i);

        }

        // create all the cards, position them, and assign a randomcard face to each
        cardsLeft = 0;
        for(var x:uint=0;x<boardWidth;x++) { // horizontal
            for(var y:uint=0;y<boardHeight;y++) { // vertical
                var c:Card = new Card(); // copy the movie clip
                c.stop(); // stop on first frame
                c.x = x*cardHorizontalSpacing+boardOffsetX; // set position
                c.y = y*cardVerticalSpacing+boardOffsetY;
                var r:uint = Math.floor(Math.random()*cardlist.length); // get a random face
                c.cardface = cardlist[r]; // assign face to card
                cardlist.splice(r,1); // remove face from list
                c.addEventListener(MouseEvent.CLICK,clickCard); // have it listen for clicks
                c.buttonMode = true;
                addChild(c); // show the card
                cardsLeft++;
            }
        }

        gameScoreField = new TextField();
        addChild(gameScoreField);
        gameScore = 0;
        showGameScore();

        gameTimeField = new TextField();
        gameTimeField.x = 450;
        addChild(gameTimeField);
        gameStartTime = getTimer();
        gameTime = 0;
        addEventListener(Event.ENTER_FRAME,showTime);
      }

      // player clicked on a card
      public function clickCard(event:MouseEvent) {
        var thisCard:Card = (event.target as Card); // what card?

        if (firstCard == null) { // first card in a pair
            firstCard = thisCard; // note it
            firstCard.gotoAndStop(thisCard.cardface+2); // turn it over

        } else if (firstCard == thisCard) { // clicked first card again
            firstCard.gotoAndStop(1); // turn back over
            firstCard = null;

        } else if (secondCard == null) { // second card in a pair
            secondCard = thisCard; // note it
            secondCard.gotoAndStop(thisCard.cardface+2); // turn it over

            // compare two cards
            if (Math.floor(firstCard.cardface/2) ==   Math.floor(secondCard.cardface/2)) {
                **pause_timer = new Timer(2000,1);
                 pause_timer.addEventListener(TimerEvent.TIMER_COMPLETE,remove_tiles);
                pause_timer.start();**
            }

        } else { // starting to pick another pair
            // reset previous pair
            firstCard.gotoAndStop(1);
            secondCard.gotoAndStop(1);
            secondCard = null;
            // select first card in next pair
            firstCard = thisCard;
            firstCard.gotoAndStop(thisCard.cardface+2);
        }
      }

      public function showGameScore() {
        gameScoreField.text = "ΣΚΟΡ: "+String(gameScore);
      }

      public function showTime(event:Event) {
        gameTime = getTimer()-gameStartTime;
        gameTimeField.text = "ΧΡΟΝΟΣ: "+clockTime(gameTime);
      }

      public function clockTime(ms:int) {
        var seconds:int = Math.floor(ms/1000);
        var minutes:int = Math.floor(seconds/60);
        seconds -= minutes*60;
        var timeString:String = minutes+":"+String(seconds+100).substr(1,2);
        return timeString;
      }
      **public function remove_tiles(event:TimerEvent) {
        removeChild(firstCard);
                removeChild(secondCard);
                // reset selection
                firstCard = null;
                secondCard = null;
                // add points
                gameScore += pointsForMatch;
                showGameScore();
                // check for game over
                cardsLeft -= 2; // 2 less cards
                if (cardsLeft == 0) {
                    MovieClip(root).gameScore = gameScore;
                    MovieClip(root).gameTime = clockTime(gameTime);
                    MovieClip(root).gotoAndStop("gameover");
                   pause_timer.removeEventListener(TimerEvent.TIMER_COMPLETE,remove_tiles);
                    } else {
                    gameScore += pointsForMiss;
                    showGameScore();
            }**
  }
}
1
Once you start pause_timer it does not stop (because cardsLeft > 0) and goes on calling remove_tiles(...) again and again, and on the second call firstCard and seconsCard are both null. - Organis
The error comes up when the player continue to pick tiles when the script is waiting to let him see the second tile he picked before both are removed. Instead of them the third tile is removed and that error comes up. I try my best but i can't find a solution. - Marianna

1 Answers

2
votes

I think you need to organize removing differently. Something like:

var removalQueue:Array = new Array;

addEventListener(Event.ENTER_FRAME, onRemove);

function onRemove(e:Event):void
{
    if (!removalQueue.length) return;

    var anEntry:Object = removalQueue[0];

    if (getTimer() < anEntry['time']) return;

    // Delete entry from queue.
    removalQueue.shift();

    removeChild(anEntry['first']);
    removeChild(anEntry['second']);

    gameScore += anEntry['score'];
    cardsLeft -= 2;

    // The rest of your code...
}

So when you have two matching cards you just need to push an appropriate entry to the queue:

var anEntry:Object =
{
    "time": getTimer() + 2000,
    "first": firstCard,
    "second": secondCard,
    "score": pointsForMatch
}

removalQueue.push(anEntry);