前些日子的文章介紹了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。
所以構造函數為
Java代碼
- public Enemy(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就可以了。
Java代碼
- 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到達下一個點時對點序列的更新。
當它和下一個點的距離很小時我們認定它到達下一個點,更新序列以保證它繼續向下一個點移動。
Java代碼
- 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列。
完整代碼:
Java代碼
- 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;
-
- public class 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;
-
- @Override
- public void create() {
- 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;
- }
- }
分割線=====================================分割線
Java代碼
- 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;
-
- public class Enemy extends Image {
-
- List<Vector2> vector2s = new ArrayList<Vector2>();
- int currentIndex;
- float stepLength = 1f;
-
- public Enemy(List<Vector2> vector2s, TextureRegion region) {
- super(region);
- this.vector2s = vector2s;
- currentIndex = 0;
- this.x = vector2s.get(currentIndex).x;
- this.y = vector2s.get(currentIndex).y;
- }
-
- @Override
- public void draw(SpriteBatch batch, float parentAlpha) {
- super.draw(batch, parentAlpha);
- }
-
- @Override
- public Actor hit(float x, float y) {
- return null;
- }
- @Override
- public void act(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