11
22
3- PIXI . Tilemap = function ( texture )
3+ PIXI . Tilemap = function ( texture , map )
44{
55 PIXI . DisplayObjectContainer . call ( this ) ;
66
@@ -12,6 +12,37 @@ PIXI.Tilemap = function(texture)
1212 */
1313 this . texture = texture ;
1414
15+ /**
16+ * The tilemap object
17+ *
18+ * @property map
19+ * @type Object
20+ */
21+ this . map = map ;
22+
23+ // faster access to the tile dimensions
24+ this . tileWide = this . map . tilewidth ;
25+ this . tileHigh = this . map . tileheight ;
26+
27+ // precalculate the width of the source texture in entire tile units
28+ this . texTilesWide = Math . ceil ( this . texture . width / this . tileWide ) ;
29+ this . texTilesHigh = Math . ceil ( this . texture . height / this . tileHigh ) ;
30+
31+ // proportion of texture used by one tile (uv coordinate scales)
32+ this . sx = this . tileWide / this . texture . width ;
33+ this . sy = this . tileHigh / this . texture . height ;
34+
35+ // TODO: switch here to create DisplayObjectContainer at correct size for the render mode
36+ this . width = this . map . width * this . tileWide ;
37+ this . height = this . map . height * this . tileHigh ;
38+
39+ /**
40+ * Remember last tile drawn to avoid unnecessary set-up
41+ *
42+ * @type Integer
43+ */
44+ this . lastTile = - 1 ;
45+
1546 /**
1647 * Whether the Tilemap is dirty or not
1748 *
@@ -29,32 +60,35 @@ PIXI.Tilemap = function(texture)
2960 */
3061 this . blendMode = PIXI . blendModes . NORMAL ;
3162
32- // transform matrix created in updateTransform
33- this . transform = null ;
34-
3563 // create buffer with all data required by shader to draw this object
3664 this . buffer = new PIXI . Float32Array ( 16 ) ;
3765
38- // screen destination position
66+ /**
67+ * create buffer data for the webgl rendering of this tile
68+ * the buffer has parts of it overwritten for each tile
69+ * but other parts remain constant throughout
70+ */
71+
72+ // screen destination position of tile corners relative to 0,0 (constant)
3973 // l, b, 0,1
4074 // l, t, 4,5
4175 // r, b, 8,9
4276 // r, t, 12,13
4377 var l = 0 ;
44- var r = l + this . texture . width ;
78+ var r = l + this . tileWide ;
4579 var t = 0 ;
46- var b = t + this . texture . height ;
80+ var b = t + this . tileHigh ;
4781
4882 this . buffer [ 0 ] = this . buffer [ 4 ] = l ;
4983 this . buffer [ 1 ] = this . buffer [ 9 ] = b ;
5084 this . buffer [ 8 ] = this . buffer [ 12 ] = r ;
5185 this . buffer [ 5 ] = this . buffer [ 13 ] = t ;
5286
53- // texture source position
54- // x , b, 2,3
55- // x, y , 6,7
87+ // texture source position for the whole texture (uv coordinates adjusted for each tile)
88+ // l , b, 2,3
89+ // l, t , 6,7
5690 // r, b, 10,11
57- // r, y , 14,15
91+ // r, t , 14,15
5892 this . buffer [ 2 ] = this . buffer [ 6 ] = 0 ;
5993 this . buffer [ 3 ] = this . buffer [ 11 ] = 1 ;
6094 this . buffer [ 10 ] = this . buffer [ 14 ] = 1 ;
@@ -68,23 +102,32 @@ PIXI.Tilemap.prototype.constructor = PIXI.Tilemap;
68102PIXI . Tilemap . prototype . update = function ( ) { } ;
69103PIXI . Tilemap . prototype . postUpdate = function ( ) { } ;
70104
105+
71106PIXI . Tilemap . prototype . _renderWebGL = function ( renderSession )
72107{
73108 // if the sprite is not visible or the alpha is 0 then no need to render this element
74- if ( ! this . visible || this . alpha <= 0 ) return ;
109+ if ( ! this . visible || this . alpha <= 0 )
110+ {
111+ return ;
112+ }
75113
76114 renderSession . spriteBatch . stop ( ) ;
77115
78116 // init! init!
79- if ( ! this . _vertexBuffer ) this . _initWebGL ( renderSession ) ;
117+ if ( ! this . _vertexBuffer )
118+ {
119+ this . _initWebGL ( renderSession ) ;
120+ }
80121
81122 renderSession . shaderManager . setShader ( renderSession . shaderManager . tilemapShader ) ;
82123
83- this . _renderTilemap ( renderSession ) ;
124+ // TODO: switch to the appropriate rendering mode function here (rebuild all, part, edges, none)
125+ this . _renderWholeTilemap ( renderSession ) ;
84126
85127 renderSession . spriteBatch . start ( ) ;
86128} ;
87129
130+
88131PIXI . Tilemap . prototype . _initWebGL = function ( renderSession )
89132{
90133 var gl = renderSession . gl ;
@@ -121,6 +164,7 @@ PIXI.Tilemap.prototype.makeProjection = function(_width, _height)
121164} ;
122165
123166
167+ /*
124168PIXI.Tilemap.prototype.makeTransform = function(_x, _y, _angleInRadians, _scaleX, _scaleY)
125169{
126170 var c = Math.cos( _angleInRadians );
@@ -138,53 +182,110 @@ PIXI.Tilemap.prototype.makeTransform = function(_x, _y, _angleInRadians, _scaleX
138182 return m;
139183};
140184
141- var rot = 0.0 ;
142185
143- PIXI . Tilemap . prototype . _renderTilemap = function ( renderSession )
186+ /**
187+ * render the entire tilemap, one layer at a time, one tile at a time
188+ * using a fast webgl tile render
189+ *
190+ * @param {[type] } renderSession [description]
191+ */
192+ PIXI . Tilemap . prototype . _renderWholeTilemap = function ( renderSession )
144193{
145- var gl = renderSession . gl ;
146- var shader = renderSession . shaderManager . tilemapShader ;
147-
148- renderSession . blendModeManager . setBlendMode ( this . blendMode ) ;
149-
150- // set the uniforms and texture
151- gl . uniformMatrix3fv ( shader . uProjectionMatrix , false , this . makeProjection ( gl . drawingBufferWidth , gl . drawingBufferHeight ) ) ;
152- gl . uniform1i ( shader . uImageSampler , 0 ) ;
153- gl . activeTexture ( gl . TEXTURE0 ) ;
194+ var gl = renderSession . gl ;
195+ var shader = renderSession . shaderManager . tilemapShader ;
196+
197+ renderSession . blendModeManager . setBlendMode ( this . blendMode ) ;
198+
199+ // set the uniforms and texture
200+ gl . uniformMatrix3fv ( shader . uProjectionMatrix , false , this . makeProjection ( gl . drawingBufferWidth , gl . drawingBufferHeight ) ) ;
201+ gl . uniform1i ( shader . uImageSampler , 0 ) ;
202+ gl . activeTexture ( gl . TEXTURE0 ) ;
203+ gl . uniform2f ( shader . uTileSize , this . tileWide , this . tileHigh ) ;
204+
205+ // check if a texture is dirty..
206+ if ( this . texture . baseTexture . _dirty [ gl . id ] )
207+ {
208+ renderSession . renderer . updateTexture ( this . texture . baseTexture ) ;
209+ }
210+ else
211+ {
212+ // bind the current texture
213+ gl . bindTexture ( gl . TEXTURE_2D , this . texture . baseTexture . _glTextures [ gl . id ] ) ;
214+ }
215+
216+ // bind the source buffer
217+ gl . bindBuffer ( gl . ARRAY_BUFFER , this . positionBuffer ) ;
218+
219+ // draw all map layers
220+ for ( var l = 0 ; l < this . map . layers . length ; l ++ )
221+ {
222+ // draw an entire map layer
223+ this . _renderLayer ( l , renderSession ) ;
224+ }
225+ } ;
154226
155- // send the transform matrix to the vector shader
156- gl . uniformMatrix3fv ( shader . uModelMatrix , false , this . transform ) ;
157227
158- // check if a texture is dirty..
159- if ( this . texture . baseTexture . _dirty [ gl . id ] )
160- {
161- renderSession . renderer . updateTexture ( this . texture . baseTexture ) ;
162- }
163- else
228+ PIXI . Tilemap . prototype . _renderLayer = function ( _which , renderSession )
229+ {
230+ var gl = renderSession . gl ;
231+ var shader = renderSession . shaderManager . tilemapShader ;
232+
233+ var layer = this . map . layers [ _which ] ;
234+ if ( layer )
235+ {
236+ var wide = layer . width , high = layer . height ;
237+ for ( var y = 0 ; y < high ; y ++ )
164238 {
165- // bind the current texture
166- gl . bindTexture ( gl . TEXTURE_2D , this . texture . baseTexture . _glTextures [ gl . id ] ) ;
239+ for ( var x = 0 ; x < wide ; x ++ )
240+ {
241+ this . _renderTile ( gl , shader , x * this . tileWide , y * this . tileHigh , layer . data [ x + y * wide ] - 1 ) ;
242+ }
167243 }
168244
169- // bind the source buffer
170- gl . bindBuffer ( gl . ARRAY_BUFFER , this . positionBuffer ) ;
171- gl . bufferData ( gl . ARRAY_BUFFER , this . buffer , gl . STATIC_DRAW ) ;
172- gl . vertexAttribPointer ( shader . aPosition , 4 , gl . FLOAT , false , 0 , 0 ) ;
173- gl . enableVertexAttribArray ( shader . aPosition ) ;
174-
175- // draw the buffer: four vertices per quad, one quad
176- gl . drawArrays ( gl . TRIANGLE_STRIP , 0 , 4 ) ;
245+ }
177246} ;
178247
179248
180- PIXI . Tilemap . prototype . updateTransform = function ( )
249+ PIXI . Tilemap . prototype . _renderTile = function ( gl , shader , x , y , tile )
181250{
182- // x, y, rotation, scalex, scaley
183- this . transform = this . makeTransform ( 100 , 100 , 0 , 1 , 1 ) ;
251+ // if repeating same tile, skip almost everything...
252+ if ( tile != this . lastTile )
253+ {
254+ // tile coordinates in the source texture
255+ var tx = tile % this . texTilesWide ;
256+ var ty = Math . floor ( tile / this . texTilesWide ) ;
257+
258+ var l = tx * this . sx ;
259+ var r = l + this . sx ;
260+ var t = ty * this . sy ;
261+ var b = t + this . sy ;
262+ // texture source position for this tile (uv values)
263+ // l, b, 2,3
264+ // l, t, 6,7
265+ // r, b, 10,11
266+ // r, t, 14,15
267+ this . buffer [ 2 ] = this . buffer [ 6 ] = l ;
268+ this . buffer [ 3 ] = this . buffer [ 11 ] = b ;
269+ this . buffer [ 10 ] = this . buffer [ 14 ] = r ;
270+ this . buffer [ 7 ] = this . buffer [ 15 ] = t ;
184271
185- PIXI . DisplayObjectContainer . prototype . updateTransform . call ( this ) ;
272+ this . lastTile = tile ;
273+ }
274+
275+ // send the latest buffer
276+ gl . bufferData ( gl . ARRAY_BUFFER , this . buffer , gl . STATIC_DRAW ) ;
277+ gl . vertexAttribPointer ( shader . aPosition , 4 , gl . FLOAT , false , 0 , 0 ) ;
278+
279+ gl . uniform2f ( shader . uScreenPosition , x , y ) ;
280+ gl . drawArrays ( gl . TRIANGLE_STRIP , 0 , 4 ) ;
186281} ;
187282
283+ /*
284+ PIXI.Tilemap.prototype.updateTransform = function()
285+ {
286+ PIXI.DisplayObjectContainer.prototype.updateTransform.call( this );
287+ };
288+ */
188289
189290/**
190291 * When the texture is updated, this event will fire to update the scale and frame
@@ -200,7 +301,7 @@ PIXI.Tilemap.prototype.onTextureUpdate = function()
200301} ;
201302
202303/**
203- * Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account.
304+ * Returns the bounds of the map as a rectangle. The bounds calculation takes the worldTransform into account.
204305 *
205306 * @method getBounds
206307 * @param matrix {Matrix} the transformation matrix of the sprite
@@ -223,7 +324,12 @@ PIXI.Tilemap.prototype.getBounds = function(matrix)
223324 var minX = Infinity ;
224325 var minY = Infinity ;
225326
226- var vertices = this . vertices ;
327+ var vertices = [
328+ 0 , 0 ,
329+ this . map . width * this . tileWide , 0 ,
330+ this . map . width * this . tileWide , this . map . height * this . tileHigh ,
331+ 0 , this . map . height * this . tileHigh
332+ ] ;
227333 for ( var i = 0 , n = vertices . length ; i < n ; i += 2 )
228334 {
229335 var rawX = vertices [ i ] , rawY = vertices [ i + 1 ] ;
@@ -254,4 +360,5 @@ PIXI.Tilemap.prototype.getBounds = function(matrix)
254360 this . _currentBounds = bounds ;
255361
256362 return bounds ;
257- } ;
363+ } ;
364+
0 commit comments