libgdx学习记录11——平铺地图TiledMap
地图对于游戏场景十分重要,很多游戏都需要对地图进行编辑,可使用TileMap进行编辑并生成对应的tmx格式地图文件。
编辑好后,可通过TmxMapLoader来读取地图文件。可通过一个正交相机OthographicCamera和正交地图渲染器OrthogonalTiledMapRenderer来进行显示。
实例如下:
1 package com.fxb.newtest; 2 3 import com.badlogic.gdx.ApplicationAdapter; 4 import com.badlogic.gdx.Gdx; 5 import com.badlogic.gdx.Input; 6 import com.badlogic.gdx.graphics.GL10; 7 import com.badlogic.gdx.graphics.OrthographicCamera; 8 import com.badlogic.gdx.graphics.Texture; 9 import com.badlogic.gdx.graphics.g2d.SpriteBatch; 10 import com.badlogic.gdx.graphics.g2d.TextureRegion; 11 import com.badlogic.gdx.maps.MapLayer; 12 import com.badlogic.gdx.maps.objects.RectangleMapObject; 13 import com.badlogic.gdx.maps.tiled.TiledMap; 14 import com.badlogic.gdx.maps.tiled.TiledMapTileLayer; 15 import com.badlogic.gdx.maps.tiled.TmxMapLoader; 16 import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer; 17 import com.badlogic.gdx.scenes.scene2d.InputEvent; 18 import com.badlogic.gdx.scenes.scene2d.InputListener; 19 import com.badlogic.gdx.scenes.scene2d.Stage; 20 import com.badlogic.gdx.scenes.scene2d.ui.Image; 21 22 public class Lib010_TiledMap extends ApplicationAdapter{ 23 24 TiledMap map; 25 OrthogonalTiledMapRenderer renderer; 26 OrthographicCamera camera; 27 TextureRegion regionPurple; 28 TextureRegion regionBlue; 29 TextureRegion regionGreen; 30 31 TiledMapTileLayer layer1; 32 33 Stage stage; 34 Image imgGreen; 35 36 enum StateX{ move_still, move_right, move_left }; 37 enum StateY{ move_still, move_up, move_down }; 38 39 StateX stateX = StateX.move_still; 40 StateY stateY = StateY.move_still; 41 42 float clicktimeX = 0; 43 float clicktimeY = 0; 44 float currentTime = 0; 45 46 @Override 47 public void create() { 48 // TODO Auto-generated method stub 49 50 map = new TmxMapLoader().load( "map1/test1.tmx" ); 51 renderer = new OrthogonalTiledMapRenderer( map ); 52 stage = new Stage( Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false, renderer.getSpriteBatch() ); 53 54 regionPurple = new TextureRegion( new Texture( Gdx.files.internal( "map1/bullet_purple_32.png" ) ) ); 55 regionBlue = new TextureRegion( new Texture( Gdx.files.internal( "map1/bullet_blue_32.png" ) ) ); 56 regionGreen = new TextureRegion( new Texture( Gdx.files.internal( "map1/bullet_green_32.png" ) ) ); 57 58 camera = new OrthographicCamera( 32*30, 32*12 ); 59 //camera.setToOrtho( false, 32*30, 32*12 ); 60 camera.position.set( 32*30/2, 32*12/2, 0 ); 61 camera.update(); 62 63 layer1 = (TiledMapTileLayer)map.getLayers().get(0); 64 MapLayer layer2 = map.getLayers().get(1); 65 66 System.out.println( layer1.getName()+"\n"+layer2.getName() ); 67 68 int count = layer2.getObjects().getCount(); 69 System.out.println(count); 70 for( int i=0; i<count; ++i ){ 71 RectangleMapObject obj = (RectangleMapObject)layer2.getObjects().get(i); 72 String strName = obj.getName(); 73 74 75 if( strName != null ){ 76 System.out.print( strName+"\t" ); 77 if( obj.getProperties() != null ){ 78 if( obj.getProperties().get("level")!=null ){ 79 String strProperty = obj.getProperties().get("level").toString(); 80 System.out.println( strProperty ); 81 82 float x = obj.getRectangle().getX(); 83 float y = obj.getRectangle().getY(); 84 //System.out.println( x/32+","+y/32 ); 85 Image tempImg = new Image( regionPurple ); 86 tempImg.setSize( 32, 32 ); 87 tempImg.setPosition( x, y ); 88 stage.addActor( tempImg ); 89 } 90 else if( obj.getProperties().get("time")!=null ){ 91 float x = obj.getRectangle().getX(); 92 float y = obj.getRectangle().getY(); 93 //System.out.println( x/32+","+y/32 ); 94 Image tempImg = new Image( regionBlue ); 95 tempImg.setSize( 32, 32 ); 96 tempImg.setPosition( x, y ); 97 stage.addActor( tempImg ); 98 } 99 100 } 101 102 103 } 104 } 105 106 107 imgGreen = new Image( regionGreen ); 108 imgGreen.setSize( 32, 32 ); 109 stage.addActor( imgGreen ); 110 imgGreen.setPosition( 0, 0 ); 111 112 stage.addListener(new InputListener(){ 113 @Override 114 public boolean keyDown(InputEvent event, int keycode) { 115 // TODO Auto-generated method stub 116 if( keycode == Input.Keys.UP ){ 117 //imgGreen.translate( 0, 32 ); 118 stateY = StateY.move_up; 119 MoveY(); 120 clicktimeY = currentTime; 121 //state = State.move_still; 122 } 123 else if( keycode == Input.Keys.DOWN ){ 124 //imgGreen.translate( 0, -32 ); 125 stateY = StateY.move_down; 126 MoveY(); 127 clicktimeY = currentTime; 128 //state = State.move_still; 129 } 130 131 if( keycode == Input.Keys.LEFT ){ 132 //imgGreen.translate( -32, 0 ); 133 stateX = StateX.move_left; 134 MoveX(); 135 clicktimeX = currentTime; 136 //state = State.move_still; 137 } 138 else if( keycode == Input.Keys.RIGHT ){ 139 //imgGreen.translate( 32, 0 ); 140 stateX = StateX.move_right; 141 MoveX(); 142 clicktimeX = currentTime; 143 //state = State.move_still; 144 } 145 return true; 146 } 147 148 @Override 149 public boolean keyUp(InputEvent event, int keycode) { 150 // TODO Auto-generated method stub 151 if( keycode == Input.Keys.UP ){ 152 //imgGreen.translate( 0, 32 ); 153 stateY = StateY.move_still; 154 } 155 else if( keycode == Input.Keys.DOWN ){ 156 //imgGreen.translate( 0, -32 ); 157 stateY = StateY.move_still; 158 } 159 160 if( keycode == Input.Keys.LEFT ){ 161 //imgGreen.translate( -32, 0 ); 162 stateX = StateX.move_still; 163 } 164 else if( keycode == Input.Keys.RIGHT ){ 165 //imgGreen.translate( 32, 0 ); 166 stateX = StateX.move_still; 167 } 168 return true; 169 } 170 171 172 }); 173 174 Gdx.input.setInputProcessor( stage ); 175 } 176 177 public void MoveX(){ 178 float x0 = imgGreen.getX(); 179 float y0 = imgGreen.getY(); 180 int x1 = 0, y1 = 0; 181 int x2 = 0, y2 = 0; 182 int x3 = 0, y3 = 0; 183 184 float speed = 2; 185 186 switch( stateX ){ 187 case move_right: 188 imgGreen.translate( speed, 0 ); 189 x1 = (int)( (imgGreen.getX()+31)/32 ); 190 x2 = x3 = x1; 191 192 y1 = (int)( (imgGreen.getY()+1)/32 ); 193 y2 = (int)( (imgGreen.getY()+15)/32 ); 194 y3 = (int)( (imgGreen.getY()+31)/32 ); 195 break; 196 case move_left: 197 imgGreen.translate( -speed, 0 ); 198 x1 = (int)( (imgGreen.getX()+1)/32 ); 199 x2 = x3 = x1; 200 201 y1 = (int)( (imgGreen.getY()+1)/32 ); 202 y2 = (int)( (imgGreen.getY()+15)/32 ); 203 y3 = (int)( (imgGreen.getY()+31)/32 ); 204 break; 205 default: 206 break; 207 } 208 if( layer1.getCell( x1, y1 )!=null || layer1.getCell( x2, y2 )!=null || layer1.getCell( x3, y3 )!=null ){ 209 imgGreen.setPosition( x0, y0 ); 210 } 211 212 } 213 214 public void MoveY(){ 215 float x0 = imgGreen.getX(); 216 float y0 = imgGreen.getY(); 217 int x1 = 0, y1 = 0; 218 int x2 = 0, y2 = 0; 219 int x3 = 0, y3 = 0; 220 221 float speed = 2; 222 switch( stateY ){ 223 case move_up: 224 imgGreen.translate( 0, speed ); 225 x1 = (int)( (imgGreen.getX()+1)/32 ); 226 x2 = (int)( (imgGreen.getX()+15)/32 ); 227 x3 = (int)( (imgGreen.getX()+31)/32 ); 228 229 y1 = (int)( (imgGreen.getTop()-1)/32 ); 230 y2 = y3 = y1; 231 //x2 = x3 = x1; 232 break; 233 case move_down: 234 imgGreen.translate( 0, -speed ); 235 x1 = (int)( (imgGreen.getX()+1)/32 ); 236 x2 = (int)( (imgGreen.getX()+15)/32 ); 237 x3 = (int)( (imgGreen.getX()+31)/32 ); 238 239 y1 = (int)( (imgGreen.getY()+1)/32 ); 240 y2 = y3 = y1; 241 break; 242 default: 243 break; 244 } 245 246 if( layer1.getCell( x1, y1 )!=null || layer1.getCell( x2, y2 )!=null || layer1.getCell( x3, y3 )!=null ){ 247 imgGreen.setPosition( x0, y0 ); 248 } 249 } 250 251 @Override 252 public void render() { 253 // TODO Auto-generated method stub 254 Gdx.gl.glClearColor( 0.5f, 0.5f, 0.5f, 1 ); 255 Gdx.gl.glClear( GL10.GL_COLOR_BUFFER_BIT ); 256 257 renderer.setView(camera); 258 renderer.render(); 259 260 261 currentTime += Gdx.graphics.getDeltaTime(); 262 if( currentTime - clicktimeX > 0.15f ){ 263 MoveX(); 264 } 265 if( currentTime - clicktimeY > 0.15f ){ 266 MoveY(); 267 } 268 269 stage.act(); 270 stage.draw(); 271 } 272 273 @Override 274 public void dispose() { 275 // TODO Auto-generated method stub 276 super.dispose(); 277 } 278 279 280 }
运行结果:
地图是自己随便编辑的。有两个图层,一个背景层,一个对象层。对象层可通过getCell()函数获取地图单元。
通过layer.getMapObject()可获取对应的对象。
MapObject可通过getProperties().get("level")这种形式获取对象的键值,以便在程序中使用。
要获取object的x,y坐标以及长宽时,需将MapObject转化为RectangleMapObject,然后获取其Rectangle就行了。
另外,地图中涉及碰撞检测,一般在控制物体(一般是玩家)的边缘设置2-3个检测点,最好不要设置在两边,而是靠近边缘的点。
大概就这么多了,比较粗糙,记录而已。。