OpenGL-es通过纹理移动相机

时间:2016-11-28 13:29:24

标签: android opengl-es

我有一个小迷宫游戏。它看起来像这样:http://i.imgur.com/VEy54Lc.png

然而,我无法想象如何不允许相机移动框

这是代码:

public class EulerCameraTest extends GLGame {

//@Override
public Screen getStartScreen() {
    return new EulerCameraScreen(this);
}

class EulerCameraScreen extends GLScreen {      
    Texture crateTexture;       
    Vertices3 cube;
    PointLight light;
    AmbientLight aLight;
    EulerCamera camera;
    Texture buttonTexture;
    SpriteBatcher batcher;
    Camera2D guiCamera;
    TextureRegion buttonRegion;
    Vector2 touchPos;
    float lastX = -1;
    float lastY = -1;

    public EulerCameraScreen(Game game) {
        super(game);    

        crateTexture = new Texture(glGame, "crate.png", true);
        cube = createCube();
        light = new PointLight();
        light.setPosition(3, 3, -3);
        aLight = new AmbientLight();
        aLight.setColor(128, 128, 128, 255);
        camera = new EulerCamera(67, glGraphics.getWidth() / (float)glGraphics.getHeight(), 0.1f, 100);
        camera.getPosition().set(0, 0, 3);

        buttonTexture = new Texture(glGame, "button.png");
        batcher = new SpriteBatcher(glGraphics, 1);
        guiCamera = new Camera2D(glGraphics, 480, 320);
        buttonRegion = new TextureRegion(buttonTexture, 0, 0, 64, 64);
        touchPos = new Vector2();
    }

     private Vertices3 createCube() {
            float[] vertices = { -0.5f, -0.5f, 0.5f, 0, 1, 0, 0, 1,
                                  0.5f, -0.5f, 0.5f, 1, 1, 0, 0, 1,
                                  0.5f,  0.5f, 0.5f, 1, 0, 0, 0, 1,
                                 -0.5f,  0.5f, 0.5f, 0, 0, 0, 0, 1,

                                  0.5f, -0.5f,  0.5f, 0, 1, 1, 0, 0,
                                  0.5f, -0.5f, -0.5f, 1, 1, 1, 0, 0,
                                  0.5f,  0.5f, -0.5f, 1, 0, 1, 0, 0,
                                  0.5f,  0.5f,  0.5f, 0, 0, 1, 0, 0,

                                  0.5f, -0.5f, -0.5f, 0, 1, 0, 0, -1,
                                 -0.5f, -0.5f, -0.5f, 1, 1, 0, 0, -1,
                                 -0.5f,  0.5f, -0.5f, 1, 0, 0, 0, -1,
                                  0.5f,  0.5f, -0.5f, 0, 0, 0, 0, -1,

                                 -0.5f, -0.5f, -0.5f, 0, 1, -1, 0, 0,
                                 -0.5f, -0.5f,  0.5f, 1, 1, -1, 0, 0,
                                 -0.5f,  0.5f,  0.5f, 1, 0, -1, 0, 0,
                                 -0.5f,  0.5f, -0.5f, 0, 0, -1, 0, 0,

                                 -0.5f,  0.5f,  0.5f, 0, 1, 0, 1, 0,
                                  0.5f,  0.5f,  0.5f, 1, 1, 0, 1, 0,
                                  0.5f,  0.5f, -0.5f, 1, 0, 0, 1, 0,
                                 -0.5f,  0.5f, -0.5f, 0, 0, 0, 1, 0,

                                 -0.5f, -0.5f, -0.5f, 0, 1, 0, -1, 0,
                                  0.5f, -0.5f, -0.5f, 1, 1, 0, -1, 0,
                                  0.5f, -0.5f,  0.5f, 1, 0, 0, -1, 0,
                                 -0.5f, -0.5f,  0.5f, 0, 0, 0, -1, 0 };
            short[] indices = { 0, 1, 2, 2, 3, 0,
                                4, 5, 6, 6, 7, 4,
                                8, 9, 10, 10, 11, 8,
                                12, 13, 14, 14, 15, 12,
                                16, 17, 18, 18, 19, 16,
                                20, 21, 22, 22, 23, 20,
                                24, 25, 26, 26, 27, 24 };
            Vertices3 cube = new Vertices3(glGraphics, vertices.length / 8, indices.length, false, true, true);
            cube.setVertices(vertices, 0, vertices.length);
            cube.setIndices(indices, 0, indices.length);
            return cube;
        }

    //@Override
    public void resume() {  
        crateTexture.reload();
    }

    //@Override
    public void update(float deltaTime) {
        game.getInput().getTouchEvents();
        float x = game.getInput().getTouchX(0);
        float y = game.getInput().getTouchY(0);
        guiCamera.touchToWorld(touchPos.set(x, y));


        if(game.getInput().isTouchDown(0)) {
            if(touchPos.x < 64 && touchPos.y < 64) {
                Vector3 direction = camera.getDirection();
                direction.y = 0;
                camera.getPosition().add(direction.mul(deltaTime));
            } else {    
                if(lastX == -1) {
                    lastX = x;
                    lastY = y;

                } else {                            
                    camera.rotate((x - lastX) / 10, (y - lastY) / 10);                  
                    lastX = x;
                    lastY = y;
                }
            }
        } else { 
            lastX = -1;
            lastY = -1;
        }
    }

    //@Override
    public void present(float deltaTime) {
        GL10 gl = glGraphics.getGL();           
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        gl.glViewport(0, 0, glGraphics.getWidth(), glGraphics.getHeight());

        camera.setMatrices(gl);

        gl.glEnable(GL10.GL_DEPTH_TEST);
        gl.glEnable(GL10.GL_TEXTURE_2D);
        gl.glEnable(GL10.GL_LIGHTING);

        crateTexture.bind();
        cube.bind();        
        light.enable(gl, GL10.GL_LIGHT0);
        aLight.enable(gl);

        int[] matrix = new int[]
                {0,0,0,1,0,
                 0,1,1,1,0,
                 0,1,0,0,0
        };
        int step = 0;
        for(int z = 0; z >= -4/2; z-=2/2)
        {
            for(int x = -4/2; x <=4/2; x+=2/2 )
            {
                if(matrix[step++] == 1)
                    continue;
                gl.glPushMatrix();
                gl.glTranslatef(x, 0, z);
                cube.draw(GL10.GL_TRIANGLES, 0, 6 * 2 * 3);
                gl.glPopMatrix();
            }
        }

        cube.unbind();

        gl.glDisable(GL10.GL_LIGHTING);
        gl.glDisable(GL10.GL_DEPTH_TEST);           

        gl.glEnable(GL10.GL_BLEND);
        gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

        guiCamera.setViewportAndMatrices();
        batcher.beginBatch(buttonTexture);
        batcher.drawSprite(32, 32, 64, 64, buttonRegion);
        batcher.endBatch();

        gl.glDisable(GL10.GL_BLEND);
        gl.glDisable(GL10.GL_TEXTURE_2D);
    }
}   
}

我相信now()方法是我应该查看的地方。有没有人知道如何让相机无法通过盒子走路?

1 个答案:

答案 0 :(得分:0)

我相信update(float deltaTime)是您应该关注的地方。如果相机不应该通过盒子,那么你不应该在打开盒子时移动它。您需要创建一个良好的系统来控制场景周围的移动,并可能将某些值转换为场景坐标系。更一般地说,你应该将物理引擎与图形引擎分开。

考虑您有一个代表您的场景的对象,并且包含以下数据:

int width; // The width of the scene
int height; // The height of the scene
bool boxes[width][height]; // The grid of boxes. If the segment is true then a box should be drawn
float playerPositionX;
float playerPositionY;

现在你的绘制方法看起来像:

for(int x = 0; x < scene.width; x++)
        {
            for(int y = 0; y < scene.height; y++)
            {
                if(!scene.boxes[y][x])
                    continue;
                gl.glPushMatrix();
                gl.glTranslatef(x*sceneScale, 0, y*sceneScale); // Scene scale is just some constant to make things as large as you want (a box size most likely in your case).
                cube.draw(GL10.GL_TRIANGLES, 0, 6 * 2 * 3);
                gl.glPopMatrix();
            }
        }

但是在你的update方法上,你宁愿简单地称之为:

scene.movePlayer(x, y);

所以场景有一个方法

public void movePlayer(float x, float y) {
    // first get the current position indices:
    int previousX = (int)playerPositionX;
    int previousY = (int)playerPositionY;

    // And the target position:
    int targetX = (int)(playerPositionX+x);
    int targetY = (int)(playerPositionY+y);

    // Now check if you have collisions
    if(targetX < 0 || targetX >= width || boxes[targetX][previousY]) { // The previousY is NOT a bug
        // We hit the wall in X direction so do not move it
        x = .0f;
    }
    if(targetY < 0 || targetY >= height || boxes[previousX][targetY]) { // The previousX is NOT a bug
        // We hit the wall in Y direction so do not move it
        y = .0f;
    }

    playerPositionX += x;
    playerPositionY += y;
}

现在你需要在update中做的就是根据场景播放器的位置设置相机位置(再次应用你需要的任何因素,如场景比例)。