游戏开发中的地图资源使用tiledmap 资源有什么好处

您所在的位置: &
2.2.4 瓦片地图创建工具:Tiled
2.2.4 瓦片地图创建工具:Tiled
机械工业出版社
《Android游戏开发实践指南》第2章游戏要素与工具,本章讲述了用来开发游戏的工具,包括进行代码开发、美工和声音制作所用的工具。本节为大家介绍瓦片地图创建工具:Tiled。
2.2.4 瓦片地图创建工具:Tiled
在电脑游戏中,瓦片用来绘制一组规则的矩形图像,例如一小块地图。在V3游戏中,有吸血鬼入侵的游戏区域以及其上的障碍物,都是通过瓦片拼成的。Tiled地图编辑器(可在下载)是一款免费软件,用Qt跨平台UI开发库编写,因此可运行在Windows、Linux及Mac OS X操作系统上。本书第9章的相关章节专门会讲述瓦片地图的用法,在图2.3中,我们先看一下正在编辑中的瓦片地图是什么样子。
(点击查看大图)图2.3 Tiled瓦片地图编辑器
【责任编辑: TEL:(010)】&&&&&&
关于&&的更多文章
在Android游戏开发中交互、传感器使用和音效都是非常重要的部分
本书描述了黑客用默默无闻的行动为数字世界照亮了一条道路的故事。
Web 2.0技术对传统界面设计的创新和变革,直接影响着
每天,Google都要测试和发布数百万个源文件、亿万行的
DSL(领域专用语言)的要旨在于沟通。精心设计的DSL
本书是目前所能找到的最实用、最全面的Linux指南和参考手册,也是唯一一本提供以下全部内容的书籍:
更好更实用的示例覆盖了实
51CTO旗下网站android游戏开发框架libgdx的使用(十七)—TiledMap中角色的行动路径
android游戏开发框架libgdx的使用(十七)—TiledMap中角色的行动路径
发布时间: 3:04:10
编辑:www.fx114.net
本篇文章主要介绍了"android游戏开发框架libgdx的使用(十七)—TiledMap中角色的行动路径",主要涉及到android游戏开发框架libgdx的使用(十七)—TiledMap中角色的行动路径方面的内容,对于android游戏开发框架libgdx的使用(十七)—TiledMap中角色的行动路径感兴趣的同学可以参考一下。
分享了一些素材,有兴趣的朋友可以看看:
前些日子的文章介绍了tiledmap的主角出现和移动等等问题。相对于主角游戏自然还应该有敌人(?)。
与主角不同的是,这些元素的移动时程序控制的,一般有3种。
1.随主角的移动变化,靠近主角或远离主角
2.按照固定路线移动
第一种的话完全是看你的游戏逻辑决定,和tiledmap关系不大。第二种的话我们可以避免硬编码(把移动路径写入程序代码中),而采用tiledmap实现,下面我们来看看具体过程。
还是新建一张地图,我选用的大小是50*30,块大小:32*32。
图片分享:
然后绘制地图:
图片分享:
我们假定敌人从地图中间的那条路走到左边的角上。路径如下:
图片分享:
现在新建一个对象层,命名为wayPoints。在几个关键的地方标注上对象,命名为wayPoint1,wayPoint2…
图片分享:
处理好地图后拷贝到项目中。
图片分享:
现在新建一个Enemy类,继承Image。
现在来整理一下思路,首先我们要得到所有的wayPoint.而第一个wayPoint就是角色的初始化点。那么Enemy类首先需要一个Vector2列表,然后继承Image需要一个TextureRegion。
所以构造函数为
public Enemy(List&Vector2& vector2s, TextureRegion region) {
super(region);
this.vector2s = vector2s;
currentIndex = 0;
this.x = vector2s.get(currentIndex).x;
this.y = vector2s.get(currentIndex).y;
初始点有了,如何移动呢?我们先来看一下坐标
图片分享:
我们现在在点1位置,将要移动到点2位置。只需计算x,y,z长度,然后求出对应的moveX和moveY就可以了。
float x = Math.abs(v1.x - v2.x);
float y = Math.abs(v1.y - v2.y);
float z = (float) MathUtil.distanceBetweenTwoPoints(v1, v2);
float moveX = 0f;
float moveY = 0f;
moveX = (x / z) * stepL
moveY = (y / z) * stepL
if (this.x & v2.x) {
this.x += moveX;
this.x -= moveX;
if (this.y & v2.y) {
this.y += moveY;
this.y -= moveY;
distanceBetweenTwoPoints是我自己写的方法,计算两点距离。
现在我们的Enemy类就可以很正常的移动到下一个点了。
但当它接近下一个点的时候可以发现它在不停的颤抖。这是因为我们没有处理当Enemy到达下一个点时对点序列的更新。
当它和下一个点的距离很小时我们认定它到达下一个点,更新序列以保证它继续向下一个点移动。
int nextIndex = currentIndex + 1 &= vector2s.size() - 1 ? vector2s
.size() - 1 : currentIndex + 1;
Vector2 v1 = vector2s.get(currentIndex);
Vector2 v2 = vector2s.get(nextIndex);
if (MathUtil.distanceBetweenTwoPoints(new Vector2(this.x,
this.y), v2) & 1) {
currentIndex = currentIndex + 1 & vector2s.size() - 1 ? currentIndex + 1
: vector2s.size() - 1;
nextIndex = currentIndex + 1 &= vector2s.size() - 1 ? vector2s
.size() - 1 : currentIndex + 1;
v1 = vector2s.get(currentIndex);
v2 = vector2s.get(nextIndex);
基本没有问题了,我们看一下效果:
图片分享:
因为手机不好截图,所以用的java桌面项目。
Enemy用的图片是这张
用TextureRegion[][] regions = TextureRegion.split(texture, 25, 33);切分,去2行3列。
完整代码:
package blogs.htynkn.
import java.util.ArrayL
import java.util.L
import javax.swing.text.ZoneV
import javax.swing.text.html.MinimalHTMLW
import com.badlogic.gdx.ApplicationL
import com.badlogic.gdx.G
import com.badlogic.gdx.InputM
import com.badlogic.gdx.InputP
import com.badlogic.gdx.files.FileH
import com.badlogic.gdx.graphics.C
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicC
import com.badlogic.gdx.graphics.T
import com.badlogic.gdx.graphics.g2d.BitmapF
import com.badlogic.gdx.graphics.g2d.SpriteB
import com.badlogic.gdx.graphics.g2d.TextureA
import com.badlogic.gdx.graphics.g2d.TextureR
import com.badlogic.gdx.graphics.g2d.tiled.TileA
import com.badlogic.gdx.graphics.g2d.tiled.TileMapR
import com.badlogic.gdx.graphics.g2d.tiled.TileS
import com.badlogic.gdx.graphics.g2d.tiled.TiledL
import com.badlogic.gdx.graphics.g2d.tiled.TiledL
import com.badlogic.gdx.graphics.g2d.tiled.TiledM
import com.badlogic.gdx.graphics.g2d.tiled.TiledO
import com.badlogic.gdx.graphics.g2d.tiled.TiledObjectG
import com.badlogic.gdx.graphics.glutils.ShaderP
import com.badlogic.gdx.math.MathU
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.A
import com.badlogic.gdx.scenes.scene2d.S
import com.badlogic.gdx.scenes.scene2d.ui.I
import com.badlogic.gdx.scenes.scene2d.ui.L
import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelS
import blogs.htynkn.actors.E
public class MapDemo
implements ApplicationListener, InputProcessor {
private TiledM
private TileA
private TileMapRenderer tileMapR
Vector3 camDirection = new Vector3(1, 1, 0);
Vector2 maxCamPosition = new Vector2(0, 0);
Vector3 moveVector = new Vector3(0, 0, 0);
int i = 0;
public void create() {
final String path = &map/&;
final String mapname = &adancedmap&;
FileHandle mapHandle = Gdx.files.internal(path + mapname + &.tmx&);
map = TiledLoader.createMap(mapHandle);
atlas = new TileAtlas(map,
new FileHandle(&map/&));
tileMapRenderer = new TileMapRenderer(map, atlas, 10, 10);
maxCamPosition.set(tileMapRenderer.getMapWidthUnits(), tileMapRenderer
.getMapHeightUnits());
width = Gdx.graphics.getWidth();
height = Gdx.graphics.getHeight();
stage = new Stage(width, height,
List&Vector2& list = new ArrayList&Vector2&();
//获取所有wayPoints
for (TiledObjectGroup group : map.objectGroups) {
for (TiledObject object : group.objects) {
if (object.name.startsWith(&wayPoint&)) {
System.out.println(object.name + & X:& + object.x + & Y:&
+ object.y);
.add(new Vector2(object.x, maxCamPosition.y
- object.y));
TextureAtlas region = new TextureAtlas(Gdx.files.internal(&imgs/pack&));
Texture texture = region.findRegion(&Enemy&).getTexture();
TextureRegion[][] regions = TextureRegion.split(texture, 25, 33);
enemy = new Enemy(list, regions[1][2]);
stage.addActor(enemy);
InputMultiplexer inputMultiplexer = new InputMultiplexer();
inputMultiplexer.addProcessor(this);
inputMultiplexer.addProcessor(stage);
Gdx.input.setInputProcessor(inputMultiplexer);
public void dispose() {
// TODO Auto-generated method stub
public void pause() {
// TODO Auto-generated method stub
public void render() {
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
OrthographicCamera c = (OrthographicCamera) stage.getCamera();
c.position.set(enemy.x, enemy.y, 0);
stage.act(Gdx.graphics.getDeltaTime());
tileMapRenderer.render(c);
stage.draw();
public void resize(int width,
int height) {
// TODO Auto-generated method stub
public void resume() {
// TODO Auto-generated method stub
public boolean keyDown(int keycode) {
return false;
public boolean keyTyped(char character) {
// TODO Auto-generated method stub
return false;
public boolean keyUp(int keycode) {
// TODO Auto-generated method stub
return false;
public boolean scrolled(int amount) {
// TODO Auto-generated method stub
return false;
public boolean touchDown(int x,
int y, int pointer,
int button) {
return false;
public boolean touchDragged(int x,
int y, int pointer) {
// TODO Auto-generated method stub
return false;
public boolean touchMoved(int x,
// TODO Auto-generated method stub
return false;
public boolean touchUp(int x,
int y, int pointer,
int button) {
Gdx.app.log(&Info&, &touchUp: x:& + x + & y: & + y + & pointer: &
+ pointer + & button: & + button);
return false;
分割线=====================================分割线
package blogs.htynkn.
import java.util.ArrayL
import java.util.L
import com.badlogic.gdx.graphics.g2d.SpriteB
import com.badlogic.gdx.graphics.g2d.TextureR
import com.badlogic.gdx.math.MathU
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.A
import com.badlogic.gdx.scenes.scene2d.ui.I
public class Enemy
extends Image {
List&Vector2& vector2s = new ArrayList&Vector2&();
int currentI
float stepLength = 1f;
public Enemy(List&Vector2& vector2s, TextureRegion region) {
super(region);
this.vector2s = vector2s;
currentIndex = 0;
this.x = vector2s.get(currentIndex).x;
this.y = vector2s.get(currentIndex).y;
public void draw(SpriteBatch batch,
float parentAlpha) {
super.draw(batch, parentAlpha);
public Actor hit(float x,
float y) {
return null;
public void act(float delta) {
int nextIndex = currentIndex + 1 &= vector2s.size() - 1 ? vector2s
.size() - 1 : currentIndex + 1;
Vector2 v1 = vector2s.get(currentIndex);
Vector2 v2 = vector2s.get(nextIndex);
if (MathUtil.distanceBetweenTwoPoints(new Vector2(this.x,
this.y), v2) & 1) {
currentIndex = currentIndex + 1 & vector2s.size() - 1 ? currentIndex + 1
: vector2s.size() - 1;
nextIndex = currentIndex + 1 &= vector2s.size() - 1 ? vector2s
.size() - 1 : currentIndex + 1;
v1 = vector2s.get(currentIndex);
v2 = vector2s.get(nextIndex);
float x = Math.abs(v1.x - v2.x);
float y = Math.abs(v1.y - v2.y);
float z = (float) MathUtil.distanceBetweenTwoPoints(v1, v2);
float moveX = 0f;
float moveY = 0f;
moveX = (x / z) * stepL
moveY = (y / z) * stepL
if (this.x & v2.x) {
this.x += moveX;
this.x -= moveX;
if (this.y & v2.y) {
this.y += moveY;
this.y -= moveY;
System.out.println(&pos: & + this.x + &,& +
this.y + & v1:&
+ v1.toString() + & v2:& + v2.toString() + & d:& + z + & move:&
+ moveX + & , & + moveY);
super.act(delta);
文章中用到的地图文件和相关资源:
本文标题:
本页链接:提示:本文记录的是本人的操作流程和心得,各位操作时可能由于版本和其它问题会出现点障碍,请参考本文后面的评论和回复。
虽说可以用Image什么的当个背景,但是要是做个RPG类的游戏就有点复杂了。为了追求效率一般可以使用libgdx的SpriteCache,但是如果习惯于TiledMap的话libgdx也是支持的。
相关的类是TiledMap,TileAtlas,TileMapRenderer,都在com.badlogic.gdx.graphics.g2d.tiled之中。
现在我们从头来看看TiledMap的使用。
1.制作TiledMap。
我使用的是Tile Map editor,下载地址:
先新建一个地图,大小50*30,每个块的大小是32*32。
然后我使用的图块资源是从网上下的,具体出处不知了,对于资源奉献者表示感谢~
添加一个新图块
块的高宽都是32.边距和间距都是1px,这些数值是取决你的图块资源本身的。效果如下:
然后发挥想象吧,画一幅地图。
保存tmx文件。然后用gdx-tiled-preprocessor处理一下。
处理完成后会多三个文件,覆盖原来的同名文件:
tilest1.png文件:
终于可以开始绘制了&
map = TiledLoader.createMap(mapHandle); atlas = new TileAtlas(map, new FileHandle("map/")); tileMapRenderer = new TileMapRenderer(map, atlas, 10, 10)
最后在render用tileMapRenderer.render(cam);绘制
而在TileMapRenderer(map, atlas, 10, 10)这句中后面两个10是缓冲的块数,可以酌情调整。我是随意写的。
我个人比较喜欢舞台,其实tiledmap一样可以在舞台中使用。
我在舞台绘制一个标签作为例子。
其实原理很简单,从Stage获取Camera,然后给Render用,最后在Stage绘制。
关键代码:
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); OrthographicCamera c = (OrthographicCamera) stage.getCamera(); ((Label) stage.findActor("fpsLabel")).setText("FPS: "
+ Gdx.graphics.getFramesPerSecond());
stage.act(Gdx.graphics.getDeltaTime());
tileMapRenderer.render(c); stage.draw();
完整代码:
package blogs.htynkn.import com.badlogic.gdx.ApplicationL import com.badlogic.gdx.G import com.badlogic.gdx.files.FileH import com.badlogic.gdx.graphics.C import com.badlogic.gdx.graphics.GL10; import com.badlogic.gdx.graphics.OrthographicC import com.badlogic.gdx.graphics.g2d.BitmapF import com.badlogic.gdx.graphics.g2d.tiled.TileA import com.badlogic.gdx.graphics.g2d.tiled.TileMapR import com.badlogic.gdx.graphics.g2d.tiled.TiledL import com.badlogic.gdx.graphics.g2d.tiled.TiledM import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.scenes.scene2d.S import com.badlogic.gdx.scenes.scene2d.ui.I import com.badlogic.gdx.scenes.scene2d.ui.L import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelSpublic class JavaGame implements ApplicationListener {
private TiledM
private TileA
private TileMapRenderer tileMapR
Vector3 camDirection = new Vector3(1, 1, 0);
Vector2 maxCamPosition = new Vector2(0, 0);
public void create() {
final String path = "map/";
final String mapname = "tilemap";
FileHandle mapHandle = Gdx.files.internal(path + mapname + ".tmx");
map = TiledLoader.createMap(mapHandle);
atlas = new TileAtlas(map, new FileHandle("map/"));
tileMapRenderer = new TileMapRenderer(map, atlas, 10, 10);
maxCamPosition.set(tileMapRenderer.getMapWidthUnits(), tileMapRenderer
.getMapHeightUnits());
width = Gdx.graphics.getWidth();
height = Gdx.graphics.getHeight();
stage = new Stage(width, height, true);
Label label = new Label("FPS:", new LabelStyle(new BitmapFont(Gdx.files
.internal("font/blue.fnt"),
Gdx.files.internal("font/blue.png"), false), Color.BLACK),
"fpsLabel");
stage.addActor(label);
Gdx.input.setInputProcessor(stage);
public void dispose() {
// TODO Auto-generated method stub
public void pause() {
// TODO Auto-generated method stub
public void render() {
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
OrthographicCamera c = (OrthographicCamera) stage.getCamera();
((Label) stage.findActor("fpsLabel")).setText("FPS: "
+ Gdx.graphics.getFramesPerSecond());
stage.act(Gdx.graphics.getDeltaTime());
tileMapRenderer.render(c);
stage.draw();
public void resize(int width, int height) {
// TODO Auto-generated method stub
public void resume() {
// TODO Auto-generated method stub
效果不是很明显,左下角有个Label。
虽说我们绘制出来了Map,但是还没有角色,而且还没有设置墙壁等障碍,接下来的几篇文章会说说这些。
写在最后:
1.做好的TMX文件一定要处理以后再用,用TiledMapPacker处理,不是TexturePacker。我起初弄混淆了,结果把这一块的代码读懂了才反应过来&
2.Stage和TiledMap混用时,一定是stage的绘制在后。
3.Stage的相机可以移动,移动时会产生地图移动效果(比如主角向前走),但是一定要更新Stage的Actors的位置。
这篇博文写了一天半,主要是我粗心把TiledMapPacker和TexturePacker搞错,仔细看了看TexturePacker,觉得TexturePacker也是很有用的东西。算法很有趣,而且还有热心网友做的一个GUI界面,用这个就不用自己辛苦拉图了。
算法介绍:
GUI界面的TexturePacker:
特别说明:
我操作的时候没有任何问题...要是各位遇到问题,请细心调试,可以参考一下:
这里还有博友破木吉他关于tilemap生成的文章:
阅读(...) 评论()

我要回帖

更多关于 tiled地图编辑器教程 的文章

 

随机推荐