Search code examples
javascriptmeteorintervals2d-games

js interval inside interval not working


i am trying to build a game - the goal is to collect only the right objects that fall from the top of the browser.

i've created an interval that calls a function that creates new elements every 5 seconds, and inside of that function i created another interval that check does the element reaches to the bottom.

problem is - when other element is created (after 5 seconds) the checker interval stop checking the current element and start checking the new one - so its never reaching the bottom.

here is the code:

    var newDrop =function(){
    random = Math.random();
    randNum = Math.floor(foodsImages.length * Math.random());
    drop = $('<img class="drop" src="'+ foodsImages[randNum].img +'">').appendTo('.board');
    drop.css({ top:0 - drop.height(), left: random * ($(window).width() - drop.width())});
    drop.animate({
        top: $('.board').height()
    }, 15000, function(){
        $(this).remove()
    });
    checkStop = setInterval(function(){new basket(drop, foodsImages[randNum])} , 30);
    drop.attr('interval', checkStop);
};

var basket = function(elm,obj){
    console.log(elm.offset().top + elm.height() > $('.basket').offset().top);
    if (elm.offset().top + elm.height() > $('.basket').offset().top){ //reached to the end
        leftLarger = elm.offset().left <= $('.basket').offset().left; 
        rightSmaller = elm.offset().left + elm.width() >= $('.basket').offset().left + $('.basket').width();

        if ( leftLarger && rightSmaller) { //if its been catched

            if (obj.value == true) { //and its a good thing
                console.log("yyah");
            }else{ // if its a bad thing
                console.log("bozzz");
            };

        }else{ //wasnt cathced

            if (obj.value == true) { //and suposed to cach
                console.log("bozzz");
            }else{
                console.log("msg");             
            };
        };

        elm.remove();
        return clearInterval( elm.checkStop ); //stop tracking
    };
}

$(function(){
    //handle drag movment
    $('.board').height( $(window).height() - $('header').height() );
    $('.basket').draggable({ 
        axis: "x",
        containment: "parent",
        scroll: false
    });

    //handle keypress on computers
    $(document).on("keydown", function (e) {
        var currentpost = $('.basket').offset().left;
        switch(e.which) {
            case 39:
                if ( (currentpost + $('.basket').width() ) < $(window).width()){
                    $('.basket').css('left', currentpost + 10);
                }
                break;
            case 37:
                if (currentpost - 10 > 0 ){
                    $('.basket').css('left', currentpost - 10);
                }
                break;
            default:
                return false;
        }
    });

    //objects
    foodsImages = [
        {
            "name": "adashim",
            "img" : "http://www.bulbsort.com/puzzlingapples/img/icon256x256.png",
            "value": true
        },
        {
            "name": "adom",
            "img" : "http://vignette1.wikia.nocookie.net/clubpenguin/images/8/86/Tacos_Puffle_Food.png/revision/latest?cb=20130820230847",
            "value": false
        },
        {
            "name": "tavshil",
            "img" : "https://tonytimecp.files.wordpress.com/2011/12/coin.png",
            "value": true
        },
        {
            "name": "pasta",
            "img" : "http://upload.wikimedia.org/wikipedia/commons/1/19/Food_Barnstar_Hires.png",
            "value": false
        }
    ];

    newDrop();
    addDrop = setInterval( function(){ newDrop() } , 5000);
});

here is the demo : https://jsfiddle.net/12345/4rgxqdLp/2/


Solution

  • I have created a new fiddle https://jsfiddle.net/qkjounLb/

    You need to understand how to properly use the keyword new and this. With that understanding OO and, scope and closures is helpful. Although not required, understanding scope and how to manipulate scope, in this case, can quickly solve the issue. I do not know the scope of the rest of your game program and so may have gone overboard with this keyword, but illustrates the point none the less.

    You can start here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures but there are many articles available to understand scope in JavaScript via a search.

    var betterDrop = function(foodsImages){
        this.random = Math.random();
        this.randNum = Math.floor(foodsImages.length * Math.random());
    
        this.drop = $('<img class="drop" src="'+ foodsImages[this.randNum].img +'">').appendTo('.board');
        this.drop.css({ top:0 - this.drop.height(), left: this.random * ($(window).width() - this.drop.width())});
        this.drop.animate({
            top: $('.board').height()
        }, 15000, function(){
            $(this).remove()
        });
    
        var scope = this;
    
        this.checkStop = setInterval(function(){new basket(scope.drop, foodsImages[scope.randNum])} , 30);
        this.drop.attr('interval', scope.checkStop);
    }
    
    var basket = function(elm,obj){
        console.log(elm.offset().top + elm.height() > $('.basket').offset().top);
        if (elm.offset().top + elm.height() > $('.basket').offset().top){ //reached to the end
            leftLarger = elm.offset().left <= $('.basket').offset().left; 
            rightSmaller = elm.offset().left + elm.width() >= $('.basket').offset().left + $('.basket').width();
    
            if ( leftLarger && rightSmaller) { //if its been catched
    
                if (obj.value == true) { //and its a good thing
                    console.log("yyah");
                }else{ // if its a bad thing
                    console.log("bozzz");
                };
    
            }else{ //wasnt cathced
    
                if (obj.value == true) { //and suposed to cach
                    console.log("bozzz");
                }else{
                    console.log("msg");             
                };
            };
    
            elm.remove();
            return clearInterval( elm.checkStop ); //stop tracking
        };
    }
    
    $(function(){
        //handle drag movment
        $('.board').height( $(window).height() - $('header').height() );
        $('.basket').draggable({ 
            axis: "x",
            containment: "parent",
            scroll: false
        });
    
        //handle keypress on computers
        $(document).on("keydown", function (e) {
            var currentpost = $('.basket').offset().left;
            switch(e.which) {
                case 39:
                    if ( (currentpost + $('.basket').width() ) < $(window).width()){
                        $('.basket').css('left', currentpost + 10);
                    }
                    break;
                case 37:
                    if (currentpost - 10 > 0 ){
                        $('.basket').css('left', currentpost - 10);
                    }
                    break;
                default:
                    return false;
            }
        });
    
        //objects
        foodsImages = [
            {
                "name": "adashim",
                "img" : "http://www.bulbsort.com/puzzlingapples/img/icon256x256.png",
                "value": true
            },
            {
                "name": "adom",
                "img" : "http://vignette1.wikia.nocookie.net/clubpenguin/images/8/86/Tacos_Puffle_Food.png/revision/latest?cb=20130820230847",
                "value": false
            },
            {
                "name": "tavshil",
                "img" : "https://tonytimecp.files.wordpress.com/2011/12/coin.png",
                "value": true
            },
            {
                "name": "pasta",
                "img" : "http://upload.wikimedia.org/wikipedia/commons/1/19/Food_Barnstar_Hires.png",
                "value": false
            }
        ];
    
        new betterDrop(foodsImages);
    
    
    addDrop = setInterval( function(){ new betterDrop(foodsImages) } , 5000);
    });