前些日子的文章介绍了tiledmap的主角出现和移动等等问题。相对于主角游戏自然还应该有敌人(?)。

       与主角不同的是,这些元素的移动时程序控制的,一般有3种。

       1.随主角的移动变化,靠近主角或远离主角

       2.按照固定路线移动

       3.不动

       第一种的话完全是看你的游戏逻辑决定,和tiledmap关系不大。第二种的话我们可以避免硬编码(把移动路径写入程序代码中),而采用tiledmap实现,下面我们来看看具体过程。

       还是新建一张地图,我选用的大小是50*30,块大小:32*32。

Android游戏引擎libgdx使用教程16:TiledMap中角色的行动路径

town

Android游戏引擎libgdx使用教程16:TiledMap中角色的行动路径

town1

       然后绘制地图:

Android游戏引擎libgdx使用教程16:TiledMap中角色的行动路径

adancedmap

       我们假定敌人从地图中间的那条路走到左边的角上。路径如下:

Android游戏引擎libgdx使用教程16:TiledMap中角色的行动路径

adancedmap

       现在新建一个对象层,命名为wayPoints。在几个关键的地方标注上对象,命名为wayPoint1,wayPoint2…

Android游戏引擎libgdx使用教程16:TiledMap中角色的行动路径

adancedmap

       处理好地图后拷贝到项目中。

Android游戏引擎libgdx使用教程16:TiledMap中角色的行动路径

advancelibgdx

       现在新建一个Enemy类,继承Image。

       现在来整理一下思路,首先我们要得到所有的wayPoint.而第一个wayPoint就是角色的初始化点。那么Enemy类首先需要一个Vector2列表,然后继承Image需要一个TextureRegion。

       所以构造函数为

Java代码
  1. public Enemy(List<Vector2> vector2s, TextureRegion region) {   
  2. super(region);   
  3. this.vector2s = vector2s;   
  4. currentIndex = 0;   
  5. this.x = vector2s.get(currentIndex).x;   
  6. this.y = vector2s.get(currentIndex).y;   
  7. }  

       初始点有了,如何移动呢?我们先来看一下坐标

Android游戏引擎libgdx使用教程16:TiledMap中角色的行动路径

advancelibgdx2

       我们现在在点1位置,将要移动到点2位置。只需计算x,y,z长度,然后求出对应的moveX和moveY就可以了。

Java代码
  1. float x = Math.abs(v1.x - v2.x);   
  2. float y = Math.abs(v1.y - v2.y);   
  3. float z = (float) MathUtil.distanceBetweenTwoPoints(v1, v2);   
  4. float moveX = 0f;   
  5. float moveY = 0f;   
  6. moveX = (x / z) * stepLength;   
  7. moveY = (y / z) * stepLength;   
  8. if (this.x < v2.x) {   
  9. this.x += moveX;   
  10. else {   
  11. this.x -= moveX;   
  12. }   
  13. if (this.y < v2.y) {   
  14. this.y += moveY;   
  15. else {   
  16. this.y -= moveY;   
  17. }  

       distanceBetweenTwoPoints是我自己写的方法,计算两点距离。

       现在我们的Enemy类就可以很正常的移动到下一个点了。

       但当它接近下一个点的时候可以发现它在不停的颤抖。这是因为我们没有处理当Enemy到达下一个点时对点序列的更新。

       当它和下一个点的距离很小时我们认定它到达下一个点,更新序列以保证它继续向下一个点移动。

Java代码
  1. int nextIndex = currentIndex + 1 >= vector2s.size() - 1 ? vector2s   
  2. .size() - 1 : currentIndex + 1;   
  3. Vector2 v1 = vector2s.get(currentIndex);   
  4. Vector2 v2 = vector2s.get(nextIndex);   
  5. if (MathUtil.distanceBetweenTwoPoints(new Vector2(this.x, this.y), v2) < 1) {   
  6. currentIndex = currentIndex + 1 < vector2s.size() - 1 ? currentIndex + 1   
  7. : vector2s.size() - 1;   
  8. nextIndex = currentIndex + 1 >= vector2s.size() - 1 ? vector2s   
  9. .size() - 1 : currentIndex + 1;   
  10. v1 = vector2s.get(currentIndex);   
  11. v2 = vector2s.get(nextIndex);   
  12. }  

       基本没有问题了,我们看一下效果:

Android游戏引擎libgdx使用教程16:TiledMap中角色的行动路径

advancelibgdx3

       因为手机不好截图,所以用的java桌面项目。

       Enemy用的图片是这张

Android游戏引擎libgdx使用教程16:TiledMap中角色的行动路径

Enemy

       用TextureRegion[][] regions = TextureRegion.split(texture, 25, 33);切分,去2行3列。

       完整代码:

Java代码
  1. package com.cnblogs.htynkn.game;  
  2.   
  3. import java.util.ArrayList;   
  4. import java.util.List;  
  5.   
  6. import javax.swing.text.ZoneView;   
  7. import javax.swing.text.html.MinimalHTMLWriter;  
  8.   
  9. import com.badlogic.gdx.ApplicationListener;   
  10. import com.badlogic.gdx.Gdx;   
  11. import com.badlogic.gdx.InputMultiplexer;   
  12. import com.badlogic.gdx.InputProcessor;   
  13. import com.badlogic.gdx.files.FileHandle;   
  14. import com.badlogic.gdx.graphics.Color;   
  15. import com.badlogic.gdx.graphics.GL10;   
  16. import com.badlogic.gdx.graphics.OrthographicCamera;   
  17. import com.badlogic.gdx.graphics.Texture;   
  18. import com.badlogic.gdx.graphics.g2d.BitmapFont;   
  19. import com.badlogic.gdx.graphics.g2d.SpriteBatch;   
  20. import com.badlogic.gdx.graphics.g2d.TextureAtlas;   
  21. import com.badlogic.gdx.graphics.g2d.TextureRegion;   
  22. import com.badlogic.gdx.graphics.g2d.tiled.TileAtlas;   
  23. import com.badlogic.gdx.graphics.g2d.tiled.TileMapRenderer;   
  24. import com.badlogic.gdx.graphics.g2d.tiled.TileSet;   
  25. import com.badlogic.gdx.graphics.g2d.tiled.TiledLayer;   
  26. import com.badlogic.gdx.graphics.g2d.tiled.TiledLoader;   
  27. import com.badlogic.gdx.graphics.g2d.tiled.TiledMap;   
  28. import com.badlogic.gdx.graphics.g2d.tiled.TiledObject;   
  29. import com.badlogic.gdx.graphics.g2d.tiled.TiledObjectGroup;   
  30. import com.badlogic.gdx.graphics.glutils.ShaderProgram;   
  31. import com.badlogic.gdx.math.MathUtil;   
  32. import com.badlogic.gdx.math.Vector2;   
  33. import com.badlogic.gdx.math.Vector3;   
  34. import com.badlogic.gdx.scenes.scene2d.Actor;   
  35. import com.badlogic.gdx.scenes.scene2d.Stage;   
  36. import com.badlogic.gdx.scenes.scene2d.ui.Image;   
  37. import com.badlogic.gdx.scenes.scene2d.ui.Label;   
  38. import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;   
  39. import com.cnblogs.htynkn.actors.Enemy;  
  40.   
  41. public class MapDemo implements ApplicationListener, InputProcessor {  
  42.   
  43. Stage stage;   
  44. float width;   
  45. float height;   
  46. private TiledMap map;   
  47. private TileAtlas atlas;   
  48. private TileMapRenderer tileMapRenderer;   
  49. Vector3 camDirection = new Vector3(110);   
  50. Vector2 maxCamPosition = new Vector2(00);   
  51. Vector3 moveVector = new Vector3(000);   
  52. Enemy enemy;   
  53. int i = 0;  
  54.   
  55. @Override   
  56. public void create() {   
  57. final String path = "map/";   
  58. final String mapname = "adancedmap";   
  59. FileHandle mapHandle = Gdx.files.internal(path + mapname + ".tmx");   
  60. map = TiledLoader.createMap(mapHandle);  
  61.   
  62. atlas = new TileAtlas(map, new FileHandle("map/"));   
  63. tileMapRenderer = new TileMapRenderer(map, atlas, 1010);   
  64. maxCamPosition.set(tileMapRenderer.getMapWidthUnits(), tileMapRenderer   
  65. .getMapHeightUnits());  
  66.   
  67. width = Gdx.graphics.getWidth();   
  68. height = Gdx.graphics.getHeight();   
  69. stage = new Stage(width, height, true);   
  70.   
  71. List<Vector2> list = new ArrayList<Vector2>();   
  72. //获取所有wayPoints   
  73. for (TiledObjectGroup group : map.objectGroups) {   
  74. for (TiledObject object : group.objects) {   
  75. if (object.name.startsWith("wayPoint")) {   
  76. System.out.println(object.name + " X:" + object.x + " Y:"   
  77. + object.y);   
  78. list   
  79. .add(new Vector2(object.x, maxCamPosition.y   
  80. - object.y));   
  81. }   
  82. }   
  83. }   
  84. TextureAtlas region = new TextureAtlas(Gdx.files.internal("imgs/pack"));   
  85. Texture texture = region.findRegion("Enemy").getTexture();   
  86. TextureRegion[][] regions = TextureRegion.split(texture, 2533);   
  87. enemy = new Enemy(list, regions[1][2]);   
  88. stage.addActor(enemy);   
  89. InputMultiplexer inputMultiplexer = new InputMultiplexer();   
  90. inputMultiplexer.addProcessor(this);   
  91. inputMultiplexer.addProcessor(stage);   
  92. Gdx.input.setInputProcessor(inputMultiplexer);   
  93. }  
  94.   
  95. @Override   
  96. public void dispose() {   
  97. // TODO Auto-generated method stub  
  98.   
  99. }  
  100.   
  101. @Override   
  102. public void pause() {   
  103. // TODO Auto-generated method stub  
  104.   
  105. }  
  106.   
  107. @Override   
  108. public void render() {   
  109. Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);   
  110. OrthographicCamera c = (OrthographicCamera) stage.getCamera();   
  111. c.position.set(enemy.x, enemy.y, 0);   
  112. stage.act(Gdx.graphics.getDeltaTime());   
  113. tileMapRenderer.render(c);   
  114. stage.draw();   
  115. }  
  116.   
  117. @Override   
  118. public void resize(int width, int height) {   
  119. // TODO Auto-generated method stub  
  120.   
  121. }  
  122.   
  123. @Override   
  124. public void resume() {   
  125. // TODO Auto-generated method stub  
  126.   
  127. }  
  128.   
  129. @Override   
  130. public boolean keyDown(int keycode) {   
  131. return false;   
  132. }  
  133.   
  134. @Override   
  135. public boolean keyTyped(char character) {   
  136. // TODO Auto-generated method stub   
  137. return false;   
  138. }  
  139.   
  140. @Override   
  141. public boolean keyUp(int keycode) {   
  142. // TODO Auto-generated method stub   
  143. return false;   
  144. }  
  145.   
  146. @Override   
  147. public boolean scrolled(int amount) {   
  148. // TODO Auto-generated method stub   
  149. return false;   
  150. }  
  151.   
  152. @Override   
  153. public boolean touchDown(int x, int y, int pointer, int button) {   
  154. return false;   
  155. }  
  156.   
  157. @Override   
  158. public boolean touchDragged(int x, int y, int pointer) {   
  159. // TODO Auto-generated method stub   
  160. return false;   
  161. }  
  162.   
  163. @Override   
  164. public boolean touchMoved(int x, int y) {   
  165. // TODO Auto-generated method stub   
  166. return false;   
  167. }  
  168.   
  169. @Override   
  170. public boolean touchUp(int x, int y, int pointer, int button) {   
  171. Gdx.app.log("Info""touchUp: x:" + x + " y: " + y + " pointer: "   
  172. + pointer + " button: " + button);   
  173. return false;   
  174. }   
  175. }  

分割线=====================================分割线

Java代码
  1. package com.cnblogs.htynkn.actors;  
  2.   
  3. import java.util.ArrayList;   
  4. import java.util.List;  
  5.   
  6. import com.badlogic.gdx.graphics.g2d.SpriteBatch;   
  7. import com.badlogic.gdx.graphics.g2d.TextureRegion;   
  8. import com.badlogic.gdx.math.MathUtil;   
  9. import com.badlogic.gdx.math.Vector2;   
  10. import com.badlogic.gdx.scenes.scene2d.Actor;   
  11. import com.badlogic.gdx.scenes.scene2d.ui.Image;  
  12.   
  13. public class Enemy extends Image {  
  14.   
  15. List<Vector2> vector2s = new ArrayList<Vector2>();   
  16. int currentIndex;   
  17. float stepLength = 1f;  
  18.   
  19. public Enemy(List<Vector2> vector2s, TextureRegion region) {   
  20. super(region);   
  21. this.vector2s = vector2s;   
  22. currentIndex = 0;   
  23. this.x = vector2s.get(currentIndex).x;   
  24. this.y = vector2s.get(currentIndex).y;   
  25. }  
  26.   
  27. @Override   
  28. public void draw(SpriteBatch batch, float parentAlpha) {   
  29. super.draw(batch, parentAlpha);   
  30. }  
  31.   
  32. @Override   
  33. public Actor hit(float x, float y) {   
  34. return null;   
  35. }   
  36. @Override   
  37. public void act(float delta) {   
  38. int nextIndex = currentIndex + 1 >= vector2s.size() - 1 ? vector2s   
  39. .size() - 1 : currentIndex + 1;   
  40. Vector2 v1 = vector2s.get(currentIndex);   
  41. Vector2 v2 = vector2s.get(nextIndex);   
  42. if (MathUtil.distanceBetweenTwoPoints(new Vector2(this.x, this.y), v2) < 1) {   
  43. currentIndex = currentIndex + 1 < vector2s.size() - 1 ? currentIndex + 1   
  44. : vector2s.size() - 1;   
  45. nextIndex = currentIndex + 1 >= vector2s.size() - 1 ? vector2s   
  46. .size() - 1 : currentIndex + 1;   
  47. v1 = vector2s.get(currentIndex);   
  48. v2 = vector2s.get(nextIndex);   
  49. }   
  50. float x = Math.abs(v1.x - v2.x);   
  51. float y = Math.abs(v1.y - v2.y);   
  52. float z = (float) MathUtil.distanceBetweenTwoPoints(v1, v2);   
  53. float moveX = 0f;   
  54. float moveY = 0f;   
  55. moveX = (x / z) * stepLength;   
  56. moveY = (y / z) * stepLength;   
  57. if (this.x < v2.x) {   
  58. this.x += moveX;   
  59. else {   
  60. this.x -= moveX;   
  61. }   
  62. if (this.y < v2.y) {   
  63. this.y += moveY;   
  64. else {   
  65. this.y -= moveY;   
  66. }   
  67. System.out.println("pos: " + this.x + "," + this.y + " v1:"   
  68. + v1.toString() + " v2:" + v2.toString() + " d:" + z + " move:"   
  69. + moveX + " , " + moveY);   
  70. super.act(delta);   
  71. }   
  72. }  

文章中用到的地图文件和相关资源:http://www.ctdisk.com/file/4279808

本文发布:Android开发网
本文地址:http://www.jizhuomi.com/android/game/455.html
2015年5月26日
发布:鸡啄米 分类:Android游戏开发 浏览: 评论:0