android游戏开发框架libgdx的使用(十七)—TiledMap中角色的行动路径

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

转载自夜明的孤行灯

本文链接地址: https://www.huangyunkun.com/2012/01/19/libgdx_17/

分享了一些素材,有兴趣的朋友可以看看:http://www.cnblogs.com/htynkn/archive/2012/01/19/game_resource.html

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

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

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

2.按照固定路线移动

3.不动

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

还是新建一张地图,我选用的大小是5030,块大小:3232。

towntown1

然后绘制地图:

adancedmap

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

adancedmap

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

adancedmap

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

advancelibgdx

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

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

所以构造函数为

publicEnemy(List<vector2> vector2s, TextureRegion region) {super(region);this.vector2s = vector2s; currentIndex =0;this.x = vector2s.get(currentIndex).x;this.y = vector2s.get(currentIndex).y; }

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

advancelibgdx2

我们现在在点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) * stepLength; moveY = (y / z) * stepLength;if (this.x < v2.x) {this.x += moveX; }else {this.x -= moveX; }if (this.y < v2.y) {this.y += moveY; }else {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); }

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

advancelibgdx3

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

Enemy用的图片是这张

Enemy

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

完整代码:

package com.cnblogs.htynkn.game;import java.util.ArrayList;import java.util.List;import javax.swing.text.ZoneView;import javax.swing.text.html.MinimalHTMLWriter;import com.badlogic.gdx.ApplicationListener;import com.badlogic.gdx.Gdx;import com.badlogic.gdx.InputMultiplexer;import com.badlogic.gdx.InputProcessor;import com.badlogic.gdx.files.FileHandle;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.TextureAtlas;import com.badlogic.gdx.graphics.g2d.TextureRegion;import com.badlogic.gdx.graphics.g2d.tiled.TileAtlas;import com.badlogic.gdx.graphics.g2d.tiled.TileMapRenderer;import com.badlogic.gdx.graphics.g2d.tiled.TileSet;import com.badlogic.gdx.graphics.g2d.tiled.TiledLayer;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.graphics.glutils.ShaderProgram;import com.badlogic.gdx.math.MathUtil;import com.badlogic.gdx.math.Vector2;import com.badlogic.gdx.math.Vector3;import com.badlogic.gdx.scenes.scene2d.Actor;import com.badlogic.gdx.scenes.scene2d.Stage;import com.badlogic.gdx.scenes.scene2d.ui.Image;import com.badlogic.gdx.scenes.scene2d.ui.Label;import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;import com.cnblogs.htynkn.actors.Enemy;publicclass MapDemo implements ApplicationListener, InputProcessor { Stage stage;float width;float height;private TiledMap map;private TileAtlas atlas;private TileMapRenderer tileMapRenderer; Vector3 camDirection =new Vector3(1,1,0); Vector2 maxCamPosition =new Vector2(0,0); Vector3 moveVector =new Vector3(0,0,0); Enemy enemy;int i =0;@Overridepublicvoidcreate() {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,true); 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); list .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); } @Override public void dispose() { // TODO Auto-generated method stub } @Override public void pause() { // TODO Auto-generated method stub } @Override 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(); } @Override public void resize(int width, int height) { // TODO Auto-generated method stub } @Override public void resume() { // TODO Auto-generated method stub } @Override public boolean keyDown(int keycode) { return false; } @Override public boolean keyTyped(char character) { // TODO Auto-generated method stub return false; } @Override public boolean keyUp(int keycode) { // TODO Auto-generated method stub return false; } @Override public boolean scrolled(int amount) { // TODO Auto-generated method stub return false; } @Override public boolean touchDown(int x, int y, int pointer, int button) { return false; } @Override public boolean touchDragged(int x, int y, int pointer) { // TODO Auto-generated method stub return false; } @Override public boolean touchMoved(int x, int y) { // TODO Auto-generated method stub return false; } @Override 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 com.cnblogs.htynkn.actors;import java.util.ArrayList;import java.util.List;import com.badlogic.gdx.graphics.g2d.SpriteBatch;import com.badlogic.gdx.graphics.g2d.TextureRegion;import com.badlogic.gdx.math.MathUtil;import com.badlogic.gdx.math.Vector2;import com.badlogic.gdx.scenes.scene2d.Actor;import com.badlogic.gdx.scenes.scene2d.ui.Image;publicclass Enemy extends Image { List<vector2> vector2s =new ArrayList<vector2>();int currentIndex;float stepLength =1f;publicEnemy(List<vector2> vector2s, TextureRegion region) {super(region);this.vector2s = vector2s; currentIndex =0;this.x = vector2s.get(currentIndex).x;this.y = vector2s.get(currentIndex).y; }@Overridepublicvoiddraw(SpriteBatch batch,float parentAlpha) {super.draw(batch, parentAlpha); }@Overridepublic Actorhit(float x,float y) {returnnull; }@Overridepublicvoidact(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) * stepLength; moveY = (y / z) * stepLength;if (this.x < v2.x) {this.x += moveX; }else {this.x -= moveX; }if (this.y < v2.y) {this.y += moveY; }else {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); } }

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

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

转载自夜明的孤行灯

本文链接地址: https://www.huangyunkun.com/2012/01/19/libgdx_17/

发表评论