在地图上绘制一个精灵而不是在屏幕上

时间:2013-08-04 04:31:30

标签: java camera sprite libgdx

我正在使用libgdx,我有一个平铺地图,我想绘制精灵。然而精灵被绘制到实际窗口上,所以当我移动相机时,精灵停留在同一个地方。 ?我希望精灵在地图上移动。

这就是我目前渲染我的对象的方式

    @Override
    public void render(float delta) {
        translateCamera();

        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

        camera.update();

        renderer.setView(camera);

        renderer.render(bgLayers);
        batch.begin();

        batch.draw(splayerSprite, Gdx.graphics.getWidth() / 2,
                Gdx.graphics.getHeight() / 2);

        batch.end();
        renderer.render(fgLayers);

    }

它总是最终位于屏幕中间,但是我希望能够像(例如,带有(W,A,S,D)的相机一样将它们分开移动,并使用方向键移动我的播放器。然后,如果我想让相机锁定在播放器上,而其他方面则是免费的。

我是libgdx的新手,所以请耐心等待,谢谢

2 个答案:

答案 0 :(得分:6)

问题是SpriteBatch投影矩阵未设置为Camera投影矩阵。这意味着Sprite未相对于Camera呈现。这就是相机移动的原因,但精灵不是;没有使用正确的矩阵。

此外,精灵的渲染时间始终为屏幕宽度的一半,也是屏幕高度的一半。要修复此致电sprite.draw。这将使用Sprite的内部位置。

通过batch.setProjectionMatrix(camera.combined)设置SpriteBatch投影矩阵。这将导致精灵相对于相机渲染。

@Override
public void render(float delta) {
    translateCamera();

    Gdx.gl.glClearColor(0, 0, 0, 1);
    Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

    camera.update();

    renderer.setView(camera);

    renderer.render(bgLayers);

    //here's the line that was missing.
    batch.setProjectionMatrix(camera.combined);
    batch.begin();

    //be sure to call this instead of specifying position yourself!
    splayerSprite.draw(batch);
    batch.end();
    renderer.render(fgLayers);

}

每当按下WASD时,你仍然需要处理将相机的位置捕捉​​到精灵的位置,但这是微不足道的。

//snap the camera to the sprite's center.
if(wasd_isDown){
    float centerX = sprite.getX()+sprite.getWidth()/2;
    float centerY = sprite.getY()+sprite.getHeight()/2;
    camera.position.set(x,y, 0);
}

如果按下方向键,只需通过Vector3.add翻译相机的位置向量,如下所示:

if(!wasd_isDown){
    float deltaX = 0;
    float deltaY = 0;
    float MOVE_DIST = 10;//or whatever you need.

    if(leftPressed) deltaX = -MOVE_DIST;
    else if(rightPressed) deltaX = MOVE_DIST;

    if(upPressed)deltaY = MOVE_DIST;
    else if(downPressed)deltaY = -MOVE_DIST;

    camera.position.add(deltaX, deltaY, 0);
}

这将允许相机仅在玩家使用方向键时独立移动,并允许相对于相机的方向渲染精灵。当按下WASD时,它还会立即将相机拍摄回精灵。

答案 1 :(得分:2)

batch.draw(splayerSprite, Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2);

您告诉代码每次将其绘制到屏幕中心。您需要将Gdx.graphics.getWidth() / 2Gdx.graphics.getHeight() / 2更改为根据您的输入更改的实际值。

编辑#2 :除了我提到的所有内容之外,还需要行batch.setProjectionmatrix(camera.combined);,我都没有注意到我的代码中已经存在特定行(它包含在默认的libGDX项目),并没有尝试运行我的演示删除该行。我希望能够解决我可能造成的任何困惑。

编辑:因为显然没有人真的喜欢我的答案,所以我使用干净的libGDX游戏中指定的控件编写了一个演示。无论相机瞄准的位置(因为它正在被翻译),精灵都总是在全局屏幕的中心呈现。非常需要在batch.draw()中使用精灵的位置而不是静态位置,否则它将不会移动。

package com.me.mygdxgame;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;

public class MyGdxGame implements ApplicationListener {
    private OrthographicCamera camera;
    private SpriteBatch batch;
    private Texture texture;
    private Sprite sprite;
    private Sprite background;

    private boolean lockToSprite;
    private Vector2 vecCamera;
    private Vector2 vecSprite;

    @Override
    public void create() {      
        float w = Gdx.graphics.getWidth();
        float h = Gdx.graphics.getHeight();

        camera = new OrthographicCamera(w, h);
        batch = new SpriteBatch();

        lockToSprite = true;
        vecCamera = new Vector2();
        vecSprite = new Vector2();

        texture = new Texture(Gdx.files.internal("data/libgdx.png"));
        texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);

        TextureRegion region = new TextureRegion(texture, 0, 0, 512, 275);

        sprite = new Sprite(region);
        sprite.setSize(0.1f * sprite.getWidth(), 0.1f * sprite.getHeight());
        sprite.setOrigin(sprite.getWidth()/2, sprite.getHeight()/2);
        sprite.setPosition(-sprite.getWidth()/2, -sprite.getHeight()/2);

        background = new Sprite(region);
        background.setOrigin(background.getWidth() / 2, background.getHeight() / 2);
        System.out.println(background.getOriginX());
        background.setPosition(-background.getWidth() / 2, -background.getHeight() / 2);
    }

    @Override
    public void dispose() {
        batch.dispose();
        texture.dispose();
    }

    @Override
    public void render() {
        camera.translate(vecCamera);

        Gdx.gl.glClearColor(1, 1, 1, 1);
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

        camera.update();

        camera.translate(vecCamera.cpy().mul(-1));

        float moveSensitivity = 0.9f;

        Vector2 vecInputSprite = new Vector2();
        if (Gdx.input.isKeyPressed(Keys.UP))
            vecInputSprite.y += moveSensitivity;
        if (Gdx.input.isKeyPressed(Keys.DOWN))
            vecInputSprite.y -= moveSensitivity;
        if (Gdx.input.isKeyPressed(Keys.LEFT))
            vecInputSprite.x -= moveSensitivity;
        if (Gdx.input.isKeyPressed(Keys.RIGHT))
            vecInputSprite.x += moveSensitivity;
        if (Gdx.input.isKeyPressed(Keys.N))
            vecSprite.set(new Vector2());

        Vector2 vecInputCamera = new Vector2();
        if (Gdx.input.isKeyPressed(Keys.W))
            vecInputCamera.y += moveSensitivity;
        if (Gdx.input.isKeyPressed(Keys.S))
            vecInputCamera.y -= moveSensitivity;
        if (Gdx.input.isKeyPressed(Keys.A))
            vecInputCamera.x -= moveSensitivity;
        if (Gdx.input.isKeyPressed(Keys.D))
            vecInputCamera.x += moveSensitivity;

        if (Gdx.input.isKeyPressed(Keys.R)) {
            vecCamera.set(new Vector2());
            lockToSprite = false;
        }

        if (vecInputCamera.len2() != 0)
            lockToSprite = false;
        else if (Gdx.input.isKeyPressed(Keys.L))
            lockToSprite = true;

        if (lockToSprite) {
            vecCamera.set(vecSprite);
        } else {
            vecCamera.add(vecInputCamera);
        }

        vecSprite.add(vecInputSprite);

        batch.setProjectionMatrix(camera.combined);
        batch.begin();
        background.draw(batch);
        sprite.setPosition(vecSprite.x, vecSprite.y);
        sprite.draw(batch);
        //batch.draw(sprite, vecSprite.x, vecSprite.y);
        batch.end();
    }

    @Override
    public void resize(int width, int height) {
    }

    @Override
    public void pause() {
    }

    @Override
    public void resume() {
    }
}