touch scrolling with libgdx

这一生的挚爱 提交于 2019-12-21 19:59:07

问题


I'm trying to implement touch scrolling in a libgdx game. I have a wide image that is a panorama of a room. I want to be able to scroll the image so the user can see around the room. I have it so that I can scroll a certain distance but when a new touchDragged event is registered the image is moved back to the original position.

This is how I'm implementing it

public class AttackGame implements ApplicationListener {

AttackInputProcessor inputProcessor;
Texture backgroundTexture; 
TextureRegion region;
OrthographicCamera cam;
SpriteBatch batch;
float width;
float height;
float posX;
float posY;

@Override
public void create() {
    posX = 0;
    posY = 0;
    width = Gdx.graphics.getWidth();
    height = Gdx.graphics.getHeight();  
    backgroundTexture = new Texture("data/pancellar.jpg");
    region = new TextureRegion(backgroundTexture, 0, 0, width, height);
    batch = new SpriteBatch();

}

@Override
public void resize(int width, int height) {
    cam = new OrthographicCamera();
    cam.setToOrtho(false, width, height);
    cam.translate(width / 2, height / 2, 0);
    inputProcessor = new AttackInputProcessor(width, height, cam);
    Gdx.input.setInputProcessor(inputProcessor);

}

@Override
public void render() {

    Gdx.gl.glClearColor(0,0,0,1);
    Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);    
    batch.setProjectionMatrix(cam.combined);
    batch.begin();
    batch.draw(backgroundTexture, 0, 0, 2400, 460);
    batch.end();

}

@Override
public void pause() {
    // TODO Auto-generated method stub

}

@Override
public void resume() {
    // TODO Auto-generated method stub

}

@Override
public void dispose() {
    backgroundTexture.dispose();

}

}

And in the InputProcessor

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

    cam.position.set(screenX, posY / 2, 0);
    cam.update();
    return false;
}

I got this far with help from this question LibGdx How to Scroll using OrthographicCamera?. However it doesn't really solve my problem.

I think the problem is with the touchDragged corodinates not being world coordinates but I have tried unprojecting the camera with no effect.

I have been struggling with this for a few weeks and I would really appreciate some help on this.

Thanks in advance.


回答1:


I recently did something as what you want. This is my Input class that I use for move the map, you only need to change my 'stage.getCamera()' for your 'cam':

public class MapInputProcessor implements InputProcessor {
    Vector3 last_touch_down = new Vector3();

    ...

    public boolean touchDragged(int x, int y, int pointer) {
        moveCamera( x, y );     
        return false;
    }

    private void moveCamera( int touch_x, int touch_y ) {
        Vector3 new_position = getNewCameraPosition( touch_x, touch_y );

        if( !cameraOutOfLimit( new_position ) )
            stage.getCamera().translate( new_position.sub( stage.getCamera().position ) );

        last_touch_down.set( touch_x, touch_y, 0);
    }

    private Vector3 getNewCameraPosition( int x, int y ) {
        Vector3 new_position = last_touch_down;
        new_position.sub(x, y, 0);
        new_position.y = -new_position.y;
        new_position.add( stage.getCamera().position );

        return new_position;
    }

    private boolean cameraOutOfLimit( Vector3 position ) {
        int x_left_limit = WINDOW_WIDHT / 2;
        int x_right_limit = terrain.getWidth() - WINDOW_WIDTH / 2;
        int y_bottom_limit = WINDOW_HEIGHT / 2;
        int y_top_limit = terrain.getHeight() - WINDOW_HEIGHT / 2;

        if( position.x < x_left_limit || position.x > x_right_limit )
            return true;
        else if( position.y < y_bottom_limit || position.y > y_top_limit )
            return true;
        else
          return false;
}


    ...
}

This is the result: http://www.youtube.com/watch?feature=player_embedded&v=g1od3YLZpww




回答2:


You need to do a lot more computation in the touchDragged callback, you can't just pass whatever screen coordinates were touched on to the camera. You need to figure out how far the user has dragged their finger, and in what direction. The absolute coordinates are not immediately useful.

Consider dragging down from the top-right or dragging down from the top-left. In both cases you want (I presume) to move the camera the same distance, but the absolute values of the screen coordinates will be very different in the two cases.

I think the simplest thing is to just track previousX and previousY (initialize them in the touchDown method. Then invoke cam.translate() with the delta (deltaX = screenX - previousX, for example), during touchDragged. And also update the previous* in touchDragged.

Alternatively, you can look at some of the fancier InputProcessor wrappers libgdx provides (see https://code.google.com/p/libgdx/wiki/InputGestureDetection).




回答3:


Simple answer:

Declare 2 fields to hold the new and old drag location:

Vector2 dragOld, dragNew;

When just touched you set both of these equal to the touched location or your cam will jump.

if (Gdx.input.justTouched())
{
    dragNew = new Vector2(Gdx.input.getX(), Gdx.input.getY());
    dragOld = dragNew;
}

Update dragNew each frame and simply subtract the vectors from each other to get the x and y for translating the camera.

if (Gdx.input.isTouched())
    {
        dragNew = new Vector2(Gdx.input.getX(), Gdx.input.getY());
        if (!dragNew.equals(dragOld))
        {
            cam.translate(dragOld.x - dragNew.x, dragNew.y - dragOld.y); //Translate by subtracting the vectors
            cam.update();
            dragOld = dragNew; //Drag old becomes drag new.
        }
    }

This is all I use to drag my ortho cam around, simple and effective.




回答4:


Used drinor's answer but added the line on "touchDown) function so it doesn't reset the camera every time you start dragging again:

@Override
        public boolean touchDown(int screenX, int screenY, int pointer, int button) {
            last_touch_down.set( screenX, screenY, 0);
            return false;
        }



回答5:


I have not used it myself, but I would start by looking at the code of:

Have you looked at the code of http://libgdx.l33tlabs.org/docs/api/com/badlogic/gdx/scenes/scene2d/ui/FlickScrollPane.html

See: touchDragged



来源:https://stackoverflow.com/questions/15115282/touch-scrolling-with-libgdx

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!