/** * Interface representing a facade for a game type * * Copyright (C) 2012 Mike Gerwitz * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ /** * Facade for the classic (original) game of LaserTank */ ltjs.ClassicGame = Class( 'ClassicGame' ) .implement( ltjs.Game ) .extend( { /** * LTG loader * @type {ltjs.LtgLoader} */ 'private _ltgLoader': null, /** * Tile masker * @type {ltjs.TileMasker} */ 'private _masker': null, /** * Tiles * @type {Object.} */ 'private _tileSet': null, /** * Set of available maps * @type {ltjs.MapSet} */ 'private _mapSet': null, /** * Event handlers * @type {Object.} */ 'private _callback': {}, /** * Performs map rendering * @type {ltjs.MapRender} */ 'private _render': null, /** * Classic game object factory * @type {ltjs.ClassicGameObjectFactory} */ 'private _gameObjFactory': null, /** * Initialize game with LTG and LVL data * * The LTG and LVL data can be changed at any time, but are required in the * constructor because they are needed in order for the game to be * functional. * * @param {string} ltg_data binary string containing LTG file data * @param {string} lvl_data binary string containing LVL file data */ __construct: function( ltg_data, lvl_data ) { var _self = this; this._ltgLoader = ltjs.LtgLoader(); this._masker = ltjs.TileMasker( ltjs.ClassicTileDfn() ); this._gameObjFactory = ltjs.ClassicGameObjectFactory(); // load initial tile and map data from the LTG and LVL data this.setTileData( ltg_data, function() { this.setMapData( lvl_data, function() { _self._trigger( 'ready' ); } ); } ); }, /** * Render to the given 2d canvas context * * @param {CanvasRenderingContext2d} ctx 2d canvas context * * @return {ClassicGame} self */ 'public renderTo': function( ctx ) { // if there is a previous renderer, free its canvas before continuing // (to both clean up and to free any locks, allowing for tile set and // map changes) if ( this._render ) { this._render.clearCanvas(); } var map = this._mapSet.getMapByNumber( 1 ), map_state = ltjs.MapState( map, this._gameObjFactory ), bounds = ltjs.MapBounds( map ); // render the first map (hardcoded for now) this._render = ltjs.MapRender( ctx, this._tileSet ) .render( map, map_state ); // POC window.onkeydown = function( event ) { var dir; switch ( event.keyCode ) { case 37: case 38: case 39: case 40: dir = event.keyCode - 37; break; default: return; } map_state.movePlayer( dir, bounds ); }; return this; }, /** * Set LTG data for tiles * * @param {string} data binary string containing LTG data * @param {function()} callback function to call when complete * * @return {ClassicGame} self */ 'public setTileData': function( data, callback ) { // get tile metadata var _self = this, meta = this._ltgLoader.fromString( data ); this._masker.getMaskedTiles( meta.tiles, meta.mask, function( tdata ) { _self._tileSet = tdata; callback.call( _self.__inst ); } ); return this; }, /** * Set LVL data for maps * * @param {string} data binary string containing LVL data * @param {function()} callback function to call when complete * * @return {ClassicGame} self */ 'public setMapData': function( data, callback ) { this._mapSet = ltjs.MapSet( data, ltjs.ClassicMap ); callback.call( this.__inst ); return this; }, /** * Attach event handler * * This is a very basic system and allows for only a single event to be * attached at a time (that is all that is needed at this point) * * @param {string} name event name * @param {Function} callback event callback * * @return {ClassicGame} self */ 'public on': function( name, callback ) { this._callback[ name ] = callback; return this; }, /** * Trigger an event, invoking its callback * * @param {string} name event name * * @return {ClassicGame} self */ 'private _trigger': function( name ) { if ( typeof this._callback[ name ] === 'function' ) { this._callback[ name ].call( this.__inst ); } } } );