2013-11-27 16:33:49 +00:00
/ * *
* @ author Richard Davey < rich @ photonstorm . com >
2014-02-05 05:54:25 +00:00
* @ copyright 2014 Photon Storm Ltd .
2013-11-27 16:33:49 +00:00
* @ license { @ link https : //github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
* /
/ * *
* Phaser . TilemapParser parses data objects from Phaser . Loader that need more preparation before they can be inserted into a Tilemap .
*
* @ class Phaser . TilemapParser
* /
2013-10-11 03:42:11 +00:00
Phaser . TilemapParser = {
2013-11-27 16:33:49 +00:00
/ * *
2014-02-21 10:06:53 +00:00
* Parse tilemap data from the cache and creates a Tilemap object .
2014-03-03 13:43:33 +00:00
*
2013-11-27 16:33:49 +00:00
* @ method Phaser . TilemapParser . parse
* @ param { Phaser . Game } game - Game reference to the currently running game .
2013-12-18 16:56:14 +00:00
* @ param { string } key - The key of the tilemap in the Cache .
2014-03-03 13:43:33 +00:00
* @ param { number } [ tileWidth = 32 ] - The pixel width of a single map tile . If using CSV data you must specify this . Not required if using Tiled map data .
* @ param { number } [ tileHeight = 32 ] - The pixel height of a single map tile . If using CSV data you must specify this . Not required if using Tiled map data .
* @ param { number } [ width = 10 ] - The width of the map in tiles . If this map is created from Tiled or CSV data you don ' t need to specify this .
* @ param { number } [ height = 10 ] - The height of the map in tiles . If this map is created from Tiled or CSV data you don ' t need to specify this .
2013-12-18 16:56:14 +00:00
* @ return { object } The parsed map object .
2013-11-27 16:33:49 +00:00
* /
2014-03-03 13:43:33 +00:00
parse : function ( game , key , tileWidth , tileHeight , width , height ) {
if ( typeof tileWidth === 'undefined' ) { tileWidth = 32 ; }
if ( typeof tileHeight === 'undefined' ) { tileHeight = 32 ; }
if ( typeof width === 'undefined' ) { width = 10 ; }
if ( typeof height === 'undefined' ) { height = 10 ; }
2013-12-18 16:56:14 +00:00
2014-03-03 05:19:46 +00:00
if ( typeof key === 'undefined' )
{
return this . getEmptyData ( ) ;
}
2014-03-03 13:43:33 +00:00
if ( key === null )
{
return this . getEmptyData ( tileWidth , tileHeight , width , height ) ;
}
2013-12-18 16:56:14 +00:00
var map = game . cache . getTilemapData ( key ) ;
2013-10-11 05:30:28 +00:00
2013-12-18 16:56:14 +00:00
if ( map )
2013-11-25 04:40:04 +00:00
{
2013-12-18 16:56:14 +00:00
if ( map . format === Phaser . Tilemap . CSV )
{
2014-03-03 13:43:33 +00:00
return this . parseCSV ( key , map . data , tileWidth , tileHeight ) ;
2013-12-18 16:56:14 +00:00
}
2014-03-10 00:50:06 +00:00
else if ( ! map . format || map . format === Phaser . Tilemap . TILED _JSON )
2013-12-18 16:56:14 +00:00
{
return this . parseTiledJSON ( map . data ) ;
}
2013-11-25 04:40:04 +00:00
}
2013-12-18 16:56:14 +00:00
else
2013-11-25 04:40:04 +00:00
{
2014-03-03 05:19:46 +00:00
console . warn ( 'Phaser.TilemapParser.parse - No map data found for key ' + key ) ;
2013-11-25 04:40:04 +00:00
}
2013-10-11 05:30:28 +00:00
2013-11-25 04:40:04 +00:00
} ,
2013-10-11 05:30:28 +00:00
2013-11-25 04:40:04 +00:00
/ * *
2013-11-27 16:33:49 +00:00
* Parses a CSV file into valid map data .
2014-03-03 13:43:33 +00:00
*
2013-11-27 16:33:49 +00:00
* @ method Phaser . TilemapParser . parseCSV
* @ param { string } data - The CSV file data .
2014-03-03 13:43:33 +00:00
* @ param { number } [ tileWidth = 32 ] - The pixel width of a single map tile . If using CSV data you must specify this . Not required if using Tiled map data .
* @ param { number } [ tileHeight = 32 ] - The pixel height of a single map tile . If using CSV data you must specify this . Not required if using Tiled map data .
2013-11-27 16:33:49 +00:00
* @ return { object } Generated map data .
2013-11-25 04:40:04 +00:00
* /
2014-03-03 13:43:33 +00:00
parseCSV : function ( key , data , tileWidth , tileHeight ) {
var map = this . getEmptyData ( ) ;
2013-10-11 03:42:11 +00:00
2013-11-25 04:40:04 +00:00
// Trim any rogue whitespace from the data
data = data . trim ( ) ;
2013-10-11 03:42:11 +00:00
2013-11-25 04:40:04 +00:00
var output = [ ] ;
var rows = data . split ( "\n" ) ;
var height = rows . length ;
var width = 0 ;
2013-10-11 17:18:27 +00:00
2014-03-03 13:43:33 +00:00
for ( var y = 0 ; y < rows . length ; y ++ )
2013-11-25 04:40:04 +00:00
{
2014-03-03 13:43:33 +00:00
output [ y ] = [ ] ;
2013-10-11 03:42:11 +00:00
2014-03-03 13:43:33 +00:00
var column = rows [ y ] . split ( "," ) ;
2013-10-11 05:30:28 +00:00
2014-03-03 13:43:33 +00:00
for ( var x = 0 ; x < column . length ; x ++ )
2013-11-25 04:40:04 +00:00
{
2014-04-28 22:21:57 +00:00
output [ y ] [ x ] = new Phaser . Tile ( map . layers [ 0 ] , parseInt ( column [ x ] , 10 ) , x , y , tileWidth , tileHeight ) ;
2013-11-25 04:40:04 +00:00
}
2013-10-11 05:30:28 +00:00
2013-11-25 04:40:04 +00:00
if ( width === 0 )
{
width = column . length ;
}
}
2014-04-28 22:21:57 +00:00
map . format = Phaser . Tilemap . CSV ;
2014-03-03 13:43:33 +00:00
map . name = key ;
map . width = width ;
map . height = height ;
map . tileWidth = tileWidth ;
map . tileHeight = tileHeight ;
map . widthInPixels = width * tileWidth ;
map . heightInPixels = height * tileHeight ;
2013-12-05 18:12:16 +00:00
2014-03-03 13:43:33 +00:00
map . layers [ 0 ] . width = width ;
map . layers [ 0 ] . height = height ;
map . layers [ 0 ] . widthInPixels = map . widthInPixels ;
map . layers [ 0 ] . heightInPixels = map . heightInPixels ;
map . layers [ 0 ] . data = output ;
return map ;
2013-11-25 04:40:04 +00:00
} ,
2013-10-11 05:30:28 +00:00
2014-02-18 03:01:51 +00:00
/ * *
* Returns an empty map data object .
2014-04-28 22:21:57 +00:00
*
2014-02-18 03:01:51 +00:00
* @ method Phaser . TilemapParser . getEmptyData
* @ return { object } Generated map data .
* /
2014-03-03 13:43:33 +00:00
getEmptyData : function ( tileWidth , tileHeight , width , height ) {
2014-02-18 03:01:51 +00:00
var map = { } ;
map . width = 0 ;
map . height = 0 ;
map . tileWidth = 0 ;
map . tileHeight = 0 ;
2014-03-03 13:43:33 +00:00
if ( typeof tileWidth !== 'undefined' && tileWidth !== null ) { map . tileWidth = tileWidth ; }
if ( typeof tileHeight !== 'undefined' && tileHeight !== null ) { map . tileHeight = tileHeight ; }
if ( typeof width !== 'undefined' && width !== null ) { map . width = width ; }
if ( typeof height !== 'undefined' && height !== null ) { map . height = height ; }
2014-02-18 03:01:51 +00:00
map . orientation = 'orthogonal' ;
map . version = '1' ;
map . properties = { } ;
map . widthInPixels = 0 ;
map . heightInPixels = 0 ;
var layers = [ ] ;
var layer = {
name : 'layer' ,
x : 0 ,
y : 0 ,
width : 0 ,
height : 0 ,
widthInPixels : 0 ,
heightInPixels : 0 ,
alpha : 1 ,
visible : true ,
properties : { } ,
indexes : [ ] ,
callbacks : [ ] ,
data : [ ]
} ;
2014-03-03 13:43:33 +00:00
// fill with nulls?
2014-02-18 03:01:51 +00:00
layers . push ( layer ) ;
map . layers = layers ;
map . images = [ ] ;
map . objects = { } ;
map . collision = { } ;
map . tilesets = [ ] ;
map . tiles = [ ] ;
return map ;
} ,
2013-11-25 04:40:04 +00:00
/ * *
2013-11-27 16:33:49 +00:00
* Parses a Tiled JSON file into valid map data .
* @ method Phaser . TilemapParser . parseJSON
2013-12-18 16:56:14 +00:00
* @ param { object } json - The JSON map data .
* @ return { object } Generated and parsed map data .
2013-11-25 04:40:04 +00:00
* /
parseTiledJSON : function ( json ) {
2013-10-11 05:30:28 +00:00
2013-12-19 03:49:28 +00:00
if ( json . orientation !== 'orthogonal' )
{
console . warn ( 'TilemapParser.parseTiledJSON: Only orthogonal map types are supported in this version of Phaser' ) ;
return null ;
}
// Map data will consist of: layers, objects, images, tilesets, sizes
2013-12-18 04:40:10 +00:00
var map = { } ;
2013-12-05 18:12:16 +00:00
2013-12-19 03:49:28 +00:00
map . width = json . width ;
map . height = json . height ;
map . tileWidth = json . tilewidth ;
map . tileHeight = json . tileheight ;
map . orientation = json . orientation ;
2014-04-28 22:21:57 +00:00
map . format = Phaser . Tilemap . TILED _JSON ;
2013-12-19 03:49:28 +00:00
map . version = json . version ;
map . properties = json . properties ;
map . widthInPixels = map . width * map . tileWidth ;
map . heightInPixels = map . height * map . tileHeight ;
2013-12-18 04:40:10 +00:00
// Tile Layers
2013-11-25 04:40:04 +00:00
var layers = [ ] ;
for ( var i = 0 ; i < json . layers . length ; i ++ )
{
2013-12-18 04:40:10 +00:00
if ( json . layers [ i ] . type !== 'tilelayer' )
2013-11-25 04:40:04 +00:00
{
continue ;
}
var layer = {
name : json . layers [ i ] . name ,
2013-12-05 18:12:16 +00:00
x : json . layers [ i ] . x ,
y : json . layers [ i ] . y ,
2013-11-25 04:40:04 +00:00
width : json . layers [ i ] . width ,
height : json . layers [ i ] . height ,
2013-12-19 03:49:28 +00:00
widthInPixels : json . layers [ i ] . width * json . tilewidth ,
heightInPixels : json . layers [ i ] . height * json . tileheight ,
2013-11-25 04:40:04 +00:00
alpha : json . layers [ i ] . opacity ,
visible : json . layers [ i ] . visible ,
2013-12-05 18:12:16 +00:00
properties : { } ,
2014-01-14 22:34:41 +00:00
indexes : [ ] ,
2014-02-18 03:01:51 +00:00
callbacks : [ ] ,
bodies : [ ]
2013-11-25 04:40:04 +00:00
} ;
2013-12-05 18:12:16 +00:00
if ( json . layers [ i ] . properties )
{
layer . properties = json . layers [ i ] . properties ;
}
var x = 0 ;
var row = [ ] ;
2013-11-25 04:40:04 +00:00
var output = [ ] ;
2013-12-05 18:12:16 +00:00
// Loop through the data field in the JSON.
2014-04-28 22:21:57 +00:00
// This is an array containing the tile indexes, one after the other. -1 = no tile, everything else = the tile index (starting at 1 for Tiled, 0 for CSV)
2014-01-14 22:34:41 +00:00
// If the map contains multiple tilesets then the indexes are relative to that which the set starts from.
2013-12-05 18:12:16 +00:00
// Need to set which tileset in the cache = which tileset in the JSON, if you do this manually it means you can use the same map data but a new tileset.
2013-11-25 04:40:04 +00:00
2013-12-18 04:40:10 +00:00
for ( var t = 0 , len = json . layers [ i ] . data . length ; t < len ; t ++ )
2013-11-25 04:40:04 +00:00
{
2013-12-05 18:12:16 +00:00
// index, x, y, width, height
if ( json . layers [ i ] . data [ t ] > 0 )
{
2014-01-14 22:34:41 +00:00
row . push ( new Phaser . Tile ( layer , json . layers [ i ] . data [ t ] , x , output . length , json . tilewidth , json . tileheight ) ) ;
2013-12-05 18:12:16 +00:00
}
else
{
2014-04-28 22:21:57 +00:00
row . push ( new Phaser . Tile ( layer , - 1 , x , output . length , json . tilewidth , json . tileheight ) ) ;
2013-12-05 18:12:16 +00:00
}
x ++ ;
if ( x === json . layers [ i ] . width )
{
output . push ( row ) ;
x = 0 ;
row = [ ] ;
}
2013-12-18 04:40:10 +00:00
}
2013-12-05 18:12:16 +00:00
2013-12-18 04:40:10 +00:00
layer . data = output ;
2013-12-05 18:12:16 +00:00
2013-12-18 04:40:10 +00:00
layers . push ( layer ) ;
}
map . layers = layers ;
// Images
var images = [ ] ;
2013-11-25 04:40:04 +00:00
2013-12-18 04:40:10 +00:00
for ( var i = 0 ; i < json . layers . length ; i ++ )
{
if ( json . layers [ i ] . type !== 'imagelayer' )
{
continue ;
}
2013-12-05 18:12:16 +00:00
2013-12-18 04:40:10 +00:00
var image = {
name : json . layers [ i ] . name ,
image : json . layers [ i ] . image ,
x : json . layers [ i ] . x ,
y : json . layers [ i ] . y ,
alpha : json . layers [ i ] . opacity ,
visible : json . layers [ i ] . visible ,
properties : { }
} ;
if ( json . layers [ i ] . properties )
{
image . properties = json . layers [ i ] . properties ;
}
2013-11-25 04:40:04 +00:00
2013-12-18 04:40:10 +00:00
images . push ( image ) ;
}
map . images = images ;
2014-03-17 23:27:13 +00:00
// Tilesets
var tilesets = [ ] ;
for ( var i = 0 ; i < json . tilesets . length ; i ++ )
{
// name, firstgid, width, height, margin, spacing, properties
var set = json . tilesets [ i ] ;
var newSet = new Phaser . Tileset ( set . name , set . firstgid , set . tilewidth , set . tileheight , set . margin , set . spacing , set . properties ) ;
if ( set . tileproperties )
{
newSet . tileProperties = set . tileproperties ;
}
newSet . rows = Math . round ( ( set . imageheight - set . margin ) / ( set . tileheight + set . spacing ) ) ;
newSet . columns = Math . round ( ( set . imagewidth - set . margin ) / ( set . tilewidth + set . spacing ) ) ;
newSet . total = newSet . rows * newSet . columns ;
if ( newSet . rows % 1 !== 0 || newSet . columns % 1 !== 0 )
{
console . warn ( 'TileSet image dimensions do not match expected dimensions. Tileset width/height must be evenly divisible by Tilemap tile width/height.' ) ;
}
else
{
tilesets . push ( newSet ) ;
}
}
map . tilesets = tilesets ;
2014-02-18 03:01:51 +00:00
// Objects & Collision Data (polylines, etc)
2013-12-23 04:19:52 +00:00
var objects = { } ;
2014-02-18 03:01:51 +00:00
var collision = { } ;
2013-12-18 04:40:10 +00:00
2014-05-01 11:05:12 +00:00
function slice ( obj , fields ) {
var sliced = { } ;
for ( var k in fields ) {
var key = fields [ k ] ;
sliced [ key ] = obj [ key ] ;
}
return sliced ;
}
2013-12-18 04:40:10 +00:00
for ( var i = 0 ; i < json . layers . length ; i ++ )
{
if ( json . layers [ i ] . type !== 'objectgroup' )
{
continue ;
}
2013-12-23 04:19:52 +00:00
objects [ json . layers [ i ] . name ] = [ ] ;
2014-02-18 03:01:51 +00:00
collision [ json . layers [ i ] . name ] = [ ] ;
2013-12-23 04:19:52 +00:00
for ( var v = 0 , len = json . layers [ i ] . objects . length ; v < len ; v ++ )
2013-12-18 04:40:10 +00:00
{
2014-02-18 03:01:51 +00:00
// Object Tiles
2013-12-18 04:40:10 +00:00
if ( json . layers [ i ] . objects [ v ] . gid )
2013-11-25 04:40:04 +00:00
{
2013-12-18 04:40:10 +00:00
var object = {
gid : json . layers [ i ] . objects [ v ] . gid ,
name : json . layers [ i ] . objects [ v ] . name ,
x : json . layers [ i ] . objects [ v ] . x ,
2014-03-17 23:54:04 +00:00
y : json . layers [ i ] . objects [ v ] . y ,
2013-12-18 04:40:10 +00:00
visible : json . layers [ i ] . objects [ v ] . visible ,
properties : json . layers [ i ] . objects [ v ] . properties
} ;
2014-03-23 07:59:28 +00:00
2013-12-23 04:19:52 +00:00
objects [ json . layers [ i ] . name ] . push ( object ) ;
2013-11-25 04:40:04 +00:00
}
2014-02-18 03:01:51 +00:00
else if ( json . layers [ i ] . objects [ v ] . polyline )
{
var object = {
name : json . layers [ i ] . objects [ v ] . name ,
2014-08-16 19:44:21 +00:00
type : json . layers [ i ] . objects [ v ] . type ,
2014-02-18 03:01:51 +00:00
x : json . layers [ i ] . objects [ v ] . x ,
y : json . layers [ i ] . objects [ v ] . y ,
width : json . layers [ i ] . objects [ v ] . width ,
height : json . layers [ i ] . objects [ v ] . height ,
visible : json . layers [ i ] . objects [ v ] . visible ,
properties : json . layers [ i ] . objects [ v ] . properties
} ;
object . polyline = [ ] ;
// Parse the polyline into an array
for ( var p = 0 ; p < json . layers [ i ] . objects [ v ] . polyline . length ; p ++ )
{
object . polyline . push ( [ json . layers [ i ] . objects [ v ] . polyline [ p ] . x , json . layers [ i ] . objects [ v ] . polyline [ p ] . y ] ) ;
}
collision [ json . layers [ i ] . name ] . push ( object ) ;
}
2014-05-01 11:05:12 +00:00
// polygon
else if ( json . layers [ i ] . objects [ v ] . polygon )
{
var object = slice ( json . layers [ i ] . objects [ v ] ,
2014-08-16 19:44:21 +00:00
[ "name" , "type" , "x" , "y" , "visible" , "properties" ] ) ;
2014-05-01 11:05:12 +00:00
// Parse the polygon into an array
object . polygon = [ ] ;
for ( var p = 0 ; p < json . layers [ i ] . objects [ v ] . polygon . length ; p ++ )
{
object . polygon . push ( [ json . layers [ i ] . objects [ v ] . polygon [ p ] . x , json . layers [ i ] . objects [ v ] . polygon [ p ] . y ] ) ;
}
objects [ json . layers [ i ] . name ] . push ( object ) ;
2013-12-18 04:40:10 +00:00
2014-05-01 11:05:12 +00:00
}
// ellipse
else if ( json . layers [ i ] . objects [ v ] . ellipse )
{
var object = slice ( json . layers [ i ] . objects [ v ] ,
2014-08-16 19:44:21 +00:00
[ "name" , "type" , "ellipse" , "x" , "y" , "width" , "height" , "visible" , "properties" ] ) ;
2014-05-01 11:05:12 +00:00
objects [ json . layers [ i ] . name ] . push ( object ) ;
}
// otherwise it's a rectangle
else
{
var object = slice ( json . layers [ i ] . objects [ v ] ,
2014-08-16 19:44:21 +00:00
[ "name" , "type" , "x" , "y" , "width" , "height" , "visible" , "properties" ] ) ;
2014-05-01 11:05:12 +00:00
object . rectangle = true ;
objects [ json . layers [ i ] . name ] . push ( object ) ;
}
2013-11-25 04:40:04 +00:00
}
2013-12-18 04:40:10 +00:00
}
2013-10-11 05:30:28 +00:00
2013-12-18 04:40:10 +00:00
map . objects = objects ;
2014-02-18 03:01:51 +00:00
map . collision = collision ;
2013-12-05 18:12:16 +00:00
2013-12-19 03:49:28 +00:00
map . tiles = [ ] ;
2013-12-18 16:56:14 +00:00
2013-12-19 03:49:28 +00:00
// Finally lets build our super tileset index
for ( var i = 0 ; i < map . tilesets . length ; i ++ )
2013-12-18 04:40:10 +00:00
{
2013-12-19 03:49:28 +00:00
var set = map . tilesets [ i ] ;
2014-03-23 07:59:28 +00:00
2013-12-19 03:49:28 +00:00
var x = set . tileMargin ;
var y = set . tileMargin ;
2013-12-18 04:40:10 +00:00
2013-12-19 03:49:28 +00:00
var count = 0 ;
var countX = 0 ;
var countY = 0 ;
2013-12-18 04:40:10 +00:00
2013-12-19 03:49:28 +00:00
for ( var t = set . firstgid ; t < set . firstgid + set . total ; t ++ )
{
// Can add extra properties here as needed
map . tiles [ t ] = [ x , y , i ] ;
2013-12-18 16:56:14 +00:00
2013-12-19 03:49:28 +00:00
x += set . tileWidth + set . tileSpacing ;
2013-12-18 16:56:14 +00:00
2013-12-19 03:49:28 +00:00
count ++ ;
2013-10-11 05:30:28 +00:00
2013-12-19 03:49:28 +00:00
if ( count === set . total )
{
break ;
}
2013-12-18 16:56:14 +00:00
2013-12-19 03:49:28 +00:00
countX ++ ;
2013-12-18 16:56:14 +00:00
2013-12-19 03:49:28 +00:00
if ( countX === set . columns )
{
x = set . tileMargin ;
y += set . tileHeight + set . tileSpacing ;
2013-12-18 16:56:14 +00:00
2013-12-19 03:49:28 +00:00
countX = 0 ;
countY ++ ;
2013-12-18 16:56:14 +00:00
2013-12-19 03:49:28 +00:00
if ( countY === set . rows )
{
break ;
}
}
}
2013-12-18 16:56:14 +00:00
2013-11-25 04:40:04 +00:00
}
2013-10-11 03:42:11 +00:00
2014-08-21 20:08:05 +00:00
// assign tile properties
var i , j , k ;
var layer , tile , sid , set ;
// go through each of the map layers
for ( i = 0 ; i < map . layers . length ; i ++ )
{
layer = map . layers [ i ] ;
// rows of tiles
for ( j = 0 ; j < layer . data . length ; j ++ )
{
row = layer . data [ j ] ;
// individual tiles
for ( k = 0 ; k < row . length ; k ++ )
{
tile = row [ k ] ;
if ( tile . index < 0 ) { continue ; }
// find the relevant tileset
sid = map . tiles [ tile . index ] [ 2 ] ;
set = map . tilesets [ sid ] ;
// if that tile type has any properties, add them to the tile object
if ( set . tileProperties && set . tileProperties [ tile . index - set . firstgid ] ) {
tile . properties = set . tileProperties [ tile . index - set . firstgid ] ;
}
}
}
}
2013-12-18 04:40:10 +00:00
return map ;
2013-10-11 03:42:11 +00:00
2013-11-25 04:40:04 +00:00
}
2013-10-11 03:42:11 +00:00
2014-03-23 06:31:02 +00:00
} ;