LibGDX游戏引擎-10-游戏地图(TiledMap)

来源:互联网 发布:手机申请淘宝号的步骤 编辑:程序博客网 时间:2024/05/17 02:19

转载自:http://www.qiushurong.cn/2014/03/23/tiledmap/

要做游戏地图,在libgdx中我们使用到的工具是TiledMap Editor,官方网址是:链接

Tiled 地图编辑器是一种用于通用目的的编辑器。特点是比较好用,风格类似mini版的photoshop。它可以用于制作多种类型的游戏引擎需要,而且支持使用插件读写map、增加用于引擎的map格式。

地图编辑 :

使用图层、图块以及对象层的方式进行地图的编辑。以“.tmx”格式保存。

————————————————————————————-
地图:

所谓的地图,特别是使用 Tiledmap 制作的地图,其实就是一张背景图片,

加上tiledmap地图编辑起来的一些图块所构成,这也是许多安卓和苹果应用所使用的技巧,

这样不仅可以节省游戏资源同时可以方便代码的实现。
————————————————————————————-
地图图块:

负责做一些碰撞检测等的而背景中的蓝天、白云这些其实就是一张JPG的图片,就是为了是游戏更加好看、美观。

————————————————————————————-

1.TiledMap软件的使用

TiledMap编辑器中,可以分为3个部分,第一个是图层、第二个是图块、第三个是对象层

(1) 图层介绍

游戏中一般要使用许多个图层,根据功能的不同,这里我将图层分为2种,
一种是作为碰撞检测的图层(即检测图层),另一种是作为美观装饰的图层(即装饰图层)。

检测图层:
一个作为碰撞检测的图层,就是负责游戏中不能穿过的图层。一般常作为地面、砖墙、障碍物等方面,游戏中必须使用到的。

装饰图层:
一个作为美观装饰的图层,就是负责装饰的,在地图中不作为碰撞检测,仅仅起到美观的作用,
可有可无,但是为了游戏体验,一般还是加入一个美观的图层,也可以被背景图片替代。

对象层:
一个作为创建对象而是用的图层,该层和其他2种不同,他是负责创建对象而是用的。
例如,超级玛丽中玛丽在地图的哪个点出生,金币在哪个点出生,怪物的设置点说的通俗点就是游戏中可以动的元素

————————————————————————————–

层的高低

  • 对象层
  • 装饰层
  • 障碍层(全透明)
  • 背景层(地板层)

————————————————————————————-

地形

瓦片地图中有许多方式来实现瓦片与瓦片之间地形的过渡,

但Tiled里的地形工具支持对地形的四角完好定义的瓦片图素过渡,这也是最常见的方式。

这个图块有4个不同地形种类。传统的编辑地图方式意味着你不得不小心地连接正确的过渡,来避免把接缝边缘玩坏掉。

但是我们现在会从图块中定义地形信息,地形工具会自动识别和放置地形间正确的过渡。

方法:

1 在图块上点击小按钮“编辑地形信息”

2 出现对话框,并允许你标记属于各地形种类的瓦片衔接处的拐角。

我们现在开始。先添加4种地形种类。最快的方法是,在最准确代表某一地形的瓦片上右键点击,

选择“增加地形类型”。这将自动设置这瓦片作为此地形的图片。

3 起一个合适的名字。然后在图块上标记这个地形应当有的所有拐角。

4如果中途涂错了,可以撤销或用清除工具擦掉错误的拐角。如此对4种地形每个都进行定义。

最终你标记完所有每个特定地形的所有瓦片部件。

5 关闭对话框,可以开始试着使用地形工具啦。使用地形工具编辑

6 切换到地形窗口。你会见到4种地形。点击沙地开始画,你会立即发现并没有什么特别的事情发生。
这是因为此时还没有其他瓦片在地图上,所以地形工具不知道如何提供帮助(因为我们图块种没有与“空”地形的过渡)
既然这样,那么此时我们最好先把整个地图用沙地填满。先暂时切回“图块”窗口,选择沙地瓦片然后使用“填充”工具。

7 切回地形窗口,来画一些地形。现在你可以看到效果啦!

在绘图的时候按住Command键,会减小绘图区域(默认是九宫格,减小后绘制4格)

到最接近光标位置的一个角落,可用来进行细微调整工作。

8 你会发现,当在“尘土”地形里面画鹅卵石的时候,因为没有“尘土”地形与“鹅卵石”地形的直接过渡,地形工具在两者之间插入了沙地地形过渡。很棒。

9 写在最后

现在你应该对地形工具在你自己项目中的运用有了很好的想法。这里还有几件事需要铭记在心:

– 目前这个工具需要所有地形种类的各个瓦片在同一个图块里。你可以有许多带地形的图块,但该工具不能自动跨图块提供地形的过渡。这意味着通常你需要把几个图块合并到一张图里。

– 目前通过Tiled的“添加外部图块”加入的图块包含的地形信息是不可编辑的。如需编辑,可以先导入图块,编辑后再重新导出。

– 地形工具同样适用于等角地图(不能用于交错等角地图),但是,“编辑地形信息”对话框目前对其瓦片不能正确渲染覆盖指示。需要脑补:左上角会应用到上,右上角应用到右,依此类推。有疑问可参考example目录下的“isometric_grass_and_water.tmx”文件。

– 该工具会处理任意数量的地形种类,且每个瓦片拐角都可以有不同种类的地形。针对此工具不能处理的过渡,仍然还有其他方法来解决。还有,同时编辑多图层是不可行的。要寻求关于自动放置瓦片的更加灵活且却更复杂的方法,请查阅“Automapping”。

Tiled在OpenGameArt.org上维护着一些瓦片地图图块,它们包含过渡且与此工具兼容。

以上内容英文原始资料来自《Using the Terrain tool》

————————————————————————————-
地图使用 :
————————————————————————————-
步骤简述:

  • 1 读取地图
  • 2 设置地图渲染
  • 3 新建相机
  • 4 设置相机
  • 5 图层处理
  •  5.1 遍历图层
  •  5.2 遍历图层对象
  •  5.3 读取图层对象属性
  •  5.4 设置障碍标识
  • 6 设置舞台
  •  6.1 新建演员
  •  6.2 添加监听
  •  6.3 添加音乐
  • 7 渲染
  •  7.1 清屏
  •  7.2 舞台渲染
  •   7.2.1 相机更新
  •   7.2.2 地图渲染关联相机
  •   7.2.3 地图渲染
  •   7.2.4 舞台行动
  •   7.2.5 舞台绘制
  •   7.2.6 其他画板绘制
  •  7.3 舞台监听重置
  • 8销毁资源

 

 

地图渲染 OrthogonalTiledMapRenderer 类

 

OrthogonalTiledMapRenderer renderer = new OrthogonalTiledMapRenderer(map,1/20f);map 是 map = new TmxMapLoader().load("map/map1.tmx")
1/20f 是焦距

renderer.setView(camera)
绘制指定图层。传的是数组,例如绘制0,2图层:
int[] layers = {0,2};render(layers);render(OrthographicCamera cam)方法:渲染是传入相机。
相机 OrthographicCamera 类
OrthographicCamera camera = new OrthographicCamera();camera.setToOrtho(false, 40, 24);camera.update();renderer.setView(camera);renderer.render();//相机监听CameraInputController cameraController = new CameraInputController(camera);Gdx.input.setInputProcessor(cameraController);
例子代码:
package com.qsuron11.barriers;import com.badlogic.gdx.ApplicationListener;import com.badlogic.gdx.Gdx;import com.badlogic.gdx.audio.Music;import com.badlogic.gdx.audio.Sound;import com.badlogic.gdx.graphics.Color;import com.badlogic.gdx.graphics.GL10;import com.badlogic.gdx.graphics.OrthographicCamera;import com.badlogic.gdx.graphics.Texture;import com.badlogic.gdx.graphics.g2d.BitmapFont;import com.badlogic.gdx.graphics.g2d.SpriteBatch;import com.badlogic.gdx.graphics.g2d.TextureRegion;import com.badlogic.gdx.maps.MapLayer;import com.badlogic.gdx.maps.MapLayers;import com.badlogic.gdx.maps.MapObject;import com.badlogic.gdx.maps.MapObjects;import com.badlogic.gdx.maps.objects.RectangleMapObject;import com.badlogic.gdx.maps.tiled.TiledMap;import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;import com.badlogic.gdx.maps.tiled.TmxMapLoader;import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;import com.badlogic.gdx.math.MathUtils;import com.badlogic.gdx.scenes.scene2d.InputEvent;import com.badlogic.gdx.scenes.scene2d.InputListener;import com.badlogic.gdx.scenes.scene2d.Stage;import com.badlogic.gdx.scenes.scene2d.ui.Image;import com.qsuron11.barriers.Person;public class MyDemo extends Gdx implements ApplicationListener {public static final int WIDTH = 800;//窗口宽度public static final int HEIGHT = 480;//窗口高度public static final int MAP_PIC = 20;//瓷砖大小public static final int MAP_WIDTH = 40;//瓷砖横向个数public static final int MAP_HEIGHT = 24;//瓷砖纵向个数private static boolean GameIsRunning;//主游戏界面是否运行private static boolean ShopIsRunning;//商店界面是否运行private static boolean SuccessIsRunning;//购买成功界面是否运行private static int[][] barriers;//障碍标识(24行40列)private TiledMap map;//地图private BitmapFont font;//标题字体private SpriteBatch batch;//画板private OrthographicCamera camera;//相机private OrthogonalTiledMapRenderer renderer;//图层渲染private float p_x , p_y;//人物坐标private Image image_openStage_background,//开始游戏背景image_openStage_btn_newGame,//新游戏按钮image_openStage_btn_shop,//商店按钮image_shopStage_background,//商店背景image_shopStage_btn_heart,//商店商品hreatimage_shopStage_btn_coin,//商店商品coinimage_shopStage_btn_close,//商店关闭按钮image_successStage_success;//购买成功private Stage stage,//游戏舞台openStage,  //开始舞台shopStage,  //商店舞台successStage;  //购买成功舞台private Sound sound_openStage_btn_newGame; //新游戏按钮声音private Music music_openStage_background,//开始游戏音乐music_stage_background;//主游戏音乐static{barriers = new int[MAP_HEIGHT][MAP_WIDTH];GameIsRunning = false;ShopIsRunning = false;SuccessIsRunning = false;}@Overridepublic void create() {batch = new SpriteBatch();stage = new Stage(WIDTH, HEIGHT, false, batch);openStage = new Stage(WIDTH, HEIGHT, false, batch);shopStage = new Stage(WIDTH, HEIGHT, false, batch);successStage = new Stage(WIDTH, HEIGHT, false, batch);//地图map = new TmxMapLoader().load("map/map1.tmx");   renderer = new OrthogonalTiledMapRenderer(map,1f/MAP_PIC);   //相机   camera = new OrthographicCamera();   camera.setToOrtho(false, MAP_WIDTH, MAP_HEIGHT);//图层处理   this.setLayer();//设置舞台this.setStage();//设置监听this.setListener();//设置音乐this.setSound();}//判断是否能够移动public static boolean passEnable(float x, float y){//+0.5使四舍五入int col = MathUtils.round(y/MAP_PIC);int row = MathUtils.round(x/MAP_PIC);boolean flag = barriers[col][row] == 0;System.out.println("往↑第" + col + "行,往→第" + row + "列 --> " + flag);return flag;}//判断是否能够下掉public static boolean downEnable(float x, float y) {//+0.5使四舍五入boolean flag = barriers[(int) ((y/MAP_PIC-0.1f))][(int) (x/MAP_PIC+0.5f)] == 0;//System.out.println("往↑第" +  ((y/MAP_PIC-0.1f)) + "行,往→第" +  (x/MAP_PIC+0.5f) + "列 --> " + flag);return flag;}//图层处理private void setLayer(){   MapLayers layers = map.getLayers();for(int i=0;i<layers.getCount();i++){System.out.println("第" + i + "层:" + layers.get(i).getName());}for(MapLayer layer : layers){//遍历图层if(layer.getName().equals("object")){//找到对象层MapObjects objs = layer.getObjects();for(MapObject obj : objs){//遍历图层内容if(obj.getName().equals("person")){//找到人物图块RectangleMapObject rmobj = (RectangleMapObject) obj;p_x = rmobj.getRectangle().x;p_y = rmobj.getRectangle().y;break;}}}if(layer.getName().equals("barriers")){//找到障碍层if(layer instanceof TiledMapTileLayer){//类型转换判断TiledMapTileLayer tlayer = (TiledMapTileLayer) layer;for(int x=0;x<MAP_HEIGHT;x++){for(int y=0;y<MAP_WIDTH;y++){if(tlayer.getCell(y, x) != null){barriers[x][y] = 1;}}}}}}for(int x=0;x<MAP_HEIGHT;x++){for(int y=0;y<MAP_WIDTH;y++){System.out.print(barriers[x][y]+" ");}System.out.println("");}}//设置舞台private void setStage(){//开始游戏舞台Texture texture_open = new Texture(Gdx.files.internal("data/open.png"));Texture texture_button = new Texture(Gdx.files.internal("data/btn_newgame.png"));Texture texture_button2 = new Texture(Gdx.files.internal("data/btn_shop.png"));image_openStage_background = new Image(new TextureRegion(texture_open,798,480));image_openStage_background.setPosition(0,0);image_openStage_btn_newGame = new Image(texture_button);image_openStage_btn_newGame.setPosition(80,380);image_openStage_btn_shop = new Image(texture_button2);image_openStage_btn_shop.setPosition(80,80);openStage.addActor(image_openStage_background);openStage.addActor(image_openStage_btn_newGame);openStage.addActor(image_openStage_btn_shop);//商店舞台Texture texture_shop = new Texture(Gdx.files.internal("data/shop.png"));image_shopStage_background = new Image(new TextureRegion(texture_shop,0,85,512,350));image_shopStage_btn_heart = new Image(new TextureRegion(texture_shop,0,0,102,85));image_shopStage_btn_coin = new Image(new TextureRegion(texture_shop,102,0,102,85));image_shopStage_btn_close = new Image(new TextureRegion(texture_shop,300,10,50,40));image_shopStage_background.setPosition(0, 0);image_shopStage_background.setSize(480,320);image_shopStage_btn_heart.setPosition(190,50);image_shopStage_btn_coin.setPosition(50,50);image_shopStage_btn_close.setPosition(400,275);shopStage.addActor(image_shopStage_background);shopStage.addActor(image_shopStage_btn_heart);shopStage.addActor(image_shopStage_btn_coin);shopStage.addActor(image_shopStage_btn_close);//购买舞台image_successStage_success = new Image(new TextureRegion(texture_shop,512,0,255,255));image_successStage_success.setPosition(100,100);successStage.addActor(image_successStage_success);//游戏舞台//背景//image_stage_background = new Image(new Texture(Gdx.files.internal("data/background.jpg")));//标题font = new BitmapFont(Gdx.files.internal("font/title.fnt"),Gdx.files.internal("font/title.png"),false);font.setColor(Color.BLACK);Gdx.input.setInputProcessor(stage);Person p = new Person(p_x,p_y);stage.addActor(p);stage.addActor(p.btn_L);stage.addActor(p.btn_R);}//设置声音private void setSound() {sound_openStage_btn_newGame = Gdx.audio.newSound(Gdx.files.internal("music/openStage_btn_newGame.ogg"));music_openStage_background = Gdx.audio.newMusic(Gdx.files.internal("music/stage.ogg"));music_stage_background = Gdx.audio.newMusic(Gdx.files.internal("music/openStage.ogg"));music_openStage_background.setLooping(true);music_stage_background.setLooping(true);//播放主页面音乐music_openStage_background.play();}//设置监听private void setListener() {image_openStage_btn_newGame.addListener(new InputListener(){@Overridepublic boolean touchDown(InputEvent event, float x, float y,int pointer, int button) {GameIsRunning = true;music_openStage_background.stop();music_stage_background.play();return true;}});image_openStage_btn_shop.addListener(new InputListener(){@Overridepublic boolean touchDown(InputEvent event, float x, float y,int pointer, int button) {ShopIsRunning = true;return true;}});image_shopStage_btn_heart.addListener(new InputListener() {           @Override           public boolean touchDown(InputEvent event, float x, float y,                   int pointer, int button) {               SuccessIsRunning = true;               sound_openStage_btn_newGame.play(1);               return true;           }});image_shopStage_btn_coin.addListener(new InputListener() {           @Override           public boolean touchDown(InputEvent event, float x, float y,                   int pointer, int button) {               SuccessIsRunning = true;               sound_openStage_btn_newGame.play();               return true;           }       });image_shopStage_btn_close.addListener(new InputListener(){@Override           public boolean touchDown(InputEvent event, float x, float y,                   int pointer, int button) {               ShopIsRunning = false;               return true;           }});image_successStage_success.addListener(new InputListener(){@Override           public boolean touchDown(InputEvent event, float x, float y,                   int pointer, int button) {               SuccessIsRunning = false;               return true;           }});}//重置舞台监听private void updateStage(){if(GameIsRunning){Gdx.input.setInputProcessor(stage);}else{Gdx.input.setInputProcessor(openStage);if(ShopIsRunning){Gdx.input.setInputProcessor(shopStage);if(SuccessIsRunning){Gdx.input.setInputProcessor(successStage);}}}}//重置舞台绘制private void stageRender(){if(GameIsRunning){camera.update();renderer.setView(camera);   renderer.render();stage.act();stage.draw();batch.begin();font.draw(batch,"小树LibGDX游戏引擎开发", 240, 450);//普通绘制batch.end();}else{openStage.act();openStage.draw();if(ShopIsRunning){shopStage.act();shopStage.draw();if(SuccessIsRunning){successStage.act();successStage.draw();}}}} @Overridepublic void render() {Gdx.gl.glClearColor(0,0,0, 0);Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);this.stageRender();this.updateStage();}@Overridepublic void dispose() {batch.dispose();stage.dispose();openStage.dispose();shopStage.dispose();successStage.dispose();map.dispose();}@Overridepublic void resize(int width, int height) {}@Overridepublic void pause() {}@Overridepublic void resume() {}}

第二个类

package com.qsuron11.barriers;import com.badlogic.gdx.Gdx;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.InputEvent;import com.badlogic.gdx.scenes.scene2d.InputListener;import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;public class Person extends Actor {public static final int MAP_PIC = MyDemo.MAP_PIC;public float x;public float y;public float statetime;//按钮ImageButton  btn_L;ImageButton  btn_R;//人物当前状态(枚举类)STATE state;//对应的动画Animation animation_left;Animation animation_right;Animation animation_idle;//实时动画TextureRegion currentFrame;public Person(float x, float y) {super();this.x = x;this.y = y;this.statetime = 0;this.show();state = STATE.I;}public void show() {//分割动画Texture animation_file = new Texture(Gdx.files.internal("data/animation2-2.png"));TextureRegion[][] animation_split_right = TextureRegion.split(animation_file,42,51);TextureRegion[][] animation_split_left = TextureRegion.split(animation_file,42,51);Texture animation_file2 = new Texture(Gdx.files.internal("data/idle.png"));TextureRegion[][] animation_split_idle = TextureRegion.split(animation_file2,42,51);//实例化动画图片组TextureRegion[] textureRegion_right = new TextureRegion[30];TextureRegion[] textureRegion_left = new TextureRegion[30];TextureRegion[] textureRegion_idle = new TextureRegion[1];//向右动画图片组int i = 0;for(TextureRegion[] animation_split_right_split:animation_split_right){for(TextureRegion animation_pic:animation_split_right_split){textureRegion_right[i] = animation_pic;i++;}}//向左动画图片组i = 0;for(TextureRegion[] animation_split_left_split:animation_split_left){for(TextureRegion animation_pic:animation_split_left_split){textureRegion_left[i] = animation_pic;textureRegion_left[i].flip(true,false);i++;}}//原地动画图片组textureRegion_idle[0] = animation_split_idle[0][0];//合成动画animation_right = new Animation(0.05f,textureRegion_right);animation_right.setPlayMode(Animation.LOOP);animation_left = new Animation(0.05f,textureRegion_left);animation_left.setPlayMode(Animation.LOOP);animation_idle = new Animation(1f,textureRegion_idle);animation_idle.setPlayMode(Animation.LOOP);//按钮图片读取Texture button_file = new Texture(Gdx.files.internal("data/button.png"));TextureRegion[][] button_split = TextureRegion.split(button_file,100,100);//按钮实例化btn_R = new ImageButton(new TextureRegionDrawable(button_split[0][0]),new TextureRegionDrawable(button_split[0][1]));btn_L = new ImageButton(new TextureRegionDrawable(button_split[0][2]),new TextureRegionDrawable(button_split[0][3]));//按钮位置btn_R.setPosition(150,20);btn_L.setPosition(20,20);//按钮监听btn_R.addListener(new InputListener(){@Overridepublic boolean touchDown(InputEvent event, float x, float y,int pointer, int button) {state = STATE.R;return true;}@Overridepublic void touchUp(InputEvent event, float x, float y,int pointer, int button) {state = STATE.I;super.touchUp(event, x, y, pointer, button);}});btn_L.addListener(new InputListener(){@Overridepublic boolean touchDown(InputEvent event, float x, float y,int pointer, int button) {state = STATE.L;return true;}@Overridepublic void touchUp(InputEvent event, float x, float y,int pointer, int button) {state = STATE.I;super.touchUp(event, x, y, pointer, button);}});}//状态控制与动画选择public void check() {if(this.state==STATE.L){currentFrame = animation_left.getKeyFrame(statetime,true);}else if(this.state==STATE.R){currentFrame = animation_right.getKeyFrame(statetime,true);}else if(this.state==STATE.I){currentFrame = animation_idle.getKeyFrame(statetime,true);}}//人物移动public void update(){//验证间隔一个瓷砖(x,y是左端点,因此偏移多半块瓷砖)if(state==STATE.L && MyDemo.passEnable(this.x - MAP_PIC*0.5f, this.y)){this.x -= 2f;}else if(state==STATE.R && MyDemo.passEnable(this.x + MAP_PIC*1.5f, this.y)){this.x += 2f;}if(MyDemo.downEnable(this.x, this.y)){this.y -= 2f;}}@Overridepublic void act(float delta) {statetime += delta;this.update();this.check();super.act(delta);}@Overridepublic void draw(SpriteBatch batch, float parentAlpha) {batch.draw(currentFrame, x, y);}enum STATE {L,R,I;};}



0 0
原创粉丝点击