プレイヤーの動きに合わせてカメラを移動させる

↑の状態、

プレイヤーの歩く動きに合わせてカメラが移動しているように見えるが、

カメラがマス単位(このゲームだと32dot)移動→そのあとにプレイヤーがドット単位で移動 という風になってしまっています。(カメラの動きがかくかくしてるかんじする。)

今回はこれを改善します。

関連記事

http://snoopopo.hatenablog.com/entry/2015/07/26/145013

http://snoopopo.hatenablog.com/entry/2015/07/16/170043

今回は、上記の内容で出来てなかった、アクション実行時もカメラをプレイヤーに合わせることです。

プレイヤーの動きに合わせてカメラを移動させる

移動と攻撃はどちらも、scene2dのActionクラスを使って移動させています。

/**
 * アクションの動きごと追跡するカメラ
 */
public class TrackActionCameraSampleListener extends ApplicationAdapter {

    private Stage stage = null;
    private OrthographicCamera cam; 

    private int cnt = 1;
    private boolean preEnter = false;
    private boolean preDown = false;
    
    private Array<Image> imagelist = null;
    private Image player = null;
    
    private float startPositionWidth;
    private float startPositionHeight;
    
    @Override
    public void create() {
        
        stage = new Stage();
        Gdx.input.setInputProcessor(stage);

        float w = Gdx.graphics.getWidth();
        float h = Gdx.graphics.getHeight();
            
        cam = (OrthographicCamera) stage.getViewport().getCamera();
        cam.setToOrtho(false, w/2, h/2); //カメラのサイズを画面サイズの半分にしてる
    
        imagelist = new Array<>();
        Texture p = new Texture("player_x0_y0.png");
        player = new Image(p);
        imagelist.add(player);  //ひとつ目
        imagelist.add(new Image(new Texture("player_x1_y0.png")));   //2つ目
        imagelist.add(new Image(new Texture("player_x2_y0.png")));   //3つ目
    
        startPositionWidth = cam.viewportWidth/2 - p.getWidth()/2;
        startPositionHeight = cam.viewportHeight - p.getHeight();
    
        for (Image image : imagelist) {
            image.setPosition(startPositionWidth, startPositionHeight);
            stage.addActor(image);
        }
        
        //移動したのがわかりにくいので、適当に表示
        Texture c = new Texture("enemy2_x0_y0.png");
        Image cat1 = new Image(c);
        cat1.setPosition(startPositionWidth + c.getWidth(), startPositionHeight);
        stage.addActor(cat1);
        
        Texture c2 = new Texture("enemy2_x0_y1.png");
        Image cat2 = new Image(c2);
        cat2.setPosition(startPositionWidth - c2.getWidth(), startPositionHeight - 120);
        stage.addActor(cat2);

        Texture c3 = new Texture("enemy2_x0_y2.png");
        Image cat3 = new Image(c3);
        cat3.setPosition(startPositionWidth + c3.getWidth(), startPositionHeight - 180);
        stage.addActor(cat3);
    }

    @Override
    public void render() {
        Gdx.gl.glClearColor(0, 1, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);   //画面クリア
        
        stage.act(Gdx.graphics.getDeltaTime()); //よばないとアクションが実行されなかった
        
        if (!preDown && Gdx.input.isKeyPressed(Keys.DOWN)) {
            for (Image image : imagelist) {
                image.addAction(Actions.moveBy(0, -100, 2)); //2秒間で100px前に前進
            }
        }
        
        if (!preEnter && Gdx.input.isKeyPressed(Keys.ENTER)) {
            for (Image image : imagelist) {
                SequenceAction seqAct = Actions.sequence();
                seqAct.addAction(Actions.moveBy( 0, player.getHeight() /2 * -1, 0.2F ));
                seqAct.addAction(Actions.moveBy( 0, player.getHeight() /2, 0.2F ));
                image.addAction(Actions.repeat(2, seqAct)); //攻撃っぽい動き
            }
        }
        
        preDown = Gdx.input.isKeyPressed(Keys.DOWN);
        preEnter = Gdx.input.isKeyPressed(Keys.ENTER);
        
        for (Image image : imagelist) {
            image.setVisible(false); //いったん全部を非表示にして
        }

        //今のフレームで表示させる画像だけ表示する
        int rest = cnt % 10;
        if (rest <= 2) {
            imagelist.get(0).setVisible(true);
        } else if (rest <= 6) {
            imagelist.get(1).setVisible(true);
        } else {          
            imagelist.get(2).setVisible(true);
        }
        cnt++;
    
        //カメラの中心をプレイヤーに合わせる
        cam.position.x = player.getX();
        cam.position.y = player.getY();
        
        stage.draw();
    }
    
    @Override
    public void resize(int width, int height) {
        cam.update();
    }

    @Override
    public void dispose() {
        stage.dispose();
    }
}

カメラのポジションにプレイヤーの位置をそのまま設定してあげればよい

カメラのポジションにプレイヤーの位置をそのまま設定してあげればよいだけでした。

       //カメラの中心をプレイヤーに合わせる
        cam.position.x = player.getX();
        cam.position.y = player.getY();

アクションが実行された際に、Actor#getX, Actor#getY でとれる値がちゃんと変わってくれてるわかるので、 この値を直接指定してあげればいきます。

というわけで

上記の内容を作っているゲームに反映させるとこのようになります。

歩行はよさそうですが、攻撃のときもカメラが動いているのでせわしない気もします。(SFC風來のシレンでは、攻撃時にはカメラが動いてないように見える)

歩行のときだけカメラを動かすとか、そのあたりの調整は必要なかんじ。