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

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

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

2.按照固定路线移动

3.不动

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

还是新建一张地图,我选用的大小是50*30,块大小:32*32。

 

然后绘制地图:

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

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

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

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

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

所以构造函数为

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; 
    }

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

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

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

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

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;

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; 
    } 
}

分割线=====================================分割线

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

 

[related_posts limit="3"]
[box]本文对原文有部分修改,原文出处:
作者:黄云坤
出处:http://www.cnblogs.com/htynkn/[/box]