forked from phaserjs/phaser
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTilemap.js
More file actions
1894 lines (1524 loc) · 64.5 KB
/
Tilemap.js
File metadata and controls
1894 lines (1524 loc) · 64.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/**
* @author Richard Davey <[email protected]>
* @copyright 2014 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
/**
* Creates a new Phaser.Tilemap object. The map can either be populated with data from a Tiled JSON file or from a CSV file.
* To do this pass the Cache key as the first parameter. When using Tiled data you need only provide the key.
* When using CSV data you must provide the key and the tileWidth and tileHeight parameters.
* If creating a blank tilemap to be populated later, you can either specify no parameters at all and then use `Tilemap.create` or pass the map and tile dimensions here.
* Note that all Tilemaps use a base tile size to calculate dimensions from, but that a TilemapLayer may have its own unique tile size that overrides it.
* A Tile map is rendered to the display using a TilemapLayer. It is not added to the display list directly itself.
* A map may have multiple layers. You can perform operations on the map data such as copying, pasting, filling and shuffling the tiles around.
*
* @class Phaser.Tilemap
* @constructor
* @param {Phaser.Game} game - Game reference to the currently running game.
* @param {string} [key] - The key of the tilemap data as stored in the Cache. If you're creating a blank map either leave this parameter out or pass `null`.
* @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.
*/
Phaser.Tilemap = function (game, key, tileWidth, tileHeight, width, height) {
/**
* @property {Phaser.Game} game - A reference to the currently running Game.
*/
this.game = game;
/**
* @property {string} key - The key of this map data in the Phaser.Cache.
*/
this.key = key;
var data = Phaser.TilemapParser.parse(this.game, key, tileWidth, tileHeight, width, height);
if (data === null)
{
return;
}
/**
* @property {number} width - The width of the map (in tiles).
*/
this.width = data.width;
/**
* @property {number} height - The height of the map (in tiles).
*/
this.height = data.height;
/**
* @property {number} tileWidth - The base width of the tiles in the map (in pixels).
*/
this.tileWidth = data.tileWidth;
/**
* @property {number} tileHeight - The base height of the tiles in the map (in pixels).
*/
this.tileHeight = data.tileHeight;
/**
* @property {string} orientation - The orientation of the map data (as specified in Tiled), usually 'orthogonal'.
*/
this.orientation = data.orientation;
/**
* @property {number} format - The format of the map data, either Phaser.Tilemap.CSV or Phaser.Tilemap.TILED_JSON.
*/
this.format = data.format;
/**
* @property {number} version - The version of the map data (as specified in Tiled, usually 1).
*/
this.version = data.version;
/**
* @property {object} properties - Map specific properties as specified in Tiled.
*/
this.properties = data.properties;
/**
* @property {number} widthInPixels - The width of the map in pixels based on width * tileWidth.
*/
this.widthInPixels = data.widthInPixels;
/**
* @property {number} heightInPixels - The height of the map in pixels based on height * tileHeight.
*/
this.heightInPixels = data.heightInPixels;
/**
* @property {array} layers - An array of Tilemap layer data.
*/
this.layers = data.layers;
/**
* @property {array} tilesets - An array of Tilesets.
*/
this.tilesets = data.tilesets;
/**
* @property {array} tiles - The super array of Tiles.
*/
this.tiles = data.tiles;
/**
* @property {array} objects - An array of Tiled Object Layers.
*/
this.objects = data.objects;
/**
* @property {array} collideIndexes - An array of tile indexes that collide.
*/
this.collideIndexes = [];
/**
* @property {array} collision - An array of collision data (polylines, etc).
*/
this.collision = data.collision;
/**
* @property {array} images - An array of Tiled Image Layers.
*/
this.images = data.images;
/**
* @property {number} currentLayer - The current layer.
*/
this.currentLayer = 0;
/**
* @property {array} debugMap - Map data used for debug values only.
*/
this.debugMap = [];
/**
* @property {array} _results - Internal var.
* @private
*/
this._results = [];
/**
* @property {number} _tempA - Internal var.
* @private
*/
this._tempA = 0;
/**
* @property {number} _tempB - Internal var.
* @private
*/
this._tempB = 0;
};
/**
* @constant
* @type {number}
*/
Phaser.Tilemap.CSV = 0;
/**
* @constant
* @type {number}
*/
Phaser.Tilemap.TILED_JSON = 1;
/**
* @constant
* @type {number}
*/
Phaser.Tilemap.NORTH = 0;
/**
* @constant
* @type {number}
*/
Phaser.Tilemap.EAST = 1;
/**
* @constant
* @type {number}
*/
Phaser.Tilemap.SOUTH = 2;
/**
* @constant
* @type {number}
*/
Phaser.Tilemap.WEST = 3;
Phaser.Tilemap.prototype = {
/**
* Creates an empty map of the given dimensions and one blank layer. If layers already exist they are erased.
*
* @method Phaser.Tilemap#create
* @param {string} name - The name of the default layer of the map.
* @param {number} width - The width of the map in tiles.
* @param {number} height - The height of the map in tiles.
* @param {number} tileWidth - The width of the tiles the map uses for calculations.
* @param {number} tileHeight - The height of the tiles the map uses for calculations.
* @param {Phaser.Group} [group] - Optional Group to add the layer to. If not specified it will be added to the World group.
* @return {Phaser.TilemapLayer} The TilemapLayer object. This is an extension of Phaser.Image and can be moved around the display list accordingly.
*/
create: function (name, width, height, tileWidth, tileHeight, group) {
if (typeof group === 'undefined') { group = this.game.world; }
this.width = width;
this.height = height;
this.setTileSize(tileWidth, tileHeight);
this.layers.length = 0;
return this.createBlankLayer(name, width, height, tileWidth, tileHeight, group);
},
/**
* Sets the base tile size for the map.
*
* @method Phaser.Tilemap#setTileSize
* @param {number} tileWidth - The width of the tiles the map uses for calculations.
* @param {number} tileHeight - The height of the tiles the map uses for calculations.
*/
setTileSize: function (tileWidth, tileHeight) {
this.tileWidth = tileWidth;
this.tileHeight = tileHeight;
this.widthInPixels = this.width * tileWidth;
this.heightInPixels = this.height * tileHeight;
},
/**
* Adds an image to the map to be used as a tileset. A single map may use multiple tilesets.
* Note that the tileset name can be found in the JSON file exported from Tiled, or in the Tiled editor.
*
* @method Phaser.Tilemap#addTilesetImage
* @param {string} tileset - The name of the tileset as specified in the map data.
* @param {string} [key] - The key of the Phaser.Cache image used for this tileset. If not specified it will look for an image with a key matching the tileset parameter.
* @param {number} [tileWidth=32] - The width of the tiles in the Tileset Image. If not given it will default to the map.tileWidth value, if that isn't set then 32.
* @param {number} [tileHeight=32] - The height of the tiles in the Tileset Image. If not given it will default to the map.tileHeight value, if that isn't set then 32.
* @param {number} [tileMargin=0] - The width of the tiles in the Tileset Image. If not given it will default to the map.tileWidth value.
* @param {number} [tileSpacing=0] - The height of the tiles in the Tileset Image. If not given it will default to the map.tileHeight value.
* @param {number} [gid=0] - If adding multiple tilesets to a blank/dynamic map, specify the starting GID the set will use here.
* @return {Phaser.Tileset} Returns the Tileset object that was created or updated, or null if it failed.
*/
addTilesetImage: function (tileset, key, tileWidth, tileHeight, tileMargin, tileSpacing, gid) {
if (typeof tileWidth === 'undefined') { tileWidth = this.tileWidth; }
if (typeof tileHeight === 'undefined') { tileHeight = this.tileHeight; }
if (typeof tileMargin === 'undefined') { tileMargin = 0; }
if (typeof tileSpacing === 'undefined') { tileSpacing = 0; }
if (typeof gid === 'undefined') { gid = 0; }
// In-case we're working from a blank map
if (tileWidth === 0)
{
tileWidth = 32;
}
if (tileHeight === 0)
{
tileHeight = 32;
}
if (typeof key === 'undefined')
{
if (typeof tileset === 'string')
{
key = tileset;
if (!this.game.cache.checkImageKey(key))
{
console.warn('Phaser.Tilemap.addTilesetImage: Invalid image key given: "' + key + '"');
return null;
}
}
else
{
return null;
}
}
if (typeof tileset === 'string')
{
tileset = this.getTilesetIndex(tileset);
if (tileset === null && this.format === Phaser.Tilemap.TILED_JSON)
{
console.warn('Phaser.Tilemap.addTilesetImage: No data found in the JSON matching the tileset name: "' + key + '"');
return null;
}
}
if (this.tilesets[tileset])
{
this.tilesets[tileset].setImage(this.game.cache.getImage(key));
return this.tilesets[tileset];
}
else
{
var newSet = new Phaser.Tileset(key, gid, tileWidth, tileHeight, tileMargin, tileSpacing, {});
newSet.setImage(this.game.cache.getImage(key));
this.tilesets.push(newSet);
var i = this.tilesets.length - 1;
var x = tileMargin;
var y = tileMargin;
var count = 0;
var countX = 0;
var countY = 0;
for (var t = gid; t < gid + newSet.total; t++)
{
this.tiles[t] = [x, y, i];
x += tileWidth + tileSpacing;
count++;
if (count === newSet.total)
{
break;
}
countX++;
if (countX === newSet.columns)
{
x = tileMargin;
y += tileHeight + tileSpacing;
countX = 0;
countY++;
if (countY === newSet.rows)
{
break;
}
}
}
return newSet;
}
return null;
},
/**
* Creates a Sprite for every object matching the given gid in the map data. You can optionally specify the group that the Sprite will be created in. If none is
* given it will be created in the World. All properties from the map data objectgroup are copied across to the Sprite, so you can use this as an easy way to
* configure Sprite properties from within the map editor. For example giving an object a property of alpha: 0.5 in the map editor will duplicate that when the
* Sprite is created. You could also give it a value like: body.velocity.x: 100 to set it moving automatically.
*
* @method Phaser.Tilemap#createFromObjects
* @param {string} name - The name of the Object Group to create Sprites from.
* @param {number} gid - The layer array index value, or if a string is given the layer name within the map data.
* @param {string} key - The Game.cache key of the image that this Sprite will use.
* @param {number|string} [frame] - If the Sprite image contains multiple frames you can specify which one to use here.
* @param {boolean} [exists=true] - The default exists state of the Sprite.
* @param {boolean} [autoCull=false] - The default autoCull state of the Sprite. Sprites that are autoCulled are culled from the camera if out of its range.
* @param {Phaser.Group} [group=Phaser.World] - Group to add the Sprite to. If not specified it will be added to the World group.
* @param {object} [CustomClass=Phaser.Sprite] - If you wish to create your own class, rather than Phaser.Sprite, pass the class here. Your class must extend Phaser.Sprite and have the same constructor parameters.
* @param {boolean} [adjustY=true] - By default the Tiled map editor uses a bottom-left coordinate system. Phaser uses top-left. So most objects will appear too low down. This parameter moves them up by their height.
*/
createFromObjects: function (name, gid, key, frame, exists, autoCull, group, CustomClass, adjustY) {
if (typeof exists === 'undefined') { exists = true; }
if (typeof autoCull === 'undefined') { autoCull = false; }
if (typeof group === 'undefined') { group = this.game.world; }
if (typeof CustomClass === 'undefined') { CustomClass = Phaser.Sprite; }
if (typeof adjustY === 'undefined') { adjustY = true; }
if (!this.objects[name])
{
console.warn('Tilemap.createFromObjects: Invalid objectgroup name given: ' + name);
return;
}
var sprite;
for (var i = 0, len = this.objects[name].length; i < len; i++)
{
if (this.objects[name][i].gid === gid)
{
sprite = new CustomClass(this.game, this.objects[name][i].x, this.objects[name][i].y, key, frame);
sprite.name = this.objects[name][i].name;
sprite.visible = this.objects[name][i].visible;
sprite.autoCull = autoCull;
sprite.exists = exists;
if (adjustY)
{
sprite.y -= sprite.height;
}
group.add(sprite);
for (var property in this.objects[name][i].properties)
{
group.set(sprite, property, this.objects[name][i].properties[property], false, false, 0, true);
}
}
}
},
/**
* Creates a Sprite for every object matching the given tile indexes in the map data.
* You can specify the group that the Sprite will be created in. If none is given it will be created in the World.
* You can optional specify if the tile will be replaced with another after the Sprite is created. This is useful if you want to lay down special
* tiles in a level that are converted to Sprites, but want to replace the tile itself with a floor tile or similar once converted.
*
* @method Phaser.Tilemap#createFromTiles
* @param {integer|Array} tiles - The tile index, or array of indexes, to create Sprites from.
* @param {integer|Array} replacements - The tile index, or array of indexes, to change a converted tile to. Set to `null` to not change.
* @param {string} key - The Game.cache key of the image that this Sprite will use.
* @param {Phaser.Group} [group=Phaser.World] - Group to add the Sprite to. If not specified it will be added to the World group.
* @param {object} [properties] - An object that contains the default properties for your newly created Sprite. This object will be iterated and any matching Sprite property will be set.
* @param {number|string|Phaser.TilemapLayer} [layer] - The layer to operate on.
* @return {integer} The number of Sprites that were created.
*/
createFromTiles: function (tiles, replacements, key, layer, group, properties) {
if (typeof tiles === 'number') { tiles = [tiles]; }
if (typeof replacements === 'undefined' || replacements === null)
{
replacements = [];
}
else if (typeof replacements === 'number')
{
replacements = [replacements];
}
layer = this.getLayer(layer);
if (typeof group === 'undefined') { group = this.game.world; }
if (typeof properties === 'undefined') { properties = {}; }
if (properties.customClass === undefined)
{
properties.customClass = Phaser.Sprite;
}
if (properties.adjustY === undefined)
{
properties.adjustY = true;
}
var lw = this.layers[layer].width;
var lh = this.layers[layer].height;
this.copy(0, 0, lw, lh, layer);
if (this._results.length < 2)
{
return 0;
}
var total = 0;
var sprite;
for (var i = 1, len = this._results.length; i < len; i++)
{
if (tiles.indexOf(this._results[i].index) !== -1)
{
sprite = new properties.customClass(this.game, this._results[i].worldX, this._results[i].worldY, key);
for (var property in properties)
{
sprite[property] = properties[property];
}
group.add(sprite);
total++;
}
}
if (replacements.length === 1)
{
// Assume 1 replacement for all types of tile given
for (i = 0; i < tiles.length; i++)
{
this.replace(tiles[i], replacements[0], 0, 0, lw, lh, layer);
}
}
else if (replacements.length > 1)
{
// Assume 1 for 1 mapping
for (i = 0; i < tiles.length; i++)
{
this.replace(tiles[i], replacements[i], 0, 0, lw, lh, layer);
}
}
return total;
},
/**
* Creates a new TilemapLayer object. By default TilemapLayers are fixed to the camera.
* The `layer` parameter is important. If you've created your map in Tiled then you can get this by looking in Tiled and looking at the Layer name.
* Or you can open the JSON file it exports and look at the layers[].name value. Either way it must match.
* If you wish to create a blank layer to put your own tiles on then see Tilemap.createBlankLayer.
*
* @method Phaser.Tilemap#createLayer
* @param {number|string} layer - The layer array index value, or if a string is given the layer name, within the map data that this TilemapLayer represents.
* @param {number} [width] - The rendered width of the layer, should never be wider than Game.width. If not given it will be set to Game.width.
* @param {number} [height] - The rendered height of the layer, should never be wider than Game.height. If not given it will be set to Game.height.
* @param {Phaser.Group} [group] - Optional Group to add the object to. If not specified it will be added to the World group.
* @return {Phaser.TilemapLayer} The TilemapLayer object. This is an extension of Phaser.Sprite and can be moved around the display list accordingly.
*/
createLayer: function (layer, width, height, group) {
// Add Buffer support for the left of the canvas
if (typeof width === 'undefined') { width = this.game.width; }
if (typeof height === 'undefined') { height = this.game.height; }
if (typeof group === 'undefined') { group = this.game.world; }
var index = layer;
if (typeof layer === 'string')
{
index = this.getLayerIndex(layer);
}
if (index === null || index > this.layers.length)
{
console.warn('Tilemap.createLayer: Invalid layer ID given: ' + index);
return;
}
return group.add(new Phaser.TilemapLayer(this.game, this, index, width, height));
},
/**
* Creates a new and empty layer on this Tilemap. By default TilemapLayers are fixed to the camera.
*
* @method Phaser.Tilemap#createBlankLayer
* @param {string} name - The name of this layer. Must be unique within the map.
* @param {number} width - The width of the layer in tiles.
* @param {number} height - The height of the layer in tiles.
* @param {number} tileWidth - The width of the tiles the layer uses for calculations.
* @param {number} tileHeight - The height of the tiles the layer uses for calculations.
* @param {Phaser.Group} [group] - Optional Group to add the layer to. If not specified it will be added to the World group.
* @return {Phaser.TilemapLayer} The TilemapLayer object. This is an extension of Phaser.Image and can be moved around the display list accordingly.
*/
createBlankLayer: function (name, width, height, tileWidth, tileHeight, group) {
if (typeof group === 'undefined') { group = this.game.world; }
if (this.getLayerIndex(name) !== null)
{
console.warn('Tilemap.createBlankLayer: Layer with matching name already exists');
return;
}
var layer = {
name: name,
x: 0,
y: 0,
width: width,
height: height,
widthInPixels: width * tileWidth,
heightInPixels: height * tileHeight,
alpha: 1,
visible: true,
properties: {},
indexes: [],
callbacks: [],
bodies: [],
data: null
};
var row;
var output = [];
for (var y = 0; y < height; y++)
{
row = [];
for (var x = 0; x < width; x++)
{
// row.push(null);
row.push(new Phaser.Tile(layer, -1, x, y, tileWidth, tileHeight));
}
output.push(row);
}
layer.data = output;
this.layers.push(layer);
this.currentLayer = this.layers.length - 1;
var w = layer.widthInPixels;
var h = layer.heightInPixels;
if (w > this.game.width)
{
w = this.game.width;
}
if (h > this.game.height)
{
h = this.game.height;
}
var output = new Phaser.TilemapLayer(this.game, this, this.layers.length - 1, w, h);
output.name = name;
return group.add(output);
},
/**
* Gets the layer index based on the layers name.
*
* @method Phaser.Tilemap#getIndex
* @protected
* @param {array} location - The local array to search.
* @param {string} name - The name of the array element to get.
* @return {number} The index of the element in the array, or null if not found.
*/
getIndex: function (location, name) {
for (var i = 0; i < location.length; i++)
{
if (location[i].name === name)
{
return i;
}
}
return null;
},
/**
* Gets the layer index based on its name.
*
* @method Phaser.Tilemap#getLayerIndex
* @param {string} name - The name of the layer to get.
* @return {number} The index of the layer in this tilemap, or null if not found.
*/
getLayerIndex: function (name) {
return this.getIndex(this.layers, name);
},
/**
* Gets the tileset index based on its name.
*
* @method Phaser.Tilemap#getTilesetIndex
* @param {string} name - The name of the tileset to get.
* @return {number} The index of the tileset in this tilemap, or null if not found.
*/
getTilesetIndex: function (name) {
return this.getIndex(this.tilesets, name);
},
/**
* Gets the image index based on its name.
*
* @method Phaser.Tilemap#getImageIndex
* @param {string} name - The name of the image to get.
* @return {number} The index of the image in this tilemap, or null if not found.
*/
getImageIndex: function (name) {
return this.getIndex(this.images, name);
},
/**
* Gets the object index based on its name.
*
* @method Phaser.Tilemap#getObjectIndex
* @param {string} name - The name of the object to get.
* @return {number} The index of the object in this tilemap, or null if not found.
*/
getObjectIndex: function (name) {
return this.getIndex(this.objects, name);
},
/**
* Sets a global collision callback for the given tile index within the layer. This will affect all tiles on this layer that have the same index.
* If a callback is already set for the tile index it will be replaced. Set the callback to null to remove it.
* If you want to set a callback for a tile at a specific location on the map then see setTileLocationCallback.
*
* @method Phaser.Tilemap#setTileIndexCallback
* @param {number|array} indexes - Either a single tile index, or an array of tile indexes to have a collision callback set for.
* @param {function} callback - The callback that will be invoked when the tile is collided with.
* @param {object} callbackContext - The context under which the callback is called.
* @param {number|string|Phaser.TilemapLayer} [layer] - The layer to operate on. If not given will default to this.currentLayer.
*/
setTileIndexCallback: function (indexes, callback, callbackContext, layer) {
layer = this.getLayer(layer);
if (typeof indexes === 'number')
{
// This may seem a bit wasteful, because it will cause empty array elements to be created, but the look-up cost is much
// less than having to iterate through the callbacks array hunting down tile indexes each frame, so I'll take the small memory hit.
this.layers[layer].callbacks[indexes] = { callback: callback, callbackContext: callbackContext };
}
else
{
for (var i = 0, len = indexes.length; i < len; i++)
{
this.layers[layer].callbacks[indexes[i]] = { callback: callback, callbackContext: callbackContext };
}
}
},
/**
* Sets a global collision callback for the given map location within the layer. This will affect all tiles on this layer found in the given area.
* If a callback is already set for the tile index it will be replaced. Set the callback to null to remove it.
* If you want to set a callback for a tile at a specific location on the map then see setTileLocationCallback.
*
* @method Phaser.Tilemap#setTileLocationCallback
* @param {number} x - X position of the top left of the area to copy (given in tiles, not pixels)
* @param {number} y - Y position of the top left of the area to copy (given in tiles, not pixels)
* @param {number} width - The width of the area to copy (given in tiles, not pixels)
* @param {number} height - The height of the area to copy (given in tiles, not pixels)
* @param {function} callback - The callback that will be invoked when the tile is collided with.
* @param {object} callbackContext - The context under which the callback is called.
* @param {number|string|Phaser.TilemapLayer} [layer] - The layer to operate on. If not given will default to this.currentLayer.
*/
setTileLocationCallback: function (x, y, width, height, callback, callbackContext, layer) {
layer = this.getLayer(layer);
this.copy(x, y, width, height, layer);
if (this._results.length < 2)
{
return;
}
for (var i = 1; i < this._results.length; i++)
{
this._results[i].setCollisionCallback(callback, callbackContext);
}
},
/**
* Sets collision the given tile or tiles. You can pass in either a single numeric index or an array of indexes: [ 2, 3, 15, 20].
* The `collides` parameter controls if collision will be enabled (true) or disabled (false).
*
* @method Phaser.Tilemap#setCollision
* @param {number|array} indexes - Either a single tile index, or an array of tile IDs to be checked for collision.
* @param {boolean} [collides=true] - If true it will enable collision. If false it will clear collision.
* @param {number|string|Phaser.TilemapLayer} [layer] - The layer to operate on. If not given will default to this.currentLayer.
* @param {boolean} [recalculate=true] - Recalculates the tile faces after the update.
*/
setCollision: function (indexes, collides, layer, recalculate) {
if (typeof collides === 'undefined') { collides = true; }
if (typeof recalculate === 'undefined') { recalculate = true; }
layer = this.getLayer(layer);
if (typeof indexes === 'number')
{
return this.setCollisionByIndex(indexes, collides, layer, true);
}
else
{
// Collide all of the IDs given in the indexes array
for (var i = 0, len = indexes.length; i < len; i++)
{
this.setCollisionByIndex(indexes[i], collides, layer, false);
}
if (recalculate)
{
// Now re-calculate interesting faces
this.calculateFaces(layer);
}
}
},
/**
* Sets collision on a range of tiles where the tile IDs increment sequentially.
* Calling this with a start value of 10 and a stop value of 14 would set collision for tiles 10, 11, 12, 13 and 14.
* The `collides` parameter controls if collision will be enabled (true) or disabled (false).
*
* @method Phaser.Tilemap#setCollisionBetween
* @param {number} start - The first index of the tile to be set for collision.
* @param {number} stop - The last index of the tile to be set for collision.
* @param {boolean} [collides=true] - If true it will enable collision. If false it will clear collision.
* @param {number|string|Phaser.TilemapLayer} [layer] - The layer to operate on. If not given will default to this.currentLayer.
* @param {boolean} [recalculate=true] - Recalculates the tile faces after the update.
*/
setCollisionBetween: function (start, stop, collides, layer, recalculate) {
if (typeof collides === 'undefined') { collides = true; }
if (typeof recalculate === 'undefined') { recalculate = true; }
layer = this.getLayer(layer);
if (start > stop)
{
return;
}
for (var index = start; index <= stop; index++)
{
this.setCollisionByIndex(index, collides, layer, false);
}
if (recalculate)
{
// Now re-calculate interesting faces
this.calculateFaces(layer);
}
},
/**
* Sets collision on all tiles in the given layer, except for the IDs of those in the given array.
* The `collides` parameter controls if collision will be enabled (true) or disabled (false).
*
* @method Phaser.Tilemap#setCollisionByExclusion
* @param {array} indexes - An array of the tile IDs to not be counted for collision.
* @param {boolean} [collides=true] - If true it will enable collision. If false it will clear collision.
* @param {number|string|Phaser.TilemapLayer} [layer] - The layer to operate on. If not given will default to this.currentLayer.
* @param {boolean} [recalculate=true] - Recalculates the tile faces after the update.
*/
setCollisionByExclusion: function (indexes, collides, layer, recalculate) {
if (typeof collides === 'undefined') { collides = true; }
if (typeof recalculate === 'undefined') { recalculate = true; }
layer = this.getLayer(layer);
// Collide everything, except the IDs given in the indexes array
for (var i = 0, len = this.tiles.length; i < len; i++)
{
if (indexes.indexOf(i) === -1)
{
this.setCollisionByIndex(i, collides, layer, false);
}
}
if (recalculate)
{
// Now re-calculate interesting faces
this.calculateFaces(layer);
}
},
/**
* Sets collision values on a tile in the set.
* You shouldn't usually call this method directly, instead use setCollision, setCollisionBetween or setCollisionByExclusion.
*
* @method Phaser.Tilemap#setCollisionByIndex
* @protected
* @param {number} index - The index of the tile on the layer.
* @param {boolean} [collides=true] - If true it will enable collision on the tile. If false it will clear collision values from the tile.
* @param {number} [layer] - The layer to operate on. If not given will default to this.currentLayer.
* @param {boolean} [recalculate=true] - Recalculates the tile faces after the update.
*/
setCollisionByIndex: function (index, collides, layer, recalculate) {
if (typeof collides === 'undefined') { collides = true; }
if (typeof layer === 'undefined') { layer = this.currentLayer; }
if (typeof recalculate === 'undefined') { recalculate = true; }
if (collides)
{
this.collideIndexes.push(index);
}
else
{
var i = this.collideIndexes.indexOf(index);
if (i > -1)
{
this.collideIndexes.splice(i, 1);
}
}
for (var y = 0; y < this.layers[layer].height; y++)
{
for (var x = 0; x < this.layers[layer].width; x++)
{
var tile = this.layers[layer].data[y][x];
if (tile && tile.index === index)
{
if (collides)
{
tile.setCollision(true, true, true, true);
}
else
{
tile.resetCollision();
}
tile.faceTop = collides;
tile.faceBottom = collides;
tile.faceLeft = collides;
tile.faceRight = collides;
}
}
}
if (recalculate)
{
// Now re-calculate interesting faces
this.calculateFaces(layer);
}
return layer;
},
/**
* Gets the TilemapLayer index as used in the setCollision calls.
*
* @method Phaser.Tilemap#getLayer
* @protected
* @param {number|string|Phaser.TilemapLayer} layer - The layer to operate on. If not given will default to this.currentLayer.
* @return {number} The TilemapLayer index.
*/
getLayer: function (layer) {
if (typeof layer === 'undefined')
{
layer = this.currentLayer;
}
else if (typeof layer === 'string')
{
layer = this.getLayerIndex(layer);
}
else if (layer instanceof Phaser.TilemapLayer)
{
layer = layer.index;
}
return layer;
},
/**
* Turn off/on the recalculation of faces for tile or collision updates.
* `setPreventRecalculate(true)` puts recalculation on hold while `setPreventRecalculate(false)` recalculates all the changed layers.
*
* @method Phaser.Tilemap#setPreventRecalculate
* @param {boolean} value - If true it will put the recalculation on hold.
*/
setPreventRecalculate: function (value) {
if (value === true && this.preventingRecalculate !== true)
{
this.preventingRecalculate = true;
this.needToRecalculate = {};
}
if (value === false && this.preventingRecalculate === true)
{
this.preventingRecalculate = false;
for (var i in this.needToRecalculate)
{
this.calculateFaces(i);
}
this.needToRecalculate = false;