CreateJS - animation being used is last one assigned

Tom Knowlton
Tom Knowlton used Ask the Experts™
on
If you look at my "generateGameBoard(  )" function, it should be assigning either one PNG or the other, depending on the modulus logic I've put in place.

What ends-up happening is the last image assigned becomes the one that ALL of the canvas elements are using.

I'm new to animation, CreatgeJS and also new to  JavaScript arrays and could use some help getting this fixed so it works as intended.  

Thank you!


JavaScript:
// for future use:  var initGamePieces = {};

// for future use:  initGamePieces["00"] = "powersourceRed.png";


$(document).ready(function() {

    function generateGameBoard() {
        var app = "";
        for (var y = 0; y < 10; y++) {
            for (var x = 0; x < 10; x++) {
                //app += "<canvas id='c' class='canvas' spritesrc='images/wall.png' height='64' width='64'></canvas>";

                //app += "<div id='" + x + y + "' class='gamepiece'><canvas id='canvas1' class='canvas' spritesrc='../images/destroyerRed.png' height='64' width='64'></canvas></div>";

                //app += "<canvas id='" + y + x + "' class='canvas' spriteSrc='images/destroyerRed.png' height='64' width='64'></canvas>";

                if (x % 2 === 0) {
                    app += "<canvas id='" + y + x + "' class='canvas' spriteSrc='images/destroyerRed.png' height='64' width='64'></canvas>";
                } else {
                    app += "<canvas id='" + y + x + "' class='canvas' spriteSrc='images/engineerBlue.png' height='64' width='64'></canvas>";
                }

                //app += "<div id='" + x + y + "' class='gamepiece'><canvas id='canvas' class='canvas' spritesrc='http://static.guineashots.com/tutorials/easeljs/assets/bubbles.png' height='64' width='64'></canvas></div>";
            }
        }
    

        $("#gameboard").empty();
        $("#gameboard").append(app);

        console.log("done generating empty game board");
        console.log(app);
    }

    generateGameBoard();

    function init(canvas) {
        var stage = new createjs.Stage(canvas);

        canvas.width = window.innerWidth;

        img = new Image();

        img.src = canvas.getAttributeNode("spriteSrc").value;

        console.log(img.src);

        img.onload = function (event) {

            var data = {
                framerate: 10,
                images: [img],
                frames: { width: 64, height: 64, regX: 32, regY: 32 },
                animations: {
                    'explode': [0, 10]
                }
            }

            var spritesheet = new createjs.SpriteSheet(data);
            var animation = new createjs.Sprite(spritesheet, "explode");
            animation.x = canvas.width / 2;
            animation.y = canvas.height / 2;

            stage.addChild(animation);
          //  var i = 0;

            createjs.Ticker.addEventListener("tick", update);
            function update(event) {

                animation.x = 50;
                animation.y = 40;
                stage.update();

                //i++;

                //if (i > 300) {
                //    i = 0;
                //}
            }
        }
    }


    canvasArr = document.getElementsByClassName("canvas");

    for (var a = 0; a < canvasArr.length; a++) {
        init(canvasArr[a]);
        console.log(canvasArr[a].id);
    }

});

Open in new window


HTML:
<!DOCTYPE html>
<meta charset="utf-8">

<html>
<head>
    <title></title>
    <link href="Styles/robotzcss.css" rel="stylesheet"/>
    <script src="Scripts/jquery-1.10.2.js"></script>
    <!--<script src="https://code.createjs.com/createjs-2015.11.26.min.js"></script>-->
    <script src="Scripts/robotz/robotzjs.js"></script>
</head>
<body>

    <script src="https://code.createjs.com/createjs-2015.11.26.min.js"></script>
    <div id="gameboard" style="position: relative; float: left; height: 680px; border: 1px solid red; width: 680px;"></div>

</body>
</html>

Open in new window


CSS:
body{
    margin: 0px;
    padding:0px;
}


.gamepiece {
    position:relative;
    float:left;
    width: 64px;
    height: 64px;
    border:1px solid transparent;
}

/* unvisited link */
.gamepiece:link {
    
}

/* visited link */
.gamepiece:visited {
    
}

/* mouse over link */
.gamepiece:hover {
    background-color: azure;
}

/* selected link */
.gamepiece:active {
    
}

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Software Engineer
Commented:
I can't fully test this (maybe some CSS is missing) but I think you see the same animation because you're using a global variable 'img' where it should be local to the 'init' function, simply change line 43 to:
var img = new Image();

Open in new window

Alternatively you could use [this] instead of [img] on line 53, so the global var isn't referenced anymore.
Tom KnowltonWeb developer

Author

Commented:
Robert:

That was exactly it!

So:

img = new Image( );  //global

var img = new Image( );  //local

Is that correct?

That seems so skwonky to me.  It's like you are declaring a global variable inside of a function which loses scope, so how is the img variable preserved when the function loses scope?

What is the difference between the img declared "globally" inside the function vs var img being declared at the top of the javascript?
Robert SchuttSoftware Engineer

Commented:
This works because you need a separate instance of 'img' (and 'stage' which already had the 'var') for each image.animation loop. In most other languages this would never work (like this). Have a close look at how the 'img,onload' and 'function update(event)' are being defined. It's kind of wonderful how functions within functions can use variables on any 'upper level' in javascript. It's called variable scoping and there's a lot more to it than you might suspect. If you want to read up on it research 'modular javascript' and closures, but get ready for a wild ride...

The main problem with a global variable in this situation is that any change to it affects all instances of functions accessing its value (through 'data').
Tom KnowltonWeb developer

Author

Commented:
Interesting...thanks!

Tom

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial