@@ -278,6 +278,29 @@ var StaticTilemapLayer = new Class({
278278 */
279279 this . vertexCount = 0 ;
280280
281+ /**
282+ * The rendering (draw) order of the tiles in this layer.
283+ *
284+ * The default is 0 which is 'right-down', meaning it will draw the tiles starting from the top-left,
285+ * drawing to the right and then moving down to the next row.
286+ *
287+ * The draw orders are:
288+ *
289+ * 0 = right-down
290+ * 1 = left-down
291+ * 2 = right-up
292+ * 3 = left-up
293+ *
294+ * This can be changed via the `setRenderOrder` method.
295+ *
296+ * @name Phaser.Tilemaps.StaticTilemapLayer#_renderOrder
297+ * @type {integer }
298+ * @default 0
299+ * @private
300+ * @since 3.12.0
301+ */
302+ this . _renderOrder = 0 ;
303+
281304 this . setAlpha ( this . layer . alpha ) ;
282305 this . setPosition ( x , y ) ;
283306 this . setOrigin ( ) ;
@@ -295,6 +318,49 @@ var StaticTilemapLayer = new Class({
295318 }
296319 } ,
297320
321+ /**
322+ * Sets the rendering (draw) order of the tiles in this layer.
323+ *
324+ * The default is 'right-down', meaning it will order the tiles starting from the top-left,
325+ * drawing to the right and then moving down to the next row.
326+ *
327+ * The draw orders are:
328+ *
329+ * 0 = right-down
330+ * 1 = left-down
331+ * 2 = right-up
332+ * 3 = left-up
333+ *
334+ * Setting the render order does not change the tiles or how they are stored in the layer,
335+ * it purely impacts the order in which they are rendered.
336+ *
337+ * You can provide either an integer (0 to 3), or the string version of the order.
338+ *
339+ * @method Phaser.Tilemaps.StaticTilemapLayer#setRenderOrder
340+ * @since 3.12.0
341+ *
342+ * @param {(integer|string) } renderOrder - The render (draw) order value. Either an integer between 0 and 3, or a string: 'right-down', 'left-down', 'right-up' or 'left-up'.
343+ *
344+ * @return {this } This Tilemap Layer object.
345+ */
346+ setRenderOrder : function ( renderOrder )
347+ {
348+ var orders = [ 'right-down' , 'left-down' , 'right-up' , 'left-up' ] ;
349+
350+ if ( typeof renderOrder === 'string' )
351+ {
352+ renderOrder = orders . indexOf ( renderOrder ) ;
353+ }
354+
355+ if ( renderOrder >= 0 && renderOrder < 4 )
356+ {
357+ this . _renderOrder = renderOrder ;
358+ this . dirty = true ;
359+ }
360+
361+ return this ;
362+ } ,
363+
298364 /**
299365 * Upload the tile data to a VBO.
300366 *
@@ -323,129 +389,103 @@ var StaticTilemapLayer = new Class({
323389 var tile ;
324390 var row ;
325391 var col ;
326- var texCoords ;
392+ var renderOrder = this . _renderOrder ;
327393
328394 var vertexBuffer = this . vertexBuffer ;
329395 var bufferData = this . bufferData ;
330396 var vOffset = - 1 ;
331- var vertexCount = 0 ;
332- var tintEffect = false ;
333397 var bufferSize = ( mapWidth * mapHeight ) * pipeline . vertexSize * 6 ;
398+
399+ this . vertexCount = 0 ;
334400
335401 if ( bufferData === null )
336402 {
337403 bufferData = new ArrayBuffer ( bufferSize ) ;
404+
338405 this . bufferData = bufferData ;
406+
339407 this . vertexViewF32 = new Float32Array ( bufferData ) ;
340408 this . vertexViewU32 = new Uint32Array ( bufferData ) ;
341409 }
342410
343- var vertexViewF32 = this . vertexViewF32 ;
344- var vertexViewU32 = this . vertexViewU32 ;
345-
346- for ( row = 0 ; row < mapHeight ; row ++ )
411+ if ( renderOrder === 0 )
347412 {
348- for ( col = 0 ; col < mapWidth ; col ++ )
413+ // right-down
414+
415+ for ( row = 0 ; row < mapHeight ; row ++ )
349416 {
350- tile = mapData [ row ] [ col ] ;
351-
352- if ( ! tile || tile . index === - 1 || ! tile . visible )
417+ for ( col = 0 ; col < mapWidth ; col ++ )
353418 {
354- continue ;
355- }
356-
357- var tx = tile . pixelX ;
358- var ty = tile . pixelY ;
359- var txw = tx + tile . width ;
360- var tyh = ty + tile . height ;
361-
362- texCoords = tileset . getTileTextureCoordinates ( tile . index ) ;
419+ tile = mapData [ row ] [ col ] ;
420+
421+ if ( ! tile || tile . index === - 1 || ! tile . visible )
422+ {
423+ continue ;
424+ }
363425
364- if ( ! texCoords )
365- {
366- continue ;
426+ vOffset = this . batchTile ( vOffset , tile , tileset , width , height , camera ) ;
367427 }
368-
369- var u0 = texCoords . x / width ;
370- var v0 = texCoords . y / height ;
371- var u1 = ( texCoords . x + tile . width ) / width ;
372- var v1 = ( texCoords . y + tile . height ) / height ;
373-
374- var tint = Utils . getTintAppendFloatAlpha ( 0xffffff , camera . alpha * this . alpha * tile . alpha ) ;
375-
376- var tx0 = tx ;
377- var ty0 = ty ;
378- var tx1 = tx ;
379- var ty1 = tyh ;
380- var tx2 = txw ;
381- var ty2 = tyh ;
382- var tx3 = txw ;
383- var ty3 = ty ;
384-
385- if ( camera . roundPixels )
428+ }
429+ }
430+ else if ( renderOrder === 1 )
431+ {
432+ // left-down
433+
434+ for ( row = 0 ; row < mapHeight ; row ++ )
435+ {
436+ for ( col = mapWidth - 1 ; col >= 0 ; col -- )
386437 {
387- tx0 |= 0 ;
388- ty0 |= 0 ;
389-
390- tx1 |= 0 ;
391- ty1 |= 0 ;
392-
393- tx2 |= 0 ;
394- ty2 |= 0 ;
395-
396- tx3 |= 0 ;
397- ty3 |= 0 ;
398- }
399-
400- vertexViewF32 [ ++ vOffset ] = tx0 ;
401- vertexViewF32 [ ++ vOffset ] = ty0 ;
402- vertexViewF32 [ ++ vOffset ] = u0 ;
403- vertexViewF32 [ ++ vOffset ] = v0 ;
404- vertexViewF32 [ ++ vOffset ] = tintEffect ;
405- vertexViewU32 [ ++ vOffset ] = tint ;
406-
407- vertexViewF32 [ ++ vOffset ] = tx1 ;
408- vertexViewF32 [ ++ vOffset ] = ty1 ;
409- vertexViewF32 [ ++ vOffset ] = u0 ;
410- vertexViewF32 [ ++ vOffset ] = v1 ;
411- vertexViewF32 [ ++ vOffset ] = tintEffect ;
412- vertexViewU32 [ ++ vOffset ] = tint ;
438+ tile = mapData [ row ] [ col ] ;
439+
440+ if ( ! tile || tile . index === - 1 || ! tile . visible )
441+ {
442+ continue ;
443+ }
413444
414- vertexViewF32 [ ++ vOffset ] = tx2 ;
415- vertexViewF32 [ ++ vOffset ] = ty2 ;
416- vertexViewF32 [ ++ vOffset ] = u1 ;
417- vertexViewF32 [ ++ vOffset ] = v1 ;
418- vertexViewF32 [ ++ vOffset ] = tintEffect ;
419- vertexViewU32 [ ++ vOffset ] = tint ;
420-
421- vertexViewF32 [ ++ vOffset ] = tx0 ;
422- vertexViewF32 [ ++ vOffset ] = ty0 ;
423- vertexViewF32 [ ++ vOffset ] = u0 ;
424- vertexViewF32 [ ++ vOffset ] = v0 ;
425- vertexViewF32 [ ++ vOffset ] = tintEffect ;
426- vertexViewU32 [ ++ vOffset ] = tint ;
427-
428- vertexViewF32 [ ++ vOffset ] = tx2 ;
429- vertexViewF32 [ ++ vOffset ] = ty2 ;
430- vertexViewF32 [ ++ vOffset ] = u1 ;
431- vertexViewF32 [ ++ vOffset ] = v1 ;
432- vertexViewF32 [ ++ vOffset ] = tintEffect ;
433- vertexViewU32 [ ++ vOffset ] = tint ;
445+ vOffset = this . batchTile ( vOffset , tile , tileset , width , height , camera ) ;
446+ }
447+ }
448+ }
449+ else if ( renderOrder === 2 )
450+ {
451+ // right-up
452+
453+ for ( row = mapHeight - 1 ; row >= 0 ; row -- )
454+ {
455+ for ( col = 0 ; col < mapWidth ; col ++ )
456+ {
457+ tile = mapData [ row ] [ col ] ;
458+
459+ if ( ! tile || tile . index === - 1 || ! tile . visible )
460+ {
461+ continue ;
462+ }
434463
435- vertexViewF32 [ ++ vOffset ] = tx3 ;
436- vertexViewF32 [ ++ vOffset ] = ty3 ;
437- vertexViewF32 [ ++ vOffset ] = u1 ;
438- vertexViewF32 [ ++ vOffset ] = v0 ;
439- vertexViewF32 [ ++ vOffset ] = tintEffect ;
440- vertexViewU32 [ ++ vOffset ] = tint ;
464+ vOffset = this . batchTile ( vOffset , tile , tileset , width , height , camera ) ;
465+ }
466+ }
467+ }
468+ else if ( renderOrder === 3 )
469+ {
470+ // left-up
471+
472+ for ( row = mapHeight - 1 ; row >= 0 ; row -- )
473+ {
474+ for ( col = mapWidth - 1 ; col >= 0 ; col -- )
475+ {
476+ tile = mapData [ row ] [ col ] ;
477+
478+ if ( ! tile || tile . index === - 1 || ! tile . visible )
479+ {
480+ continue ;
481+ }
441482
442- vertexCount += 6 ;
483+ vOffset = this . batchTile ( vOffset , tile , tileset , width , height , camera ) ;
484+ }
443485 }
444486 }
445-
487+
446488 this . dirty = false ;
447-
448- this . vertexCount = vertexCount ;
449489
450490 if ( vertexBuffer === null )
451491 {
@@ -469,6 +509,117 @@ var StaticTilemapLayer = new Class({
469509 return this ;
470510 } ,
471511
512+ /**
513+ * Add a single tile into the batch.
514+ *
515+ * @method Phaser.Tilemaps.StaticTilemapLayer#batchTile
516+ * @private
517+ * @since 3.12.0
518+ *
519+ * @param {integer } vOffset - The vertex offset.
520+ * @param {any } tile - The tile being rendered.
521+ * @param {any } tileset - The tileset being used for rendering.
522+ * @param {integer } width - The width of the layer.
523+ * @param {integer } height - The height of the layer.
524+ * @param {Phaser.Cameras.Scene2D.Camera } camera - The camera the layer is being rendered with.
525+ *
526+ * @return {integer } The new vOffset value.
527+ */
528+ batchTile : function ( vOffset , tile , tileset , width , height , camera )
529+ {
530+ var tx = tile . pixelX ;
531+ var ty = tile . pixelY ;
532+ var txw = tx + tile . width ;
533+ var tyh = ty + tile . height ;
534+
535+ var texCoords = tileset . getTileTextureCoordinates ( tile . index ) ;
536+
537+ if ( ! texCoords )
538+ {
539+ return ;
540+ }
541+
542+ var u0 = texCoords . x / width ;
543+ var v0 = texCoords . y / height ;
544+ var u1 = ( texCoords . x + tile . width ) / width ;
545+ var v1 = ( texCoords . y + tile . height ) / height ;
546+
547+ var tint = Utils . getTintAppendFloatAlpha ( 0xffffff , camera . alpha * this . alpha * tile . alpha ) ;
548+
549+ var tx0 = tx ;
550+ var ty0 = ty ;
551+ var tx1 = tx ;
552+ var ty1 = tyh ;
553+ var tx2 = txw ;
554+ var ty2 = tyh ;
555+ var tx3 = txw ;
556+ var ty3 = ty ;
557+
558+ if ( camera . roundPixels )
559+ {
560+ tx0 |= 0 ;
561+ ty0 |= 0 ;
562+
563+ tx1 |= 0 ;
564+ ty1 |= 0 ;
565+
566+ tx2 |= 0 ;
567+ ty2 |= 0 ;
568+
569+ tx3 |= 0 ;
570+ ty3 |= 0 ;
571+ }
572+
573+ var vertexViewF32 = this . vertexViewF32 ;
574+ var vertexViewU32 = this . vertexViewU32 ;
575+
576+ vertexViewF32 [ ++ vOffset ] = tx0 ;
577+ vertexViewF32 [ ++ vOffset ] = ty0 ;
578+ vertexViewF32 [ ++ vOffset ] = u0 ;
579+ vertexViewF32 [ ++ vOffset ] = v0 ;
580+ vertexViewF32 [ ++ vOffset ] = 0 ;
581+ vertexViewU32 [ ++ vOffset ] = tint ;
582+
583+ vertexViewF32 [ ++ vOffset ] = tx1 ;
584+ vertexViewF32 [ ++ vOffset ] = ty1 ;
585+ vertexViewF32 [ ++ vOffset ] = u0 ;
586+ vertexViewF32 [ ++ vOffset ] = v1 ;
587+ vertexViewF32 [ ++ vOffset ] = 0 ;
588+ vertexViewU32 [ ++ vOffset ] = tint ;
589+
590+ vertexViewF32 [ ++ vOffset ] = tx2 ;
591+ vertexViewF32 [ ++ vOffset ] = ty2 ;
592+ vertexViewF32 [ ++ vOffset ] = u1 ;
593+ vertexViewF32 [ ++ vOffset ] = v1 ;
594+ vertexViewF32 [ ++ vOffset ] = 0 ;
595+ vertexViewU32 [ ++ vOffset ] = tint ;
596+
597+ vertexViewF32 [ ++ vOffset ] = tx0 ;
598+ vertexViewF32 [ ++ vOffset ] = ty0 ;
599+ vertexViewF32 [ ++ vOffset ] = u0 ;
600+ vertexViewF32 [ ++ vOffset ] = v0 ;
601+ vertexViewF32 [ ++ vOffset ] = 0 ;
602+ vertexViewU32 [ ++ vOffset ] = tint ;
603+
604+ vertexViewF32 [ ++ vOffset ] = tx2 ;
605+ vertexViewF32 [ ++ vOffset ] = ty2 ;
606+ vertexViewF32 [ ++ vOffset ] = u1 ;
607+ vertexViewF32 [ ++ vOffset ] = v1 ;
608+ vertexViewF32 [ ++ vOffset ] = 0 ;
609+ vertexViewU32 [ ++ vOffset ] = tint ;
610+
611+ vertexViewF32 [ ++ vOffset ] = tx3 ;
612+ vertexViewF32 [ ++ vOffset ] = ty3 ;
613+ vertexViewF32 [ ++ vOffset ] = u1 ;
614+ vertexViewF32 [ ++ vOffset ] = v0 ;
615+ vertexViewF32 [ ++ vOffset ] = 0 ;
616+ vertexViewU32 [ ++ vOffset ] = tint ;
617+
618+ this . vertexCount += 6 ;
619+
620+ return vOffset ;
621+ } ,
622+
472623 /**
473624 * Calculates interesting faces at the given tile coordinates of the specified layer. Interesting
474625 * faces are used internally for optimizing collisions against tiles. This method is mostly used
0 commit comments