1 /******************************************************************************* 2 * Copyright 2013 See AUTHORS file. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 ******************************************************************************/ 16 17 package com.badlogic.gdx.maps.tiled.renderers; 18 19 import static com.badlogic.gdx.graphics.g2d.Batch.C1; 20 import static com.badlogic.gdx.graphics.g2d.Batch.C2; 21 import static com.badlogic.gdx.graphics.g2d.Batch.C3; 22 import static com.badlogic.gdx.graphics.g2d.Batch.C4; 23 import static com.badlogic.gdx.graphics.g2d.Batch.U1; 24 import static com.badlogic.gdx.graphics.g2d.Batch.U2; 25 import static com.badlogic.gdx.graphics.g2d.Batch.U3; 26 import static com.badlogic.gdx.graphics.g2d.Batch.U4; 27 import static com.badlogic.gdx.graphics.g2d.Batch.V1; 28 import static com.badlogic.gdx.graphics.g2d.Batch.V2; 29 import static com.badlogic.gdx.graphics.g2d.Batch.V3; 30 import static com.badlogic.gdx.graphics.g2d.Batch.V4; 31 import static com.badlogic.gdx.graphics.g2d.Batch.X1; 32 import static com.badlogic.gdx.graphics.g2d.Batch.X2; 33 import static com.badlogic.gdx.graphics.g2d.Batch.X3; 34 import static com.badlogic.gdx.graphics.g2d.Batch.X4; 35 import static com.badlogic.gdx.graphics.g2d.Batch.Y1; 36 import static com.badlogic.gdx.graphics.g2d.Batch.Y2; 37 import static com.badlogic.gdx.graphics.g2d.Batch.Y3; 38 import static com.badlogic.gdx.graphics.g2d.Batch.Y4; 39 40 import com.badlogic.gdx.Gdx; 41 import com.badlogic.gdx.graphics.Color; 42 import com.badlogic.gdx.graphics.OrthographicCamera; 43 import com.badlogic.gdx.graphics.g2d.Batch; 44 import com.badlogic.gdx.graphics.g2d.SpriteBatch; 45 import com.badlogic.gdx.graphics.g2d.TextureRegion; 46 import com.badlogic.gdx.maps.MapLayer; 47 import com.badlogic.gdx.maps.MapObject; 48 import com.badlogic.gdx.maps.tiled.TiledMap; 49 import com.badlogic.gdx.maps.tiled.TiledMapImageLayer; 50 import com.badlogic.gdx.maps.tiled.TiledMapRenderer; 51 import com.badlogic.gdx.maps.tiled.TiledMapTileLayer; 52 import com.badlogic.gdx.maps.tiled.TiledMapTileLayer.Cell; 53 import com.badlogic.gdx.maps.tiled.tiles.AnimatedTiledMapTile; 54 import com.badlogic.gdx.math.Matrix4; 55 import com.badlogic.gdx.math.Rectangle; 56 import com.badlogic.gdx.utils.Disposable; 57 58 public abstract class BatchTiledMapRenderer implements TiledMapRenderer, Disposable { 59 static protected final int NUM_VERTICES = 20; 60 61 protected TiledMap map; 62 63 protected float unitScale; 64 65 protected Batch batch; 66 67 protected Rectangle viewBounds; 68 protected Rectangle imageBounds = new Rectangle(); 69 70 protected boolean ownsBatch; 71 72 protected float vertices[] = new float[NUM_VERTICES]; 73 74 public TiledMap getMap () { 75 return map; 76 } 77 78 public void setMap (TiledMap map) { 79 this.map = map; 80 } 81 82 public float getUnitScale () { 83 return unitScale; 84 } 85 86 public Batch getBatch () { 87 return batch; 88 } 89 90 public Rectangle getViewBounds () { 91 return viewBounds; 92 } 93 94 public BatchTiledMapRenderer (TiledMap map) { 95 this(map, 1.0f); 96 } 97 98 public BatchTiledMapRenderer (TiledMap map, float unitScale) { 99 this.map = map; 100 this.unitScale = unitScale; 101 this.viewBounds = new Rectangle(); 102 this.batch = new SpriteBatch(); 103 this.ownsBatch = true; 104 } 105 106 public BatchTiledMapRenderer (TiledMap map, Batch batch) { 107 this(map, 1.0f, batch); 108 } 109 110 public BatchTiledMapRenderer (TiledMap map, float unitScale, Batch batch) { 111 this.map = map; 112 this.unitScale = unitScale; 113 this.viewBounds = new Rectangle(); 114 this.batch = batch; 115 this.ownsBatch = false; 116 } 117 118 @Override 119 public void setView (OrthographicCamera camera) { 120 batch.setProjectionMatrix(camera.combined); 121 float width = camera.viewportWidth * camera.zoom; 122 float height = camera.viewportHeight * camera.zoom; 123 viewBounds.set(camera.position.x - width / 2, camera.position.y - height / 2, width, height); 124 } 125 126 @Override 127 public void setView (Matrix4 projection, float x, float y, float width, float height) { 128 batch.setProjectionMatrix(projection); 129 viewBounds.set(x, y, width, height); 130 } 131 132 @Override 133 public void render () { 134 beginRender(); 135 for (MapLayer layer : map.getLayers()) { 136 if (layer.isVisible()) { 137 if (layer instanceof TiledMapTileLayer) { 138 renderTileLayer((TiledMapTileLayer)layer); 139 } if (layer instanceof TiledMapImageLayer) { 140 renderImageLayer((TiledMapImageLayer)layer); 141 } else { 142 renderObjects(layer); 143 } 144 } 145 } 146 endRender(); 147 } 148 149 @Override 150 public void render (int[] layers) { 151 beginRender(); 152 for (int layerIdx : layers) { 153 MapLayer layer = map.getLayers().get(layerIdx); 154 if (layer.isVisible()) { 155 if (layer instanceof TiledMapTileLayer) { 156 renderTileLayer((TiledMapTileLayer)layer); 157 } else if (layer instanceof TiledMapImageLayer) { 158 renderImageLayer((TiledMapImageLayer)layer); 159 } else { 160 renderObjects(layer); 161 } 162 } 163 } 164 endRender(); 165 } 166 167 @Override 168 public void renderObjects(MapLayer layer) { 169 for (MapObject object : layer.getObjects()) { 170 renderObject(object); 171 } 172 } 173 174 @Override 175 public void renderObject(MapObject object) { 176 177 } 178 179 @Override 180 public void renderImageLayer(TiledMapImageLayer layer) { 181 final Color batchColor = batch.getColor(); 182 final float color = Color.toFloatBits(batchColor.r, 183 batchColor.g, 184 batchColor.b, 185 batchColor.a * layer.getOpacity()); 186 187 final float[] vertices = this.vertices; 188 189 TextureRegion region = layer.getTextureRegion(); 190 191 if (region == null) { 192 return; 193 } 194 195 final float x = layer.getX(); 196 final float y = layer.getY(); 197 final float x1 = x * unitScale; 198 final float y1 = y * unitScale; 199 final float x2 = x1 + region.getRegionWidth() * unitScale; 200 final float y2 = y1 + region.getRegionHeight() * unitScale; 201 202 imageBounds.set(x1, y1, x2 - x1, y2 - y1); 203 204 if (viewBounds.contains(imageBounds) || viewBounds.overlaps(imageBounds)) { 205 final float u1 = region.getU(); 206 final float v1 = region.getV2(); 207 final float u2 = region.getU2(); 208 final float v2 = region.getV(); 209 210 vertices[X1] = x1; 211 vertices[Y1] = y1; 212 vertices[C1] = color; 213 vertices[U1] = u1; 214 vertices[V1] = v1; 215 216 vertices[X2] = x1; 217 vertices[Y2] = y2; 218 vertices[C2] = color; 219 vertices[U2] = u1; 220 vertices[V2] = v2; 221 222 vertices[X3] = x2; 223 vertices[Y3] = y2; 224 vertices[C3] = color; 225 vertices[U3] = u2; 226 vertices[V3] = v2; 227 228 vertices[X4] = x2; 229 vertices[Y4] = y1; 230 vertices[C4] = color; 231 vertices[U4] = u2; 232 vertices[V4] = v1; 233 234 batch.draw(region.getTexture(), vertices, 0, NUM_VERTICES); 235 } 236 } 237 238 /** Called before the rendering of all layers starts. */ 239 protected void beginRender () { 240 AnimatedTiledMapTile.updateAnimationBaseTime(); 241 batch.begin(); 242 } 243 244 /** Called after the rendering of all layers ended. */ 245 protected void endRender () { 246 batch.end(); 247 } 248 249 @Override 250 public void dispose () { 251 if (ownsBatch) { 252 batch.dispose(); 253 } 254 } 255 256 } 257