kittykatattack / ga

The world's tiniest, cutest and funnest game engine
451 stars 85 forks source link

Introducing classes to GA. #26

Closed qsrahman closed 9 years ago

qsrahman commented 9 years ago

The code of GA is indeed simple and easy to understand. I also like your down to earth explanations in the code comments. However the way you define and return objects in the code is although simple but IMHO not standard. Is there any reason for this style or it is just because this style is easier?

I re wrote the whole GA code using 'standard' class based style. In this way it is easier to extend basic GA objects. e.g if a user wants to extend Sprite object he can do it as:

var Player = GA.Sprite.extend({
    init: function(source, x, y) {
        this._super(source);
        this.x = x || 0;
        this.y = y || 0;
    },
    update: function(dt) {

    }
});

var player = new Player('cube.png', 180, 40);

Also objects can be extended on the fly as all objects have a merge method which adds functionality to any object e.g in GA GameObject if interactive property is set to true interaction capability is added to the GameObject:

.....
interactive: {
    get: function() {
        return this._interactive;
    },
    set: function(value) {
        if(value === true) {
            this.merge(InteractionObj); // add interaction
            Q.buttons.push(this);
            this._interactive = true;
        }
        else if(value === false) {
            var idx = Q.buttons.indexOf(this);
            if(idx !== -1)
                Q.buttons.splice(idx, 1);

            for(prop in InteractionObj) {   // remove interaction
                delete this[prop];
            }
            this._interactive = false;
        }
    },
    enumerable: true, configurable: true
},
.....

I think with the introduction of these changes GA will become an extendable game engine :)

kittykatattack commented 9 years ago

Using functional composition rather than classes was an artistic choice. It avoids the need to use this, prototype and new which reduces clutter and keeps the line lengths short (it also helps meet the 6.5k compressed file size target limit for the core ga.js file). And, Ga is in large part an experiment in seeing how small a 2D game engine can be (Phaser is 744 kb compressed!).

Extending an object using composition is just matter of sending it to a function, and having that function apply new properties and methods:

oldSprite = sprite();
betterSprite = addNewPropertiesAndMethods(oldSprite);

function addNewPropertiesAndMethods(anySprite) {
  //Add the new properties and methods
  anySprite.newMethod = function(){};
  anySprite.newProperty = 0;
  return anySprite;
}

The effect is the same as using a JavaScript class (which is also just a function that returns itself as an object). But it's just a matter of which style you prefer :)

kittykatattack commented 9 years ago

Another issue related to this: https://github.com/kittykatattack/ga/issues/34