146 lines
4.1 KiB
JavaScript
146 lines
4.1 KiB
JavaScript
|
/**
|
||
|
* Represents a classic map (level)
|
||
|
*
|
||
|
* 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 <http://www.gnu.org/licenses/>.
|
||
|
*
|
||
|
*
|
||
|
* Each map is concatenated in the file and consists of the following
|
||
|
* information:
|
||
|
*
|
||
|
* - Playfield data (game objects), 16x16 multidimensional char array
|
||
|
* - Level name, 31 characters
|
||
|
* - Hint, 256 characters
|
||
|
* - Author, 31 characters
|
||
|
* - Difficulty, 16-bit integer, little endian
|
||
|
*
|
||
|
* One can easily calculate the position of the level in a file, given its
|
||
|
* number, by multiplying by the size of the data structure (see TLEVEL, LTANK.H
|
||
|
* in the original sources).
|
||
|
*
|
||
|
* It is worth mentioning how the playfield data is stored. Since the
|
||
|
* multidimensional array is defined as [x][y], the array is created as an
|
||
|
* "array of columns", meaning that the data is organized in columns instead of
|
||
|
* rows. For example, when viewing the data in a HEX editor that displays 16
|
||
|
* bytes per line (e.g. xxd), the map would appear to be mirrored rotated 90
|
||
|
* degrees counter-clockwise. To make it easier to visualize, one can create a
|
||
|
* map with a number of tunnels in a pattern to take advantage of the ASCII
|
||
|
* display.
|
||
|
*/
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Represents a classic map, as they exist in the original game.
|
||
|
*
|
||
|
* Classic maps are 16x16 tiles in size (for a total of 256 tiles).
|
||
|
*/
|
||
|
ltjs.ClassicMap = Class( 'ClassicMap' )
|
||
|
.implement( ltjs.Map )
|
||
|
.extend(
|
||
|
{
|
||
|
'private const _SIZE': 590,
|
||
|
|
||
|
/**
|
||
|
* Game object size
|
||
|
*
|
||
|
* The game objects are stores as a 16x16 multi-dimensional signed char
|
||
|
* array (in the C sources).
|
||
|
*
|
||
|
* @type {number}
|
||
|
*/
|
||
|
'private const _GOSIZE': 256,
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Map set data (binary string)
|
||
|
* @type {string}
|
||
|
*/
|
||
|
'private _data': null,
|
||
|
|
||
|
/**
|
||
|
* Map id (1-indexed)
|
||
|
* @type {string}
|
||
|
*/
|
||
|
'private _id': 0,
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Initialize map with map data and the given id
|
||
|
*
|
||
|
* @param {ltjs.MapSet} set map set data
|
||
|
* @param {number} id 1-indexed map id
|
||
|
*/
|
||
|
__construct: function( data, id )
|
||
|
{
|
||
|
this._data = ''+( data );
|
||
|
this._id = +id;
|
||
|
},
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Retrieve game objects
|
||
|
*
|
||
|
* The game objects are returned in a manner consistent with the original
|
||
|
* sources - in columns, not rows. The reason for this is that the original
|
||
|
* game uses a multi-dimensional array [x][y], which creates an array of
|
||
|
* columns (TPLAYFIELD, LTANK.H).
|
||
|
*
|
||
|
* @return {Array.<number>} array of game objects
|
||
|
*/
|
||
|
'public getObjects': function()
|
||
|
{
|
||
|
// calculate offset in LVL file
|
||
|
var offset = ( this.__self.$( '_SIZE' ) * ( this._id - 1 ) );
|
||
|
return this._getMapData( offset );
|
||
|
},
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Retrieve the map data (game objects only) at the requested offset
|
||
|
*
|
||
|
* The object data at the requested position will be loaded and converted to
|
||
|
* integers (from a binary string).
|
||
|
*
|
||
|
* @param {number} offset offset of the requested map data
|
||
|
*
|
||
|
* @return {Array.<number>} converted map data
|
||
|
*/
|
||
|
'private _getMapData': function( offset )
|
||
|
{
|
||
|
var tiles = this._data.substr( offset, this.__self.$( '_GOSIZE' ) )
|
||
|
.split( '' ),
|
||
|
|
||
|
i = tiles.length;
|
||
|
|
||
|
while ( i-- )
|
||
|
{
|
||
|
tiles[ i ] = tiles[ i ].charCodeAt( 0 );
|
||
|
}
|
||
|
|
||
|
return tiles;
|
||
|
},
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Retrieve map dimensions
|
||
|
*
|
||
|
* @return {Array.<number>} width and height in tiles
|
||
|
*/
|
||
|
'public getDimensions': function()
|
||
|
{
|
||
|
return [ 16, 16 ];
|
||
|
}
|
||
|
} );
|