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。

town

town1

然后绘制地图:

adancedmap

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

adancedmap

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

adancedmap

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

advancelibgdx

现在新建一个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     }

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

advancelibgdx2

我们现在在点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         }

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

advancelibgdx3

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

Enemy用的图片是这张

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

posted @ 2013-02-04 21:13  王世桢  阅读(204)  评论(0)    收藏  举报