Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I'm learning JavaScript and came up with this basic game code structure (using the CreateJS framework):

var stage;
var totalLoaded = 0;
var manifest;


var game = game || {};
game.init = {

    load: function () {
        var canvas = document.getElementById('gameCanvas');
        images = createjs.images || {};
        stage = new createjs.Stage(canvas);

        manifest = [{
            src: "http://i47.tinypic.com/swtj03.png",
            id: "circleImg"
        }, ]

        loader = new createjs.PreloadJS(false);
        loader.onFileLoad = game.init.handleFileLoad;
        loader.loadManifest(manifest);

        game.init.ticker();
        game.init.processText();
        game.init.interaction();
    },

    handleFileLoad: function (o) {
        if (o.type == "image") {
            images[o.id] = o.result = new createjs.Bitmap(o.result);
            switch (o.id) {
                case "circleImg":
                    images[o.id].y = 302;
                    break;
            }
            game.init.handleLoadComplete();
        }
    },

    handleLoadComplete: function (e) {
        totalLoaded++;
        if (manifest.length == totalLoaded) {
            game.init.handleComplete();
        }
    },

    handleComplete: function () {
        game.menu();
    },

    ticker: function () {
        createjs.Ticker.addListener(window);
        createjs.Ticker.useRAF = true;
        createjs.Ticker.setFPS(60);
    },

    text: [{
        "name": "startText",
            "content": "START",
            "style": "bold 50px Arial",
            "color": "red",
            "x": "325",
            "y": "140",
            "scaleX":"1",
            "scaleY":"1"
    },

    {
        "name": "animationComplete",
            "content": "ANIMATION COMPLETE",
            "style": "bold 50px Arial",
            "color": "red",
            "x": "125",
            "y": "140",
            "scaleX":"1",
            "scaleY":"1"
    },

    {
        "name": "animationRestart",
            "content": "RESTART TO MENU?",
            "style": "bold 20px Arial",
            "color": "gray",
            "x": "125",
            "y": "340",
            "scaleX":"1",
            "scaleY":"1"
    }

    ],


    textId: [],

    processText: function () {
        for (i = 0; i < this.text.length; i++) {
            this.textId[i] = new createjs.Text(this.text[i].content, this.text[i].style, this.text[i].color);
            this.textId[i].x = this.text[i].x;
            this.textId[i].y = this.text[i].y;
            this.textId[i].scaleX = this.text[i].scaleX;
            this.textId[i].scaleY = this.text[i].scaleY;
            this.textId[i].name = this.text[i].name;
        }
    },

    resource: function (e) {
        stage.addChild(e);
    },

    remove: function (e) {
        stage.removeChild(e);
    },

    interaction: function () {
        this.textId[0].onClick = handleClick;
        this.textId[2].onClick = handleClick;
        function handleClick(event) {
            switch (event.target.name) {
                case "startText":
                    game.init.remove(game.init.textId[0]);
                    game.init.resource(images['circleImg']);
                    game.animation.circle();
                    break;
                case "animationRestart":
                    game.restart();
                    break;
            }
        }
    }
}

game.animation = {
    circle: function () {
        var circleTween = new createjs.Tween.get(images['circleImg'], {
            loop: false
        }).to({
            x: 800
        }, 2000, createjs.Ease.quadIn).call(function () {
            game.animation.callComplete();
        });
    },
    callComplete: function() {
        game.init.resource(game.init.textId[1]);
        game.animation.restartText();
    },
    restartText: function() {
        game.init.resource(game.init.textId[2]);

        var restartBlink = new createjs.Tween.get(game.init.textId[2], {
            loop:true
        }).to({
            scaleX: 1,
            scaleY: 1
        }, 500, createjs.Ease.quadOut)
        .to({
            scaleX: 1.1,
            scaleY: 1.1
        }, 500, createjs.Ease.quadOut)
        .to({
            scaleX: 1,
            scaleY: 1
        }, 500, createjs.Ease.quadOut)
    }

}
game.resetPositions = function() {
    images['circleImg'].x = 0;
}
game.restart = function () {
    stage.removeAllChildren();
    game.resetPositions();
    game.menu();
}
game.menu = function () {
    game.init.resource(game.init.textId[0]);
}


tick = function () {
    stage.update();
}​

JSFiddle

(old version before changes)

Is this a viable basic game structure? How can I improve game data storage (in this basic case text storage) and naming?

EDIT: added repeat functionality and a dedicated namespace.

share|improve this question
add comment

1 Answer

From a once over:

  • Object notation does not require the properties to be quoted, you can simply do this:

    {
      name: "startText",
      content: "START",
      style: "bold 50px Arial",
      color: "red",
      x: 325,
      y: 140,
      scaleX:1,
      scaleY:1
    }
    

    Note that I also removed quotes from the numeric constants, you do not need them.

  • I would have named your text array texts instead of text
  • There are some variables you are not declaring with var : i, images, and loader, this pollutes the global namespace.
  • It is better to use images.circleImg then images['circleImg'].
  • There is no need capture the results of new createjs.Tween into circleTween and restartBlink since you do nothing with those variables
  • The magic number 500, 2000 and 800 in restartText should be capture in a single constant
  • This : this.textId[0].onClick = handleClick; is old skool, please look into addEventListener
  • I would have made stage, totalLoaded and manifest part of game
  • I would add some error handling to loader especially if you are loading an image from a different domain..
  • On a final note, the jsfiddle does not work for me, but then again, this a 2012 question ;)
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.