3
\$\begingroup\$

I'm working on a tile based platformer game in libgdx. I'm having trouble getting the actual touch input coordinates when the aspect ratio of device is different from the virtual fixed aspect ratio that I'm working on. I'm using a virtual resolution of 480x800. All the rendering work and camera work is being done in GameRenderer class and the input is being handled in InputHandler class. I've tried implementing the camera.unproject() method but it won't do any good. I've added the unproject method in GameRenderer class since my camera is defined here. Then I've sent the screen touch coords from the InputHandler class to the GameRenderer class and returned the converted coords back to InputHandler.

I'm posting the relevant code from both classes.

GameRenderer:

public class GameRenderer 
{
    public static OrthographicCamera cam;
    private ShapeRenderer shapeRenderer;
    private SpriteBatch batcher;
    private static Player player=GameWorld.getPlayer();

    private static final int VIRTUAL_WIDTH = 800;
    private static final int VIRTUAL_HEIGHT = 480;
    private static final float ASPECT_RATIO = (float)VIRTUAL_WIDTH/(float)VIRTUAL_HEIGHT;
    private Rectangle viewport;
    public static Vector2 crop = new Vector2(0f, 0f); 
    public static float scale = 1f;
    public static int Case=0;
    public static float width;
    public static float height;
    public static float w;
    public static float h;

    public GameRenderer(GameWorld world) 
    {
        cam = new OrthographicCamera();
        cam.setToOrtho(true, 800, 480);
        batcher=new SpriteBatch();
        batcher.setProjectionMatrix(cam.combined);
        shapeRenderer = new ShapeRenderer();
        shapeRenderer.setProjectionMatrix(cam.combined);
    }


    public void render()
    {
        cam.update();
        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

        height=Gdx.graphics.getHeight();
        width=Gdx.graphics.getWidth();

        float aspectRatio = (float)width/(float)height;


        if(aspectRatio > ASPECT_RATIO)
        {
            scale = (float)height/(float)VIRTUAL_HEIGHT;
            crop.x = (width - VIRTUAL_WIDTH*scale)/2f;
            Case=1;
        }
        else if(aspectRatio < ASPECT_RATIO)
        {
            scale = (float)width/(float)VIRTUAL_WIDTH;
            crop.y = (float)(height - VIRTUAL_HEIGHT*scale)/2f;
            Case=2;
        }
        else
        {
            scale = (float)width/(float)VIRTUAL_WIDTH;
        }

        w = (float)VIRTUAL_WIDTH*scale;
        h = (float)VIRTUAL_HEIGHT*scale;


        viewport = new Rectangle(crop.x, crop.y, w, h);

        Gdx.gl.glViewport((int) viewport.x, (int) viewport.y, (int) viewport.width, (int) viewport.height);

        switch(GameWorld.state)
        {
            case Running: renderRunning(); break;
            case GameOver: renderGameOver(); break;
            case Paused: renderPaused(); break;
            default: break;
        }

    }

    public static Vector3 unprojectCoords(Vector3 coords)
    {
        cam.unproject(coords);
        return coords;
    }

}

InputHandler:

public class InputHandler implements InputProcessor 
{

    @Override
    public boolean touchDown(int screenX, int screenY, int pointer, int button) 
    {

        Vector3 coords=new Vector3(screenX,screenY,0);
        Vector3 coords2=GameRenderer.unprojectCoords(coords);

        screenX=(int) coords2.x;
        screenY=(int) coords2.y;

        switch(GameWorld.state)
        {
            case Running:
            {
                if(GameRenderer.jumpButton.isTouchDown((int)screenX, (int)screenY))
                {
                    if(player.isJumped() == false)
                    {
                        player.jump();
                        if(!GameWorld.soundMuted) AssetLoader.jump.play(AssetLoader.SOUND_VOL);
                    }

                }




        return false;
    }

    @Override
    public boolean keyDown(int keycode) 
    {
        switch(GameWorld.state)
        {
            case Running:
            {
                if(keycode==Keys.SPACE)
                {
                    if(player.isJumped() == false)
                    {
                        player.jump();
                        if(!GameWorld.soundMuted) AssetLoader.jump.play(AssetLoader.SOUND_VOL);
                    }
                }

                if(keycode==Keys.LEFT)
                {
                    leftDown=true;
                }

                if(keycode==Keys.RIGHT)
                {
                    rightDown=true;
                }

                if(keycode==Keys.CONTROL_RIGHT)
                {
                    player.shoot();
                }
                break;
            }

            default: break;
        }

        return false;
    }



}
\$\endgroup\$
6
\$\begingroup\$

Try using this Camera:unproject method:

unproject(Vector3 screenCoords, float viewportX, float viewportY, float viewportWidth, float viewportHeight)

from the documentation:

Function to translate a point given in screen coordinates to world space. It's the same as GLU gluUnProject, but does not rely on OpenGL. The x- and y-coordinate of vec are assumed to be in screen coordinates (origin is the top left corner, y pointing down, x pointing to the right) as reported by the touch methods in Input. A z-coordinate of 0 will return a point on the near plane, a z-coordinate of 1 will return a point on the far plane. This method allows you to specify the viewport position and dimensions in the coordinate system expected by GL20.glViewport(int, int, int, int), with the origin in the bottom left corner of the screen.

\$\endgroup\$
  • \$\begingroup\$ Works perfectly! I appreciate your help. \$\endgroup\$ – user48445 Jun 24 '14 at 12:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.