本文接上文:Android游戲引擎libgdx使用教程12:如何使用TiledMap地圖
地圖我們創建好了接下來就是主角的出現。其實上文介紹了如何TiledMap和Stage的結合,角色的處理就簡單了。
可以繼承Actor類創建主角類,我就偷個懶,用Image代替。
編輯我們的TMX文件,添加一個對象層。
在主角要出現的地方加個形狀。
取名為play1。
我們的主角是:
思路是我們遍歷map中的所有Object,如果名字和我們設定的play1一致,那麼就實例化一個Image,位置和Object一致,添加到舞台。
關鍵代碼:
Java代碼
- for (TiledObjectGroup group : map.objectGroups) {
- for (TiledObject object : group.objects) {
- if ("play1".equals(object.name)) {
- player = new Image(new TextureRegion(new Texture(Gdx.files
- .internal("map/player.png")), 0, 0, 27, 40));
- player.x = object.x;
- player.y = tileMapRenderer.getMapHeightUnits() - object.y; //map是左上角,Stage是左下角
- stage.addActor(player);
- }
- }
- }
效果如下:
然後現在來試試讓主角動起來。
首先是我們如何控制,android設備的話優先選用觸控。如果我們按住前方不放,主角向前。按住上方不放,主角向上。
那麼如何確定我們按住的是哪個方向呢?
如圖所示,黃色的是Stage,粉紅的邊框是整個Map,有部分顯示,有一部分沒有顯示。右下角的綠色點是主角的位置,我們假定紅色的點是我們的觸碰點。
認定紅色的觸碰點為向前,我在提供一個方案,但是方法不唯一哈,我這樣確定方向也不一定是最符合用戶體驗的。
以主角的位置為原點重現建立坐標系,得到觸碰點的新坐標x,y。
確定了在新坐標系下的觸碰點的象限,在判斷x,y的大小就可以知道方向了。
代碼如下:
Java代碼
- Vector3 tmp = new Vector3(x, y, 0);
- stage.getCamera().unproject(tmp);
- float newx = tmp.x - player.x;
- float newy = tmp.y - player.y;
- if (newx > 0 && newy > 0) {
- if (newx > newy) {
- ChangeDirect(4);
- } else {
- ChangeDirect(1);
- }
- } else if (newx > 0 && newy < 0) {
- if (newx > -newy) {
- ChangeDirect(4);
- } else {
- ChangeDirect(2);
- }
- } else if (newx < 0 && newy > 0) {
- if (-newx > newy) {
- ChangeDirect(3);
- } else {
- ChangeDirect(1);
- }
- } else {
- if (-newx > -newy) {
- ChangeDirect(3);
- } else {
- ChangeDirect(2);
- }
- }
直接移動Camera位置可以移動地圖,但是我們的主角卻從地圖上消失了…處理辦法是將你希望仍然顯示在地圖上的Actor的坐標隨著Camera一起移動。
代碼如下:
Java代碼
- private void CameraMove(Vector3 vector3) {
- stage.getCamera().position.add(vector3);
- for (Actor actor : stage.getActors()) {
- actor.x += vector3.x;
- actor.y += vector3.y;
- }
- }
完整代碼:
Java代碼
- package com.cnblogs.htynkn.game;
-
- 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.TextureRegion;
- import com.badlogic.gdx.graphics.g2d.tiled.TileAtlas;
- import com.badlogic.gdx.graphics.g2d.tiled.TileMapRenderer;
- 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.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;
-
- public class firstGame implements ApplicationListener, InputProcessor {
-
- Stage stage;
- float width;
- float height;
- private TiledMap map;
- private TileAtlas atlas;
- private TileMapRenderer tileMapRenderer;
- Image player;
- Vector3 camDirection = new Vector3(1, 1, 0);
- Vector2 maxCamPosition = new Vector2(0, 0);
- Vector3 moveVector = new Vector3(0, 0, 0);
- boolean isPress;
-
- // Image image;
-
- @Override
- public void create() {
- final String path = "map/";
- final String mapname = "tilemap";
- FileHandle mapHandle = Gdx.files.internal(path + mapname + ".tmx");
- map = TiledLoader.createMap(mapHandle);
- atlas = new TileAtlas(map, Gdx.files.internal("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);
- Label label = new Label("FPS:", new LabelStyle(new BitmapFont(Gdx.files
- .internal("font/blue.fnt"),
- Gdx.files.internal("font/blue.png"), false), Color.WHITE),
- "fpsLabel");
- label.y = height - label.getPrefHeight();
- label.x = 0;
- stage.addActor(label);
-
- for (TiledObjectGroup group : map.objectGroups) {
- for (TiledObject object : group.objects) {
- if ("play1".equals(object.name)) {
- player = new Image(new TextureRegion(new Texture(Gdx.files
- .internal("map/player.png")), 0, 0, 27, 40));
- player.x = object.x;
- player.y = tileMapRenderer.getMapHeightUnits() - object.y; // map是左上角,Stage是左下角
- stage.addActor(player);
- }
- }
- }
-
- 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();
- if (isPress) {
- CameraMove(moveVector);
- }
- ((Label) stage.findActor("fpsLabel")).setText("FPS: "
- + Gdx.graphics.getFramesPerSecond());
- stage.act(Gdx.graphics.getDeltaTime());
- tileMapRenderer.render(c);
- stage.draw();
- }
-
- private void CameraMove(Vector3 vector3) {
- stage.getCamera().position.add(vector3);
- for (Actor actor : stage.getActors()) {
- actor.x += vector3.x;
- actor.y += vector3.y;
- }
- }
-
- @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) {
- // TODO Auto-generated method stub
- 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;
- }
-
- private void ChangeDirect(int typeId) {
- switch (typeId) {
- case 1:
- moveVector.set(0, 1, 0);
- Gdx.app.log("方向變動", "向上");
- break;
- case 2:
- moveVector.set(0, -1, 0);
- Gdx.app.log("方向變動", "向下");
- break;
- case 3:
- moveVector.set(-1, 0, 0);
- Gdx.app.log("方向變動", "向左");
- break;
- case 4:
- moveVector.set(1, 0, 0);
- Gdx.app.log("方向變動", "向右");
- break;
- }
- }
-
- @Override
- public boolean touchDown(int x, int y, int pointer, int button) {
- Vector3 tmp = new Vector3(x, y, 0);
- stage.getCamera().unproject(tmp);
- float newx = tmp.x - player.x;
- float newy = tmp.y - player.y;
- if (newx > 0 && newy > 0) {
- if (newx > newy) {
- ChangeDirect(4);
- } else {
- ChangeDirect(1);
- }
- } else if (newx > 0 && newy < 0) {
- if (newx > -newy) {
- ChangeDirect(4);
- } else {
- ChangeDirect(2);
- }
- } else if (newx < 0 && newy > 0) {
- if (-newx > newy) {
- ChangeDirect(3);
- } else {
- ChangeDirect(1);
- }
- } else {
- if (-newx > -newy) {
- ChangeDirect(3);
- } else {
- ChangeDirect(2);
- }
- }
- isPress = true;
- 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) {
- isPress = false;
- Gdx.app.log("Info", "touchUp: x:" + x + " y: " + y + " pointer: "
- + pointer + " button: " + button);
- return false;
- }
- }
我不知道怎麼錄制手機屏幕,所以只有用模擬機演示,但是真機速度很流暢,完全沒問題。
如果有多個角色,方法是一樣的,多建幾個Object就行了。可以很明顯看出,我們的忍者水平很高…行走地圖完全沒有障礙,而且如果你一直走的話會發現地圖會消失一部分,這些問題接下的文章會慢慢解決的。