加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

12.TiledMap使用详解(一)

(2013-04-26 13:56:26)
标签:

android开发

分类: libGDX开发教程
本文使用的libgdx是0.98版本,可能和最新版有一些不同地方。全文内容仅供参考。

上一次我们是简单的学习了一下如何创建地图,地图和绘制出地图。但是并没有介绍libgdx中是如何对TiledMap
进行封装的,今天我们就来详细的学习一下,libgdx中TiledMap的详细使用方法。

Libgdx游戏引擎(1群):187378034
Libgdx游戏引擎(2群):148848483
Libgdx游戏引擎(3群): 79168470

                       视频教程

1. TiledObjectGroup 类

API定义:包含了TiledMap中的对象层。

成员变量:height、width、name、objets、properties。

height:对象层图块的高度。

width:对象层的图块宽度。

name:对象层图块的名字。

objects: 对象层的图块(即对象)。

properties:对象层的属性。

使用方法:一般都是通过遍历的方式取出坐标或者属性,加上一定的判断条件使用。

代码如下:

    for(TiledObjectGroup group : map.objectGroups{   
                                                        
     }

TiledObjectGroup 其实并不难理解,在上一博文中我们已经知道了对象层是做什么的,这

TiledObjectGroup 其实就是libgdx中对于对象层的封装,方便与我们查找和使用。对象层,顾名思义,他是

用来处理对象的,TiledMap中的对象其实通俗的讲就是游戏中能“动”的事物,以超级玛丽为例,比如玛丽中的

主角、游戏中的金币、移动的敌人小乌龟、长大的蘑菇、打人的炮塔等,这些都是对象,都可以在对象层里面处

理。在上一博文中,我也已经详细的介绍了,如何拖拽出对象层。TiledObjectGroup 一般都是和TildObject连

用的,毕竟TildObject才是里面拖拽出来的对象图块。



2. TildObject 类

API定义:包含TiledMap中的对象图块。

成员变量:object中 X 坐标(int x)、object中Y坐标(int y )、 gid(int)、name、polygon、polyline、properties、type、width、height。

height:对象层图块的高度。

width:对象层的图块宽度。

name:对象层图块的名字。

properties:对象层的属性。

int gid :群体身份。(这个土豆也不是很清楚,求大神指教)

int x : object中的x坐标。

int y : object中的y坐标。

polygon:多边形对象层。

polyline:线性对象层。

功能用法:都是配合TiledObjectGroup使用,同样是作为遍历的对象,常用用于设置对象的出生点。

代码如下:

     for(TiledObject object : group.objects) {            
                                                          
      }

TildObject 是TiledObjectGroup中的对象图块,但是TildObject 作为对象,有许多属性,这些属性就是我们可

以利用来开发游戏的,比如我们可以给object设置属性,然后遍历其中的属性,创建不同的对象,根据不同的对

象向名字,然后得到object实例,从而在该实例的地方,进行相应的操作。详细的方法,在下文的代码实现中,

我会详细介绍的。



3. TiledLayer 类

API定义:包含TiledMap图层信息。

成员变量:name、二维数组tiles[][]、properties。

name:图层名字。

tiles[][]:是一个将TildMap默认分为一个二维数组,方便管理,如果该方块中有图片那么tiles[m][n] = 1(m、n为任意常数),否则的话tiles[m][n] = 0.

使用方法:图层比较常用,这里我就拿一个实例来说明。
       
代码如下:

             tiles = map.layers.get(0).tiles;

             String name = map.layers.get(0).name;

这里相信大家也能看清楚,都知道是做取出tiles和name,这里我要强调一下,这个get(n)是什么意思呢,这个n代表图层数。

如果 n = 0 的话就代表取出“块层1”;n = 1的时候就是代表取出“块层2”依次类推。

TiledLayer 一般比较常用,图层是我们应对碰撞检测时候必须要使用到的元素,所以大家一定要
搞清楚图层的选取项和图层名字。一定要熟悉TiledMap给我们定义好的Tiled[][]数组,这个也是需要我们熟悉的。

4. TileAtlas 类

API定义:以一个tile为单位,储存tiles作为地图集(atlas),用于TileMapRender绘制。

功能用法:一般配合TileMap使用,作为地图集。

代码如下:

atlas = new TileAtlas(map, Gdx.files.internal("data/"));

成员变量:regionMaps、texture。

基本方法:

flipRegions(boolean x, boolean y)  翻转Region

getRegion(int id)  通过id获取region

TileAtlas 一般都是配合tiledmap使用的,这里不详细介绍了。

5. TiledLoader 类

API定义:TiledMap软件中,加载一个TMX文件。

使用方法:有两种使用方法。

(1)通过Gdx获取tmx路径加载文件。
 
  map = TiledLoader.createMap(Gdx.files.internal("data/1.tmx"));

(2)通过TMX文件名加载文件。

  map = TiledLoader.createMap(String tmxdata);

关于 TiledLoader 其实就这么几句话,没什么好解释的,大家这么用下去就可以了。

6. TileSet 类

API定义:Tileset其实是所有tile的集合,这是tiled管理tile的一种分组方式。每个tile有一个name来代表。

使用方法:可以选择使用。

TileSet set = map.tileSets.get(i);

成员变量:firstgid 、imageName、 margin 、name、spacing 、tileHeight 、tilewidth。

firstgid:tile的全局id--firstgid。每个tile内部使用自己的local id,而firstgid作为在多个map中区分tile的标识。

ps:由于一个tile可以被多个map引用,所以layer的data属性值使用base64编码、使用gzip压缩的一个32位整数的数 组,它代表了tile的全局id--firstgid。每个tile内部使用自己的local id,而firstgid作为在多个map中区分tile的标识.

imageName:图块中图片名称。

margin :边距,实质上就是每个矩形图块间的间隙,在上个博文中我也介绍了边距是什么意思。

spacing : Tile四边的边框,因为不常用,所以经常被设置为0。

tileHeight 和 tilewidth :tile的宽和高。


7. TileMapRenderer 类

API定义:通过Sprite绘制一个地图。

参数变量:

TileMapRenderer(int[][][] map, TileAtlas atlas, int tileWidth, int tileHeight,

        float unitsPerTileX, float unitsPerTileY, IntArray blendedTiles, int tilesPerBlockX,

                int tilesPerBlockY, ShaderProgram shader)

(1)第一个参数:传入一个TildMap ,map,即 TMX文件作为 TiledMapRender的对象。

(2)第二个参数:TieldAtlas,图块,上文也介绍到了。

(3)第三、四个参数: tile的宽高,同样上文介绍了。

(4)第五、六个参数:X 轴和 Y 轴方向,图块的缓冲个数。

(5)第七个参数: 混合Tiles,不常用。

(5)第八、九个参数:X 轴和 Y 轴方向,一个单位渲染的图块个数。

(6)第十个参数:阴影效果。

一般参数并不全部使用,只是选择几个常用的参数使用而已,这里全部介绍一下,大家可以自定义使用。

常用方法:TileMapRenderer 中方法比较多,但是常用的不多,这里简单的介绍几个常用的方法。

getMapHeightUnits() 方法:获取地图的高度,单位是像素,宽度也是同理。

render方法:前两个参数是绘制起点,后面连个是绘制宽高,最后是绘制的图层。

render(float x, float y, float width, float height, int[] layers)

render(OrthographicCamera cam)方法:渲染是传入相机。 


8.实例分析

关于0.98版本 Tildmap的封装,这里已经进行了详细的介绍,估计大家已经能了解了这些类的具体功能与实现

了。为了方便大家理解这几个类的使用,这里我们就那一个实例来帮助大家使用TiledMap,由于上面介绍的类有

一些是负责碰撞检测的,这里先不做介绍,后面土豆会单独拿出来一节博文,专门讲解TiledMap中碰撞检测的实

现,以及一些技巧。今天我们还是拿我们的超级玛丽项目当例子。

(1)首先测试一下Tiledobjects、和TileGroup的使用方法。在项目中新建一个Mario的类,继承Actor类。我们将马里奥实例化的时候设置在(0,0)点,然后通过对object遍历的方式,将马里奥放入我们制定好的对象层的坐标中,当然了我们也可以讲马里奥实例化在object的坐标点,这个大家随意了。通过新建一个 setMario()方法来实现。

代码如下:

public void setMario() {
       for(TiledObjectGroup group : map.objectGroups{
           for(TiledObject object : group.objects{
               if("mario".equals(object.name)) {
//                    mario = new Mario(object.x, 
//                            render.getMapHeightUnits() - object.y - 75);
                   mario.x = object.x;
                   mario.y = render.getMapHeightUnits() - object.y - 75;
               }
           }
       }
   }



(2)为了方便检测图层名称,我们这次简单的打印一下图层的名字。

代码如下:

String name = map.layers.get(1).name;

System.out.println(name);

String name1 = map.layers.get(0).name;

System.out.println(name1);

效果图:(大家应该知道eclipse是不支持中文的,没办法这个“块层”2个字打不出来是乱码)


(3)对比效果,如果没有用遍历的方式,我们的马里奥是出生在(0.0)点的,实现了遍历以后马里奥是出生在我们设置的对象层的位置。这里要强调一下,TiledMap的默认起点坐标是左上角为(0.0)点,而不是左下角的(0.0)点,希望大家注意,所以马里奥的Y轴坐标需要转换一下,通过过去屏幕的全部高度然后减去对象层的高度,就转化为我们要获得的人物初始的坐标了。

坐标系图:


效果图:

关于TiledmapRender 在前面也做了详细的介绍,这个在上几篇博文中也做了介绍,这里就不赘述了,关于

TiledSet 我会在碰撞检测的时候给大家做介绍。


完整代码:

(1)TiledMapTest 类代码。

package com.potato;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.tiled.TileAtlas;
import com.badlogic.gdx.graphics.g2d.tiled.TileMapRenderer;
import com.badlogic.gdx.graphics.g2d.tiled.TiledLoader;
import com.badlogic.gdx.graphics.g2d.tiled.TiledMap;
import com.badlogic.gdx.graphics.g2d.tiled.TiledObject;
import com.badlogic.gdx.graphics.g2d.tiled.TiledObjectGroup;
import com.badlogic.gdx.scenes.scene2d.Stage;


public class TiledMapTest implements ApplicationListener {

   TiledMap map;
   TileAtlas atlas;
   int tiles[][];
   TileMapRenderer render;
   OrthographicCamera cam;
   Stage stage;
   Mario mario;
   
   @Override
   public void create()        
       
       map TiledLoader.createMap(Gdx.files.internal("data/1.tmx"));
       
       atlas new TileAtlas(map, Gdx.files.internal("data/"));
       
       render new TileMapRenderer(map, atlas, 1010);
       
       tiles map.layers.get(0).tiles;
               
       String name map.layers.get(1).name;
       
       System.out.println(name);
       
       String name1 map.layers.get(0).name;
       
       System.out.println(name1);
       
       cam  new OrthographicCamera();
               
       cam.setToOrtho(false480320);
           
       stage new Stage(480320false);
       
       mario new Mario(00);        
       
       setMario();
       
       stage.addActor(mario);
       
       stage.addActor(mario.buttonL);
       
       stage.addActor(mario.buttonR);
       
       Gdx.input.setInputProcessor(stage);
   }

   @Override
   public void dispose() {
       
   }
   
   public void setMario() {
       for(TiledObjectGroup group map.objectGroups{
           for(TiledObject object group.objects{
               if("mario".equals(object.name)) {
//                    mario = new Mario(object.x, 
//                            render.getMapHeightUnits() - object.y - 75);
                   mario.x object.x;
                   mario.y render.getMapHeightUnits() object.y 75;
               }
           }
       }
   }

   @Override
   public void render()        
       Gdx.gl.glClearColor(0000);
       Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
       
       render.render(cam);
       
       stage.act();
       stage.draw();
       
   }

   @Override
   public void resize(int width, int height) {
   }

   @Override
   public void pause() {
   }

   @Override
   public void resume() {
   }
}


(2) Mario 类中代码。

package com.potato;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;

public class Mario extends Actor{
   
   public static float ;
   public static float ;
   public float statetime;
   
   Texture texture;
   TextureRegion currentFrame;
   
   ImageButton buttonL;
   ImageButton buttonR;
   
   Animation aniRight;
   Animation aniLeft;
   Animation aniIdle;
   
   STATE state;

   enum STATE {
       Left,Right,Idel
   };
   
   public Mario(float x,float y) {

       this.x x;
       this.y y;
       this.statetime 0;
       this.show();
       state STATE.Idel;
       
   }
   
   @Override
   public void draw(SpriteBatch batch, float parentAlpha) {
       // TODO Auto-generated method stub

       statetime += Gdx.graphics.getDeltaTime();
       
       this.update();
       
       this.check();
       
       batch.draw(currentFrame, x, y);


   }

   public void update() {
       if(state == STATE.Left){
           this.x -= 1.5f;    
           if(this.x 20this.x 20;
       }else if (state == STATE.Right{
           this.x +=1.5f;
           if(this.x 400this.x 400;
       }
       this.x x;
   }
   
   public void check() {
       if(state == STATE.Left{
           currentFrame aniLeft.getKeyFrame(statetime, true);
       }else if (state == STATE.Right{
           currentFrame aniRight.getKeyFrame(statetime, true);
       }else if (state == STATE.Idel{
           currentFrame aniIdle.getKeyFrame(statetime, true);
       }
       
   }
   
   public void show() {
       texture new Texture(Gdx.files.internal("data/Mario.png"));
       
       TextureRegion[][] spilt TextureRegion.split(texture, 6464);
       TextureRegion[][] miror TextureRegion.split(texture, 6464);
       
       for(TextureRegion[] region1 miror){
           for(TextureRegion region2 region1){
               region2.flip(truefalse);
           }
       }
       //右
       TextureRegion[] regionR new TextureRegion[3];
           regionR[0spilt[0][1];
           regionR[1spilt[0][2];
           regionR[2spilt[0][0];
       aniRight new Animation(0.1fregionR);
       //左
       TextureRegion[] regionL new TextureRegion[3];
       regionL[0miror[0][1];
       regionL[1miror[0][2];
       regionL[2miror[0][0];
       aniLeft new Animation(0.1fregionL);
       //空闲
       TextureRegion[] regionI new TextureRegion[1];
       regionI[0spilt[0][0];

       aniIdle new Animation(0.1fregionI);
   
       buttonL new ImageButton(new TextureRegionDrawable(spilt[1][0]), new TextureRegionDrawable(spilt[1][1]));
       buttonR new ImageButton(new TextureRegionDrawable(miror[1][0]), new TextureRegionDrawable(miror[1][1]));
       
       buttonL.setPosition(2020);
       buttonR.setPosition(10020);
       
       buttonL.addListener(new InputListener(){

           @Override
           public void touchUp(InputEvent event, float x, float y,
                   int pointer, int button) {
               // TODO Auto-generated method stub
               state STATE.Idel;
               super.touchUp(event, x, y, pointer, button);
           }

           @Override
           public boolean touchDown(InputEvent event, float x, float y,
                   int pointer, int button) {
               // TODO Auto-generated method stub
               state STATE.Left;
               return true;
           }
           
       });
       buttonR.addListener(new InputListener(){
           @Override
           public void touchUp(InputEvent event, float x, float y,
                   int pointer, int button) {
               // TODO Auto-generated method stub
               state STATE.Idel;
               super.touchUp(event, x, y, pointer, button);
           }
           @Override
           public boolean touchDown(InputEvent event, float x, float y,
                   int pointer, int button) {
               // TODO Auto-generated method stub
               state STATE.Right;
               return true;
           }
           
       });
       
   
   }
   
   
}


源码下载:http://pan.baidu.com/share/link?shareid=421751&uk=3456175979

写在最后,关于libgdx中封装TiledMap就介绍到这里了,作为地图编辑器,Tiledmap给我们开发游戏带来了很多的方便,0.98版本对于TiledMap的封装以及使用方法就介绍到这里,由于0.99版本马上就要推出了,这里土豆决定再写一篇关于0.99版本的Tiledmap的使用,不过就不能这么详细的写了,希望大家能理解。下一篇是是关于libgdx框架中《TiledMap使用详解(二)》的博文,我会介绍0.99版本的Tiledmap的使用。如果大家有什么问题可以加我QQ:316344618,一起讨论下。

                             ------------奋斗小土豆丶
                                                                                                          2013 年 4 月 26 日

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有