android游戏开发框架libgdx的使用(十七)—TiledMap中角色的行动路径
转载声明:http://www.cnblogs.com/htynkn/archive/2012/01/19/libgdx_17.html
分享了一些素材,有兴趣的朋友可以看看:http://www.cnblogs.com/htynkn/archive/2012/01/19/game_resource.html
前些日子的文章介绍了tiledmap的主角出现和移动等等问题。相对于主角游戏自然还应该有敌人(?)。
与主角不同的是,这些元素的移动时程序控制的,一般有3种。
1.随主角的移动变化,靠近主角或远离主角
2.按照固定路线移动
3.不动
第一种的话完全是看你的游戏逻辑决定,和tiledmap关系不大。第二种的话我们可以避免硬编码(把移动路径写入程序代码中),而采用tiledmap实现,下面我们来看看具体过程。
还是新建一张地图,我选用的大小是50*30,块大小:32*32。
然后绘制地图:
我们假定敌人从地图中间的那条路走到左边的角上。路径如下:
现在新建一个对象层,命名为wayPoints。在几个关键的地方标注上对象,命名为wayPoint1,wayPoint2…
处理好地图后拷贝到项目中。
现在新建一个Enemy类,继承Image。
现在来整理一下思路,首先我们要得到所有的wayPoint.而第一个wayPoint就是角色的初始化点。那么Enemy类首先需要一个Vector2列表,然后继承Image需要一个TextureRegion。
所以构造函数为
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 }
初始点有了,如何移动呢?我们先来看一下坐标
我们现在在点1位置,将要移动到点2位置。只需计算x,y,z长度,然后求出对应的moveX和moveY就可以了。
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到达下一个点时对点序列的更新。
当它和下一个点的距离很小时我们认定它到达下一个点,更新序列以保证它继续向下一个点移动。
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 }
基本没有问题了,我们看一下效果:
因为手机不好截图,所以用的java桌面项目。
Enemy用的图片是这张
用TextureRegion[][] regions = TextureRegion.split(texture, 25, 33);切分,去2行3列。
完整代码:
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(1, 1, 0); 50 Vector2 maxCamPosition = new Vector2(0, 0); 51 Vector3 moveVector = new Vector3(0, 0, 0); 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, 10, 10); 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, 25, 33); 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 }
分割线=====================================分割线
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










浙公网安备 33010602011771号