Skip to content

Commit eb77949

Browse files
committed
Strip down PIXI.Tilemap to remove all unused code.
Add very simple tilemap render function to draw every layer, every tile, for the tiles provided. Link to the TilemapShader and get the whole thing working.
1 parent 9deb07c commit eb77949

1 file changed

Lines changed: 157 additions & 50 deletions

File tree

src/pixi/extras/Tilemap.js

Lines changed: 157 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
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;
68102
PIXI.Tilemap.prototype.update = function() {};
69103
PIXI.Tilemap.prototype.postUpdate = function() {};
70104

105+
71106
PIXI.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+
88131
PIXI.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+
/*
124168
PIXI.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

Comments
 (0)