From 0d38e232e6bb9b12b4c9454d998c8f323ba7f49f Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 3 Nov 2017 16:52:57 +0000 Subject: [PATCH] Both Static and Dynamic Tilemaps support the new property `skipIndexZero` which allows them to skip over index 0 tiles. Works in both canvas and webgl. Fix #3052 --- v3/src/gameobjects/tilemap/dynamic/Tile.js | 13 +- v3/src/gameobjects/tilemap/dynamic/Tilemap.js | 16 +- .../tilemap/dynamic/TilemapCanvasRenderer.js | 21 ++- .../tilemap/dynamic/TilemapWebGLRenderer.js | 6 + .../tilemap/static/StaticTilemap.js | 148 +++++++++++------- .../static/StaticTilemapCanvasRenderer.js | 2 +- .../static/StaticTilemapWebGLRenderer.js | 1 + 7 files changed, 136 insertions(+), 71 deletions(-) diff --git a/v3/src/gameobjects/tilemap/dynamic/Tile.js b/v3/src/gameobjects/tilemap/dynamic/Tile.js index 2126dfaf5..1d827b43c 100644 --- a/v3/src/gameobjects/tilemap/dynamic/Tile.js +++ b/v3/src/gameobjects/tilemap/dynamic/Tile.js @@ -4,36 +4,47 @@ function Tile (properties) this.id = properties.id; this.x = properties.x; this.y = properties.y; + this.width = properties.width; this.height = properties.height; + this.frameX = properties.frameX; this.frameY = properties.frameY; this.frameWidth = properties.frameWidth; this.frameHeight = properties.frameHeight; + this.alpha = 1.0; this.tint = 0xFFFFFF; this.visible = true; + this.textureWidth = properties.textureWidth; this.textureHeight = properties.textureHeight; + this.border = properties.border; - this.center = properties.center; + this.center = properties.center; } Tile.prototype.setId = function (id) { var tileId = this.id = id; + var tileWidth = this.width; var tileHeight = this.height; + var setWidth = this.textureWidth / tileWidth; + var tileWidthBorder = (tileWidth + this.border * 2); var tileHeightBorder = (tileHeight + this.border * 2); + var halfTileWidth = tileWidthBorder * 0.5; var halfTileHeight = tileHeightBorder * 0.5; + if (!this.center) { halfTileWidth = 0; halfTileHeight = 0; } + var rectx = (((tileId % setWidth)|0) * tileWidthBorder) + halfTileWidth; var recty = (((tileId / setWidth)|0) * tileHeightBorder) + halfTileHeight; diff --git a/v3/src/gameobjects/tilemap/dynamic/Tilemap.js b/v3/src/gameobjects/tilemap/dynamic/Tilemap.js index dce0de180..ab635d128 100644 --- a/v3/src/gameobjects/tilemap/dynamic/Tilemap.js +++ b/v3/src/gameobjects/tilemap/dynamic/Tilemap.js @@ -31,18 +31,24 @@ var Tilemap = new Class({ GameObject.call(this, scene, 'Tilemap'); this.mapData = (mapData !== null) ? new Uint32Array(mapData) : new Uint32Array(mapWidth * mapHeight); - this.tileWidth = tileWidth; - this.tileHeight = tileHeight; this.mapWidth = mapWidth; this.mapHeight = mapHeight; + + this.tileWidth = tileWidth; + this.tileHeight = tileHeight; + this.tileArray = []; this.culledTiles = []; this.tileBorder = tileBorder; + this.setTexture(texture, frame); this.setPosition(x, y); this.setSizeToFrame(); this.setOrigin(); this.setSize(tileWidth * mapWidth, tileHeight * mapHeight); + + this.skipIndexZero = false; + this.buildTilemap(!!scene.sys.game.renderer.gl); }, @@ -61,15 +67,19 @@ var Tilemap = new Class({ var tileArray = this.tileArray; var mapData = this.mapData; var border = this.tileBorder; + var tileWidth = this.tileWidth; var tileHeight = this.tileHeight; var tileWidthBorder = tileWidth + border * 2; var tileHeightBorder = tileHeight + border * 2; + var width = this.texture.source[0].width; var height = this.texture.source[0].height; + var mapWidth = this.mapWidth; var mapHeight = this.mapHeight; var setWidth = width / tileWidth; + var tileWidthBorderHalf = tileWidthBorder * 0.5; var tileHeightBorderHalf = tileHeightBorder * 0.5; @@ -157,7 +167,7 @@ var Tilemap = new Class({ // frameX // frameY // id - // index = the tile in the tilset to render + // index = the tile in the tileset to render // textureWidth = tileset texture size // textureHeight // tint diff --git a/v3/src/gameobjects/tilemap/dynamic/TilemapCanvasRenderer.js b/v3/src/gameobjects/tilemap/dynamic/TilemapCanvasRenderer.js index 943cc59f6..bb9c86b82 100644 --- a/v3/src/gameobjects/tilemap/dynamic/TilemapCanvasRenderer.js +++ b/v3/src/gameobjects/tilemap/dynamic/TilemapCanvasRenderer.js @@ -12,9 +12,11 @@ var TilemapCanvasRenderer = function (renderer, gameObject, interpolationPercent var tiles = gameObject.culledTiles; var tileCount = tiles.length; var image = gameObject.frame.source.image; - var scrollFactorX = gameObject.scrollFactorX; - var scrollFactorY = gameObject.scrollFactorY; - var alpha = gameObject.alpha; + + // var scrollFactorX = gameObject.scrollFactorX; + // var scrollFactorY = gameObject.scrollFactorY; + // var alpha = gameObject.alpha; + var tx = gameObject.x - camera.scrollX * gameObject.scrollFactorX; var ty = gameObject.y - camera.scrollY * gameObject.scrollFactorY; var ctx = renderer.gameContext; @@ -29,11 +31,16 @@ var TilemapCanvasRenderer = function (renderer, gameObject, interpolationPercent { var tile = tiles[index]; + if (tile.id <= 0 && gameObject.skipIndexZero) + { + continue; + } + ctx.drawImage( - image, - tile.frameX, tile.frameY, - tile.frameWidth, tile.frameHeight, - tile.x, tile.y, + image, + tile.frameX, tile.frameY, + tile.frameWidth, tile.frameHeight, + tile.x, tile.y, tile.frameWidth, tile.frameHeight ); } diff --git a/v3/src/gameobjects/tilemap/dynamic/TilemapWebGLRenderer.js b/v3/src/gameobjects/tilemap/dynamic/TilemapWebGLRenderer.js index 10a038aee..fdc7acf02 100644 --- a/v3/src/gameobjects/tilemap/dynamic/TilemapWebGLRenderer.js +++ b/v3/src/gameobjects/tilemap/dynamic/TilemapWebGLRenderer.js @@ -25,6 +25,12 @@ var TilemapWebGLRenderer = function (renderer, gameObject, interpolationPercenta for (var index = 0; index < length; ++index) { var tile = renderTiles[index]; + + if (tile.id <= 0 && gameObject.skipIndexZero) + { + continue; + } + batch.addTileTextureRect( texture, x + tile.x, y + tile.y, tile.width, tile.height, alpha * tile.alpha, tile.tint, diff --git a/v3/src/gameobjects/tilemap/static/StaticTilemap.js b/v3/src/gameobjects/tilemap/static/StaticTilemap.js index 8951a89ef..4d7ce2c4f 100644 --- a/v3/src/gameobjects/tilemap/static/StaticTilemap.js +++ b/v3/src/gameobjects/tilemap/static/StaticTilemap.js @@ -1,8 +1,8 @@ var Class = require('../../../utils/Class'); -var GameObject = require('../../GameObject'); var Components = require('../../components'); -var StaticTilemapRender = require('./StaticTilemapRender'); var CONST = require('../../../renderer/webgl/renderers/tilemaprenderer/const'); +var GameObject = require('../../GameObject'); +var StaticTilemapRender = require('./StaticTilemapRender'); var StaticTilemap = new Class({ @@ -35,85 +35,112 @@ var StaticTilemap = new Class({ this.tilemapRenderer = scene.sys.game.renderer.tilemapRenderer ? scene.sys.game.renderer.tilemapRenderer : null; this.resourceManager = this.gl ? scene.sys.game.renderer.resourceManager : null; this.bufferData = null; + this.mapData = mapData; - this.tileWidth = tileWidth; - this.tileHeight = tileHeight; this.mapWidth = mapWidth; this.mapHeight = mapHeight; + + this.tileWidth = tileWidth; + this.tileHeight = tileHeight; + this.dirty = true; this.vertexCount = 0; this.cullStart = 0; this.cullEnd = 0; + this.tileBorder = tileBorder; + this.setTexture(texture, frame); this.setPosition(x, y); this.setSizeToFrame(); this.setOrigin(); this.setSize(tileWidth * mapWidth, tileHeight * mapHeight); - - var _this = this; - scene.sys.game.renderer.addContextRestoredCallback(function (renderer) { - _this.tileTexture = null; - _this.dirty = true; - _this.vbo = null; - _this.gl = renderer.gl; - _this.tilemapRenderer = renderer.tilemapRenderer; - }); + + this.skipIndexZero = false; + + scene.sys.game.renderer.addContextRestoredCallback(this.contextRestore.bind(this)); }, - upload: function (camera) + contextRestore: function (renderer) { + this.tileTexture = null; + this.dirty = true; + this.vbo = null; + this.gl = renderer.gl; + this.tilemapRenderer = renderer.tilemapRenderer; + }, + + upload: function (camera) + { + var mapWidth = this.mapWidth; + var mapHeight = this.mapHeight; + var border = this.tileBorder; + var tileWidth = this.tileWidth; + var tileHeight = this.tileHeight; + var tileWidthBorder = tileWidth + border * 2; + var tileHeightBorder = tileHeight + border * 2; + var width = this.texture.source[0].width; + var height = this.texture.source[0].height; + var setWidth = width / tileWidth; + var mapData = this.mapData; + + var x; + var y; + if (this.gl) { if (this.dirty) { var gl = this.gl; var vbo = this.vbo; - var mapWidth = this.mapWidth; - var mapHeight = this.mapHeight; - var border = this.tileBorder; - var tileWidth = this.tileWidth; - var tileHeight = this.tileHeight; - var tileWidthBorder = tileWidth + border * 2; - var tileHeightBorder = tileHeight + border * 2; var bufferData = this.bufferData; - var bufferF32, bufferU32; + var bufferF32; var voffset = 0; var vertexCount = 0; - var width = this.texture.source[0].width; - var height = this.texture.source[0].height; - var setWidth = width / tileWidth; - var mapData = this.mapData; if (this.vbo === null) { vbo = this.resourceManager.createBuffer(gl.ARRAY_BUFFER, (4 * 6 * (mapWidth * mapHeight)) * 4, gl.STATIC_DRAW); + vbo.addAttribute(this.tilemapRenderer.shader.getAttribLocation('a_position'), 2, gl.FLOAT, false, CONST.VERTEX_SIZE, 0); vbo.addAttribute(this.tilemapRenderer.shader.getAttribLocation('a_tex_coord'), 2, gl.FLOAT, false, CONST.VERTEX_SIZE, 8); + bufferData = this.bufferData = new ArrayBuffer((4 * 6 * (mapWidth * mapHeight)) * 4); + this.vbo = vbo; + vbo.bind(); } bufferF32 = new Float32Array(bufferData); - for (var y = 0; y < mapHeight; ++y) + for (y = 0; y < mapHeight; ++y) { - for (var x = 0; x < mapWidth; ++x) + for (x = 0; x < mapWidth; ++x) { var tileId = mapData[y * mapWidth + x]; + + if (tileId <= 0 && this.skipIndexZero) + { + continue; + } + var halfTileWidth = (tileWidthBorder) * 0.5; var halfTileHeight = (tileHeightBorder) * 0.5; + var rectx = (((tileId % setWidth)|0) * tileWidthBorder) + halfTileWidth; var recty = (((tileId / setWidth)|0) * tileHeightBorder) + halfTileHeight; + var tx = x * tileWidth; var ty = y * tileHeight; var txw = tx + tileWidth; var tyh = ty + tileHeight; + var u0 = (rectx - (halfTileWidth - 0.5)) / width; var v0 = (recty - (halfTileHeight - 0.5)) / height; var u1 = (rectx + (halfTileWidth - 0.5)) / width; var v1 = (recty + (halfTileHeight - 0.5)) / height; + var tx0 = tx; var ty0 = ty; var tx1 = tx; @@ -157,20 +184,26 @@ var StaticTilemap = new Class({ vertexCount += 6; } } + this.vertexCount = vertexCount; + vbo.updateResource(bufferData, 0); this.dirty = false; } - this.tilemapRenderer.shader.setConstantFloat2(this.tilemapRenderer.scrollLocation, camera.scrollX, camera.scrollY); - this.tilemapRenderer.shader.setConstantFloat2(this.tilemapRenderer.scrollFactorLocation, this.scrollFactorX, this.scrollFactorY); - this.tilemapRenderer.shader.setConstantFloat2(this.tilemapRenderer.tilemapPositionLocation, this.x, this.y); + + var renderer = this.tilemapRenderer; + + renderer.shader.setConstantFloat2(renderer.scrollLocation, camera.scrollX, camera.scrollY); + renderer.shader.setConstantFloat2(renderer.scrollFactorLocation, this.scrollFactorX, this.scrollFactorY); + renderer.shader.setConstantFloat2(renderer.tilemapPositionLocation, this.x, this.y); + var cmat = camera.matrix.matrix; - this.tilemapRenderer.shader.setConstantMatrix3x3( - this.tilemapRenderer.cameraTransformLocation, + renderer.shader.setConstantMatrix3x3( + renderer.cameraTransformLocation, [ - cmat[0], cmat[1], 0.0, + cmat[0], cmat[1], 0.0, cmat[2], cmat[3], 0.0, cmat[4], cmat[5], 1.0 ] @@ -178,33 +211,25 @@ var StaticTilemap = new Class({ } else if (this.dirty && !this.gl) { - var mapWidth = this.mapWidth; - var mapHeight = this.mapHeight; - var border = this.tileBorder; - var tileWidth = this.tileWidth; - var tileHeight = this.tileHeight; - var tileWidthBorder = tileWidth + border * 2; - var tileHeightBorder = tileHeight + border * 2; - var width = this.texture.source[0].width; - var height = this.texture.source[0].height; - var setWidth = width / tileWidth; - var mapData = this.mapData; - this.tiles = []; - for (var y = 0; y < mapHeight; ++y) + for (y = 0; y < mapHeight; ++y) { - for (var x = 0; x < mapWidth; ++x) + for (x = 0; x < mapWidth; ++x) { - var tileId = mapData[y * mapWidth + x]; - var frameX = (((tileId % setWidth)|0) * tileWidthBorder); - var frameY = (((tileId / setWidth)|0) * tileHeightBorder); - var tx = x * tileWidth; - var ty = y * tileHeight; + var id = mapData[y * mapWidth + x]; + + if (id <= 0 && this.skipIndexZero) + { + continue; + } + + var frameX = (((id % setWidth) | 0) * tileWidthBorder); + var frameY = (((id / setWidth) | 0) * tileHeightBorder); this.tiles.push({ - x: tx, - y: ty, + x: x * tileWidth, + y: y * tileHeight, frameX: frameX, frameY: frameY }); @@ -224,6 +249,7 @@ var StaticTilemap = new Class({ getVisibleTileCount: function (camera) { this.cull(camera); + return (this.cullEnd - this.cullStart) / 6; }, @@ -231,8 +257,10 @@ var StaticTilemap = new Class({ { this.cullStart = 0; this.cullEnd = 0; + var tileWidth = this.tileWidth; var tileHeight = this.tileHeight; + var pixelX = this.x - (camera.scrollX * this.scrollFactorX); var pixelY = this.y - (camera.scrollY * this.scrollFactorY); var pixelWidth = this.mapWidth * tileWidth; @@ -245,13 +273,15 @@ var StaticTilemap = new Class({ { var interX = Math.max(pixelX, camera.x + -(tileWidth * 2)); var interY = Math.max(pixelY, camera.y + -(tileHeight * 2)); + var interWidth = Math.min(pixelX + pixelWidth, camera.x + camera.width + (tileWidth * 2)) - interX; var interHeight = Math.min(pixelY + pixelHeight, camera.y + camera.height + (tileHeight * 2)) - interY; - interX = ((interX + (camera.scrollX * this.scrollFactorX)) / tileWidth)|0; - interY = ((interY + (camera.scrollY * this.scrollFactorY)) / tileHeight)|0; - interWidth = (interWidth / tileWidth)|0; - interHeight = (interHeight / tileHeight)|0; + interX = ((interX + (camera.scrollX * this.scrollFactorX)) / tileWidth) | 0; + interY = ((interY + (camera.scrollY * this.scrollFactorY)) / tileHeight) | 0; + + interWidth = (interWidth / tileWidth) | 0; + interHeight = (interHeight / tileHeight) | 0; this.cullStart = (interY * this.mapWidth + interX) * 6; this.cullEnd = ((interY + interHeight) * this.mapWidth + interX) * 6; diff --git a/v3/src/gameobjects/tilemap/static/StaticTilemapCanvasRenderer.js b/v3/src/gameobjects/tilemap/static/StaticTilemapCanvasRenderer.js index 7167f10df..789245e6e 100644 --- a/v3/src/gameobjects/tilemap/static/StaticTilemapCanvasRenderer.js +++ b/v3/src/gameobjects/tilemap/static/StaticTilemapCanvasRenderer.js @@ -18,7 +18,6 @@ var StaticTilemapCanvasRenderer = function (renderer, gameObject, interpolationP var image = frame.source.image; var tx = gameObject.x - camera.scrollX * gameObject.scrollFactorX; var ty = gameObject.y - camera.scrollY * gameObject.scrollFactorY; - var boundsX = camera.scrollX; ctx.save(); ctx.translate(tx, ty); @@ -29,6 +28,7 @@ var StaticTilemapCanvasRenderer = function (renderer, gameObject, interpolationP for (var index = 0; index < tileCount; ++index) { var tile = tiles[index]; + ctx.drawImage(image, tile.frameX, tile.frameY, tileWidth, tileHeight, tile.x, tile.y, tileWidth, tileHeight); } diff --git a/v3/src/gameobjects/tilemap/static/StaticTilemapWebGLRenderer.js b/v3/src/gameobjects/tilemap/static/StaticTilemapWebGLRenderer.js index c45d96125..b2fac8132 100644 --- a/v3/src/gameobjects/tilemap/static/StaticTilemapWebGLRenderer.js +++ b/v3/src/gameobjects/tilemap/static/StaticTilemapWebGLRenderer.js @@ -12,6 +12,7 @@ var StaticTilemapWebGLRenderer = function (renderer, src, interpolationPercentag var gl = gameObject.gl; renderer.setRenderer(gameObject.tilemapRenderer, frame.texture.source[frame.sourceIndex].glTexture, gameObject.renderTarget); + gameObject.tilemapRenderer.bind(); gameObject.upload(camera); gameObject.vbo.bind();