如何让一个角色走主角路线? LIBGDX / JAVA

How to make one character follow the main character path? LIBGDX / JAVA

我正在 libgdx/java 使用 Box2d 开发 2d 角色扮演游戏。

我有主角和其他3个。我希望他们像蛇一样沿着主角的相同路径排队(与Master System / Phantasy Star和其他旧RPG相同)以避免在发现狭窄入口时搞砸。

在我的 PlayScreen class 我单独调用所有角色。

    private static Alis _player;
    private static Myau _follower;
    private static Odin _follower1;
    private static Noah _follower2;

在构造函数播放屏幕上

_player = new Alis(world, this, mapManager);
_follower = new Myau(world, this, mapManager);
_follower1 = new Odin(world, this, mapManager);
_follower2 = new Noah(world, this, mapManager);

HandleInput(float dt)方法我只移动主角

if(Gdx.input.isKeyPressed(Input.Keys.RIGHT) && _player.b2body.getLinearVelocity().x <= 0.5f) {
_player.b2body.applyLinearImpulse(new Vector2(0.05f, 0), _player.b2body.getWorldCenter(), true);

}else if(Gdx.input.isKeyPressed(Input.Keys.LEFT) && _player.b2body.getLinearVelocity().x >= -0.5f) {
_player.b2body.applyLinearImpulse(new Vector2(-0.05f, 0), _player.b2body.getWorldCenter(), true);

}else if(Gdx.input.isKeyPressed(Input.Keys.RIGHT) == Gdx.input.isKeyPressed(Input.Keys.LEFT)){
_player.b2body.setLinearVelocity(0f, _player.b2body.getLinearVelocity().y);
}

if(Gdx.input.isKeyPressed(Input.Keys.UP) && _player.b2body.getLinearVelocity().y <= 0.5f) {
_player.b2body.applyLinearImpulse(new Vector2(0, 0.05f), _player.b2body.getWorldCenter(), true);
} else if(Gdx.input.isKeyPressed(Input.Keys.DOWN) && _player.b2body.getLinearVelocity().y >= -0.5f) {
_player.b2body.applyLinearImpulse(new Vector2(0, -0.05f), _player.b2body.getWorldCenter(), true);
} else if(Gdx.input.isKeyPressed(Input.Keys.UP) == Gdx.input.isKeyPressed(Input.Keys.DOWN)){          _player.b2body.setLinearVelocity(_player.b2body.getLinearVelocity().x, 0f);
}

更新(float dt)方法

handleInput(dt);
_player.update(dt);
_follower.update(dt, _player.b2body.getPosition());
_follower1.update(dt, _follower.b2body.getPosition());
_follower2.update(dt, _follower1.b2body.getPosition());

渲染(浮动增量)方法

game.batch.begin();
_follower2.draw(game.batch);
_follower1.draw(game.batch);
_follower.draw(game.batch);
_player.draw(game.batch);
game.batch.end();

dispose() 方法

_player.dispose();
_follower.dispose();
_follower1.dispose();
_follower2.dispose();

现在,在我的角色 class 中,使用 update(float dt, Vector2 position) 方法

if ((position.x - b2body.getPosition().x) > (15 /PhantasyStar.PPM)) {
            b2body.setLinearVelocity(new Vector2(0.5f, 0));

} else if ((position.x - b2body.getPosition().x) < ( - 15 /PhantasyStar.PPM)) {
            b2body.setLinearVelocity(new Vector2(-0.5f, 0));

} else if ((position.y - b2body.getPosition().y) > (15 / PhantasyStar.PPM)) {
            b2body.setLinearVelocity(new Vector2(0, 0.5f));

} else if ((position.y - b2body.getPosition().y) < (-15 / PhantasyStar.PPM)) {
            b2body.setLinearVelocity(new Vector2(0, -0.5f));

} else if (((position.y - b2body.getPosition().y) <= (15 / PhantasyStar.PPM) && (position.y - b2body.getPosition().y) >= (-15 / PhantasyStar.PPM)) || ((position.x - b2body.getPosition().x) <= (15 /PhantasyStar.PPM) && (position.x - b2body.getPosition().x) >= (-15 /PhantasyStar.PPM)) ) {
            b2body.setLinearVelocity(new Vector2(0, 0));
         }

setPosition(b2body.getPosition().x - getWidth() / 2, b2body.getPosition().y - getHeight() / 4);

setRegion(getFrame(dt));

这段代码给了我一个很好的结果,例如,如果我只在 x 轴或只在 y 轴上行走,玩家们就会按照我需要的方式行走,彼此之间的距离正确,并且返回时也正确,但是如果我开始上下移动,他们就会开始互相跟随,但每次我发现障碍时,一些追随者就会卡住。所以我希望他们完全按照主角的路线走。

我 100% 认为我所做的是不正确的,但我试图为此找到一些文献,但没有找到。我相信如果我找到一种方法来获得主要玩家的最后位置并使其成为第二个目标。

我尝试在将玩家位置更新为最后一个位置后收集并用于随从的下一次更新,但是,即使我要求随从跟随该位置,它也太接近了,所以我假设这不是正确的收集位置,或者可能是另一种收集方式。我是否需要创建一个数组来收集所有位置并将此信息延迟传递给其他角色?

有没有更有游戏开发经验的人来帮帮我?

在 PlayScreen 上 Class 创建 2 个数组变量。这两个数组将收集主要玩家的位置和状态。

public class PlayScreen implements Screen {
private Array<Vector2> _playerPath;
private Array<Alis.State> _playerState;
}

在 PlayScreen Constructor 上,我初始化了 Arrays,所以在 .get 和 .set 之后就可以工作了。

public PlayScreen(PhantasyStar game, MapManager mapManager){

//starting Array for player path and state
_playerPath = new Array<Vector2>(100);
_playerState = new Array<Alis.State>(100);
for(int k=0;k<100;k++) {
_playerPath.add(new Vector2(0f, 0f));
_playerState.add(Alis.State.STANDING_DOWN);
}
//Create Player
_player = new Alis(world, this, mapManager);
_follower = new Myau(world, this, mapManager);
_follower1 = new Odin(world, this, mapManager);
_follower2 = new Noah(world, this, mapManager);
}

仍在 PlayScreen Class,更新方法。每个位置和每个状态都在数组内更新,为跟随者创建路径。我更新了每个延迟 20 帧的关注者更新方法。

public void update(float dt){

//start ***Items for the following path***

 for (int i = 99; i > 0; i--) {
    _playerPath.get(i).set(_playerPath.get(i - 1));
    _playerState.set(i,_playerState.get(i - 1));
 }
    _playerPath.get(0).set(_player.b2body.getPosition());
    _playerState.set(0, _player.currentState);

handleInput(dt);

world.step(1/60f, 6, 2);

_player.update(dt);

_follower.update(dt, _playerPath.get(20), _playerState.get(20));

_follower1.update(dt, _playerPath.get(40), _playerState.get(40));

_follower2.update(dt, _playerPath.get(60), _playerState.get(60));
// end ***Items for the following path ***


        gamecam.position.x = _player.b2body.getPosition().x;
        gamecam.position.y = _player.b2body.getPosition().y;

//removing the blank spaces in the borders stopping the camera
xOffset = (gamecam.position.x - PhantasyStar.V_WIDTH / PhantasyStar.PPM / 2);
xOffsetRight = (mapManager.getMapWidth() / PhantasyStar.PPM) - gamecam.position.x - (PhantasyStar.V_WIDTH / PhantasyStar.PPM / 2);

yOffset = (gamecam.position.y - (PhantasyStar.V_HEIGHT / PhantasyStar.PPM / 2));
yOffsetUp = (mapManager.getMapHeight() / PhantasyStar.PPM) - gamecam.position.y - (PhantasyStar.V_HEIGHT / PhantasyStar.PPM / 2);

if(xOffset < 0)
gamecam.position.x = PhantasyStar.V_WIDTH / PhantasyStar.PPM / 2;
if(xOffsetRight < 0)
gamecam.position.x = (mapManager.getMapWidth() / PhantasyStar.PPM) - (PhantasyStar.V_WIDTH / PhantasyStar.PPM / 2);

if(yOffset < 0)
gamecam.position.y = PhantasyStar.V_HEIGHT / PhantasyStar.PPM / 2;
if(yOffsetUp < 0)
gamecam.position.y = (mapManager.getMapHeight() / PhantasyStar.PPM) - (PhantasyStar.V_HEIGHT / PhantasyStar.PPM / 2);       
// end removing blank spaces

//portal contact
 if(isCollided) {
   updateMap();
 }

 gamecam.update();
 renderer.setView(gamecam);
 }

下一个代码是 Follower Class,使用数组中的位置和状态。

public TextureRegion getFrame(float dt, Alis.State state) {

        currentState = getState(state);

        TextureRegion region;

        switch (currentState) {
            case RUN_UP:
                region = myauRun_Up.getKeyFrame(stateTimer, true);
                break;
            case RUN_DOWN:
                region = myauRun_Down.getKeyFrame(stateTimer, true);
                break;
            case RUN_RIGHT:
                region = myauRun_Right.getKeyFrame(stateTimer, true);
                break;
            case RUN_LEFT:
                region = myauRun_Left.getKeyFrame(stateTimer, true);
                break;
            case STANDING_UP:
                region = myauStand_Up;
                break;
            case STANDING_RIGHT:
                region = myauStand_Right;
                break;
            case STANDING_LEFT:
                region = myauStand_Left;
                break;

            case STANDING_DOWN:
            default:
                region = myauStand_Down;
                break;

        }
        stateTimer = currentState == previousState ? stateTimer + dt : 0;
        previousState = currentState;
        return region;
    }

    public State getState(Alis.State state) {

        if (state == Alis.State.RUN_UP)
            return State.RUN_UP;
        else if (state == Alis.State.RUN_DOWN)
            return State.RUN_DOWN;
        else if (state == Alis.State.RUN_RIGHT)
            return State.RUN_RIGHT;
        else if (state == Alis.State.RUN_LEFT)
            return State.RUN_LEFT;
        else if (state == Alis.State.STANDING_UP)
            return State.STANDING_UP;
        else if (state == Alis.State.STANDING_LEFT)
            return State.STANDING_LEFT;
        else if (state == Alis.State.STANDING_DOWN)
            return State.STANDING_DOWN;
        else
            return State.STANDING_DOWN;

    }

    public void update(float dt, Vector2 position, Alis.State state) {

        setPosition(position.x - getWidth() / 2, position.y - getHeight() / 4);

        setRegion(getFrame(dt, state));

    }

希望这对其他人有帮助