• Register

Conquer the universe using tactics in an universe with limited resources. Planets, upgrades, zombies, DNA, badges.

Post news Report RSS Some source code released

Some source code of my game has been released. This might be good for inspiration for other developers and a learning example.

Posted by on

View complete gist here. ( Gist.github.com )
BlockStore.js

 define(function(require, exports, module){
    var _               = require('underscore');
    var utils           = require('client/utils');
    var Phaser          = require('phaser');
    var Block           = require('../actors/Block');
    var PlanetGenerator = require('client/PlanetGenerator')
    var constants       = require('client/constants');
    var EventEmitter    = require('eventEmitter');





    var BlockStore = function(options){
        _.extend(this, {
            api    : null,
            stores : {},
        },options);
        this.__shipsById             = {};
        this.__planetsById           = {};
        this.__planetsByBlockId      = [];
        this.__blocksIdByPlanetId    = {};
        this.__blocksById            = [];
        this.__blocksByPos           = {};
        this.__selectedBlocksHistory = [];
        this.__onPlanetChangeBinded  = this.__onPlanetChange.bind(this);
        this.onBlockUpdated          = new Phaser.Signal();
        this.invalidateInBoundsBlocks();
        this.generateEmptyBlocks();


        var appDispatcher  = options.appDispatcher;
        this.dispatchToken = appDispatcher.register(this.onAppDispatcherAction.bind(this))
    }





    BlockStore.getBoundingBoxStepped = function(view, step){
        // Adjusting so we don't care about negative values
        var adjustX = 0;
        if(view.x < 0){
            adjustX = step * Math.ceil(-view.x/step);
        }
        view.x += adjustX;
        var adjustY = 0;
        if(view.y < 0){
            adjustY = step * Math.ceil(-view.y/step);
        }
        view.y += adjustY;

        var leftBoundingBox = view.x - view.x % step - adjustX;
        var topBoundingBox  = view.y - view.y % step - adjustY;
        var horizontalSteps = Math.ceil((view.width  + view.x % step) / step);
        var verticalSteps   = Math.ceil((view.height + view.y % step) / step);
        var width           = step * horizontalSteps;
        var height          = step * verticalSteps;
        return {
            x               : leftBoundingBox,
            y               : topBoundingBox,
            width           : width,
            height          : height,
            horizontalSteps : horizontalSteps,
            verticalSteps   : verticalSteps,
            leftStep        : leftBoundingBox / step,
            topStep         : topBoundingBox / step,
        }
    }




    _.extend(BlockStore.prototype, EventEmitter.prototype, {
        onAppDispatcherAction: function(payload){
            var action = payload.action;
            switch(action.type){
                case 'players.unlockBlock':
                    // @todo.
                    break;

                default:
                    // do nothing
              }
        },



        selectBlock: function(block){
            this.selectedBlock = block;
            this.__selectedBlocksHistory.push(block);
        },



        getLastXSelectedBlocks: function(howMany){
            return _.last(this.__selectedBlocksHistory, howMany)
        },



        getVisibleBlocks: function(){
            var last2SelectedBlocks = this.getLastXSelectedBlocks(2);
            console.log(last2SelectedBlocks.length)
            return last2SelectedBlocks
        },



        updateAuthorizedBlocks: function(){
            var unlockedBlocksIds = this.stores.authStore.currentPlayer.unlockedBlocksIds;
            unlockedBlocksIds.forEach(function(blockId){
                var block = this.getBlockById(blockId);
                block.setAuthorized(true);
            }.bind(this))
        },



        invalidateInBoundsBlocks: function(){
            this.__inBoundsBlocksAreDirty = true;
        },



        updateInBoundsBlocks: function(){
            if(!this.__inBoundsBlocksAreDirty) return;
            // Use camera
            var cameraVisibleRect = this.stores.cameraStore.getVisibleArea();
            // Don't consider scale.
            // The origin of the blocks is (0, 0)
            var blockSize = constants.BLOCK_SIZE;
            var boundingBoxStepped = BlockStore.getBoundingBoxStepped(cameraVisibleRect, blockSize);
            var inBoundsBlocksIds  = [];
            var inBoundsBlocksById = {};
            var inBoundsBlocks     = [];
            var block;
            var currentPlayer = this.stores.authStore.currentPlayer;
            for(var x = boundingBoxStepped.leftStep; x < boundingBoxStepped.leftStep + boundingBoxStepped.horizontalSteps; x++){
                for(var y = boundingBoxStepped.topStep; y < boundingBoxStepped.topStep + boundingBoxStepped.verticalSteps; y++){
                    block = this.getBlockByXY(x, y);
                    // if(currentPlayer.unlockedBlocksIds.indexOf(block._id) === -1) continue;
                    inBoundsBlocksIds.push(block._id);
                    inBoundsBlocks.push(block);
                    inBoundsBlocksById[block._id] = block;
                }
            }
            this.__inBoundsBlocksIds      = inBoundsBlocksIds;
            this.__inBoundsBlocksById     = inBoundsBlocksById;
            this.__inBoundsBlocks         = inBoundsBlocks;
            this.__inBoundsBlocksAreDirty = false;
        },



        getInBoundsBlocks: function(){
            this.updateInBoundsBlocks();
            return this.__inBoundsBlocks;
        },



        getInBoundsBlocksIds: function(){
            this.updateInBoundsBlocks();
            return this.__inBoundsBlocksIds;
        },



        getInBoundsBlocksById: function(){
            this.updateInBoundsBlocks();
            return this.__inBoundsBlocksById;
        },



        getRenderedBlocks: function(){
            return this.__blocksById.filter(function(block){
                return block.isRendered();
            })
        },



        getOutOfBoundsRenderedBlocks: function(){
            var renderedBlocks             = this.getRenderedBlocks();
            var authorizedAndInBoundsBlocks = this.getAuthorizedAndInBoundsBlocks();
            var outOfBoundsRenderedBlocks  = _.difference(renderedBlocks, authorizedAndInBoundsBlocks);
            return outOfBoundsRenderedBlocks;
        },



        getAuthorizedAndInBoundsBlocks: function(){
            return this.getInBoundsBlocks().filter(function(block){
                return this.blockIdIsAuthorized(block._id);
            }.bind(this))
        },



        blockIdIsAuthorized: function(blockId){
            return this.stores.authStore.currentPlayer.unlockedBlocksIds.indexOf(blockId) !== -1;
        },



        generateEmptyBlocks: function(){
            var i = 1000;
            while(i--){
                var blockPos = PlanetGenerator.getXYFromUlamSpiralIndex(i);
                this.addBlock(new Block({
                    _id  : i,
                    pos  : blockPos,
                    game : this.game,
                }))
            }
        },



        getBlockByWorldPosXY: function(x, y){
            var blockX = Math.floor(x / constants.BLOCK_SIZE);
            var blockY = Math.floor(y / constants.BLOCK_SIZE);
            return this.getBlockByXY(blockX, blockY);
        },



        getAllShips: function(){
            var activeShips = [];
            _.forEach(this.__shipsById, function(ship){
                if(ship.destinationReached) return;
                activeShips.push(ship);
            })
            return activeShips;
        },



        replaceShipId: function(oldShipId, newShipId){
            var ship = this.__shipsById[oldShipId];
            delete this.__shipsById[oldShipId];
            this.__shipsById[newShipId] = ship;
            ship._id = newShipId;
        },



        addShip: function(ship){
            // Can happen when the ship travel between blocks because we
            // get the ships by a certain block, therefore no need to render
            // it again, as it's the exact same ship.
            if(this.hasShip(ship)) return;
            this.__shipsById[ship._id] = ship;
            this.onBlockUpdated.dispatch(ship.from.block);
        },



        hasShip: function(ship){
            return !!this.__shipsById[ship._id];
        },



        removeShipById: function(shipId){
            var ship = this.__shipsById[shipId];
            delete this.__shipsById[shipId];
            this.onBlockUpdated.dispatch(ship.to.block);
        },



        __addPlanet: function(planet){
            if(!planet) throw new Error('no planet')
            var planetId = planet._id;
            if(planetId === void 0) throw new Error('no planet id')
            if(this.__planetsById[planetId]) throw new Error('planet already added')
            this.__planetsById[planetId] = planet;
            if(!this.__planetsByBlockId[planet.block.id]){
                this.__planetsByBlockId[planet.block.id] = [];
            }
            this.__planetsByBlockId[planet.block.id].push(planet);
            planet.onChange = this.__onPlanetChangeBinded;
        },



        __onPlanetChange: function(planet, what){
            this.onBlockUpdated.dispatch(planet.block.id, what, planet);
        },



        setBlockPlanets: function(blockId, planets){
            var _this = this;
            planets.forEach(function(planet){
                _this.__addPlanet(planet)
            })
            this.onBlockUpdated.dispatch(blockId);
        },



        getPlanetsInBlockId: function(blockId){
            var planets = this.__planetsByBlockId[blockId];
            return planets ? planets.slice() : false;
        },



        getPlanetById: function(planetId){
            if(planetId === void 0) throw new Error('add a planet id')
            return this.__planetsById[planetId];
        },



        getAllPlanets: function(){
            return _.extend({}, this.__planetsById);
        },



        addBlock: function(block){
            this.__blocksById[block._id] = block;
            this.__blocksByPos[block.getPosAsString()] = block;
        },



        getBlockByXY: function(x, y){
            return this.__blocksByPos[Block.getPosXYAsString(x, y)];
        },



        getBlockByPosString: function(posString){
            return this.__blocksByPos[posString];
        },



        getBlockByPosObject: function(posObject){
            return this.getBlockByPosString(Block.getPosObjectAsString(posObject));
        },



        getBlockById: function(id){
            return this.__blocksById[id];
        },
    })





    return BlockStore;
});
Post a comment

Your comment will be anonymous unless you join the community. Or sign in with your social account: