android游戏开发框架libgdx的使用(十三)—TiledMap中的角色和角色移动
转载声明:http://www.cnblogs.com/htynkn/archive/2012/01/13/libgdx_13.html
地图我们创建好了接下来就是主角的出现。其实上文介绍了如何TiledMap和Stage的结合,角色的处理就简单了。
可以继承Actor类创建主角类,我就偷个懒,用Image代替。
编辑我们的TMX文件,添加一个对象层。

在主角要出现的地方加个形状

取名为play1

我们的主角是:

思路是我们遍历map中的所有Object,如果名字和我们设定的play1一致,那么就实例化一个Image,位置和Object一致,添加到舞台。
关键代码:
1 for (TiledObjectGroup group : map.objectGroups) { 2 for (TiledObject object : group.objects) { 3 if ("play1".equals(object.name)) { 4 player = new Image(new TextureRegion(new Texture(Gdx.files 5 .internal("map/player.png")), 0, 0, 27, 40)); 6 player.x = object.x; 7 player.y = tileMapRenderer.getMapHeightUnits() - object.y; //map是左上角,Stage是左下角 8 stage.addActor(player); 9 } 10 } 11 }
效果如下:

然后现在来试试让主角动起来。
首先是我们如何控制,android设备的话优先选用触控。如果我们按住前方不放,主角向前。按住上方不放,主角向上。
那么如何确定我们按住的是哪个方向呢?

如图所示,黄色的是Stage,粉红的边框是整个Map,有部分显示,有一部分没有显示。右下角的绿色点是主角的位置,我们假定红色的点是我们的触碰点。
认定红色的触碰点为向前,我在提供一个方案,但是方法不唯一哈,我这样确定方向也不一定是最符合用户体验的。
以主角的位置为原点重现建立坐标系,得到触碰点的新坐标x,y.
确定了在新坐标系下的触碰点的象限,在判断x,y的大小就可以知道方向了。
代码如下:
1 Vector3 tmp = new Vector3(x, y, 0); 2 stage.getCamera().unproject(tmp); 3 float newx = tmp.x - player.x; 4 float newy = tmp.y - player.y; 5 if (newx > 0 && newy > 0) { 6 if (newx > newy) { 7 ChangeDirect(4); 8 } else { 9 ChangeDirect(1); 10 } 11 } else if (newx > 0 && newy < 0) { 12 if (newx > -newy) { 13 ChangeDirect(4); 14 } else { 15 ChangeDirect(2); 16 } 17 } else if (newx < 0 && newy > 0) { 18 if (-newx > newy) { 19 ChangeDirect(3); 20 } else { 21 ChangeDirect(1); 22 } 23 } else { 24 if (-newx > -newy) { 25 ChangeDirect(3); 26 } else { 27 ChangeDirect(2); 28 } 29 }
直接移动Camera位置可以移动地图,但是我们的主角却从地图上消失了…处理办法是将你希望仍然显示在地图上的Actor的坐标随着Camera一起移动。
代码如下:
1 private void CameraMove(Vector3 vector3) { 2 stage.getCamera().position.add(vector3); 3 for (Actor actor : stage.getActors()) { 4 actor.x += vector3.x; 5 actor.y += vector3.y; 6 } 7 }
完整代码:
1 package com.cnblogs.htynkn.game; 2 3 import com.badlogic.gdx.ApplicationListener; 4 import com.badlogic.gdx.Gdx; 5 import com.badlogic.gdx.InputMultiplexer; 6 import com.badlogic.gdx.InputProcessor; 7 import com.badlogic.gdx.files.FileHandle; 8 import com.badlogic.gdx.graphics.Color; 9 import com.badlogic.gdx.graphics.GL10; 10 import com.badlogic.gdx.graphics.OrthographicCamera; 11 import com.badlogic.gdx.graphics.Texture; 12 import com.badlogic.gdx.graphics.g2d.BitmapFont; 13 import com.badlogic.gdx.graphics.g2d.TextureRegion; 14 import com.badlogic.gdx.graphics.g2d.tiled.TileAtlas; 15 import com.badlogic.gdx.graphics.g2d.tiled.TileMapRenderer; 16 import com.badlogic.gdx.graphics.g2d.tiled.TiledLoader; 17 import com.badlogic.gdx.graphics.g2d.tiled.TiledMap; 18 import com.badlogic.gdx.graphics.g2d.tiled.TiledObject; 19 import com.badlogic.gdx.graphics.g2d.tiled.TiledObjectGroup; 20 import com.badlogic.gdx.math.Vector2; 21 import com.badlogic.gdx.math.Vector3; 22 import com.badlogic.gdx.scenes.scene2d.Actor; 23 import com.badlogic.gdx.scenes.scene2d.Stage; 24 import com.badlogic.gdx.scenes.scene2d.ui.Image; 25 import com.badlogic.gdx.scenes.scene2d.ui.Label; 26 import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle; 27 28 public class firstGame implements ApplicationListener, InputProcessor { 29 30 Stage stage; 31 float width; 32 float height; 33 private TiledMap map; 34 private TileAtlas atlas; 35 private TileMapRenderer tileMapRenderer; 36 Image player; 37 Vector3 camDirection = new Vector3(1, 1, 0); 38 Vector2 maxCamPosition = new Vector2(0, 0); 39 Vector3 moveVector = new Vector3(0, 0, 0); 40 boolean isPress; 41 42 // Image image; 43 44 @Override 45 public void create() { 46 final String path = "map/"; 47 final String mapname = "tilemap"; 48 FileHandle mapHandle = Gdx.files.internal(path + mapname + ".tmx"); 49 map = TiledLoader.createMap(mapHandle); 50 atlas = new TileAtlas(map, Gdx.files.internal("map/")); 51 tileMapRenderer = new TileMapRenderer(map, atlas, 10, 10); 52 maxCamPosition.set(tileMapRenderer.getMapWidthUnits(), tileMapRenderer 53 .getMapHeightUnits()); 54 55 width = Gdx.graphics.getWidth(); 56 height = Gdx.graphics.getHeight(); 57 stage = new Stage(width, height, true); 58 Label label = new Label("FPS:", new LabelStyle(new BitmapFont(Gdx.files 59 .internal("font/blue.fnt"), 60 Gdx.files.internal("font/blue.png"), false), Color.WHITE), 61 "fpsLabel"); 62 label.y = height - label.getPrefHeight(); 63 label.x = 0; 64 stage.addActor(label); 65 66 for (TiledObjectGroup group : map.objectGroups) { 67 for (TiledObject object : group.objects) { 68 if ("play1".equals(object.name)) { 69 player = new Image(new TextureRegion(new Texture(Gdx.files 70 .internal("map/player.png")), 0, 0, 27, 40)); 71 player.x = object.x; 72 player.y = tileMapRenderer.getMapHeightUnits() - object.y; // map是左上角,Stage是左下角 73 stage.addActor(player); 74 } 75 } 76 } 77 78 InputMultiplexer inputMultiplexer = new InputMultiplexer(); 79 inputMultiplexer.addProcessor(this); 80 inputMultiplexer.addProcessor(stage); 81 Gdx.input.setInputProcessor(inputMultiplexer); 82 } 83 84 @Override 85 public void dispose() { 86 // TODO Auto-generated method stub 87 88 } 89 90 @Override 91 public void pause() { 92 // TODO Auto-generated method stub 93 94 } 95 96 @Override 97 public void render() { 98 Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); 99 OrthographicCamera c = (OrthographicCamera) stage.getCamera(); 100 if (isPress) { 101 CameraMove(moveVector); 102 } 103 ((Label) stage.findActor("fpsLabel")).setText("FPS: " 104 + Gdx.graphics.getFramesPerSecond()); 105 stage.act(Gdx.graphics.getDeltaTime()); 106 tileMapRenderer.render(c); 107 stage.draw(); 108 } 109 110 private void CameraMove(Vector3 vector3) { 111 stage.getCamera().position.add(vector3); 112 for (Actor actor : stage.getActors()) { 113 actor.x += vector3.x; 114 actor.y += vector3.y; 115 } 116 } 117 118 @Override 119 public void resize(int width, int height) { 120 // TODO Auto-generated method stub 121 122 } 123 124 @Override 125 public void resume() { 126 // TODO Auto-generated method stub 127 128 } 129 130 @Override 131 public boolean keyDown(int keycode) { 132 // TODO Auto-generated method stub 133 return false; 134 } 135 136 @Override 137 public boolean keyTyped(char character) { 138 // TODO Auto-generated method stub 139 return false; 140 } 141 142 @Override 143 public boolean keyUp(int keycode) { 144 // TODO Auto-generated method stub 145 return false; 146 } 147 148 @Override 149 public boolean scrolled(int amount) { 150 // TODO Auto-generated method stub 151 return false; 152 } 153 154 private void ChangeDirect(int typeId) { 155 switch (typeId) { 156 case 1: 157 moveVector.set(0, 1, 0); 158 Gdx.app.log("方向变动", "向上"); 159 break; 160 case 2: 161 moveVector.set(0, -1, 0); 162 Gdx.app.log("方向变动", "向下"); 163 break; 164 case 3: 165 moveVector.set(-1, 0, 0); 166 Gdx.app.log("方向变动", "向左"); 167 break; 168 case 4: 169 moveVector.set(1, 0, 0); 170 Gdx.app.log("方向变动", "向右"); 171 break; 172 } 173 } 174 175 @Override 176 public boolean touchDown(int x, int y, int pointer, int button) { 177 Vector3 tmp = new Vector3(x, y, 0); 178 stage.getCamera().unproject(tmp); 179 float newx = tmp.x - player.x; 180 float newy = tmp.y - player.y; 181 if (newx > 0 && newy > 0) { 182 if (newx > newy) { 183 ChangeDirect(4); 184 } else { 185 ChangeDirect(1); 186 } 187 } else if (newx > 0 && newy < 0) { 188 if (newx > -newy) { 189 ChangeDirect(4); 190 } else { 191 ChangeDirect(2); 192 } 193 } else if (newx < 0 && newy > 0) { 194 if (-newx > newy) { 195 ChangeDirect(3); 196 } else { 197 ChangeDirect(1); 198 } 199 } else { 200 if (-newx > -newy) { 201 ChangeDirect(3); 202 } else { 203 ChangeDirect(2); 204 } 205 } 206 isPress = true; 207 return false; 208 } 209 210 @Override 211 public boolean touchDragged(int x, int y, int pointer) { 212 // TODO Auto-generated method stub 213 return false; 214 } 215 216 @Override 217 public boolean touchMoved(int x, int y) { 218 // TODO Auto-generated method stub 219 return false; 220 } 221 222 @Override 223 public boolean touchUp(int x, int y, int pointer, int button) { 224 isPress = false; 225 Gdx.app.log("Info", "touchUp: x:" + x + " y: " + y + " pointer: " 226 + pointer + " button: " + button); 227 return false; 228 } 229 }
最终效果:(图像加载可能有点慢)
(...传不上来)无语中...
我不知道怎么录制手机屏幕,所以只有用模拟机演示,但是真机(中兴V880)速度很流畅,完全没问题。
如果有多个角色,方法是一样的,多建几个Object就行了。可以很明显看出,我们的忍者水平很高…行走地图完全没有障碍,而且如果你一直走的话会发现地图会消失一部分,这些问题接下的文章会慢慢解决的。

浙公网安备 33010602011771号