0
votes

I have an Actor which has set a drag listener:

ballActor.addListener(new DragListener() {
    public void drag(InputEvent event, float x, float y, int pointer) {
        ballActor.moveBy(x - ballActor.getWidth() / 2, y - ballActor.getHeight() / 2);
    }
});

This actor is added to a stage:

W = Gdx.graphics.getWidth();
H = Gdx.graphics.getHeight();
camera = new OrthographicCamera(W / RATE, H / RATE);
stage = new Stage(new ScreenViewport(camera));
stage.addActor(ballActor);
Gdx.input.setInputProcessor(stage);

Now if I use meter to pixel ratio 1:1 the drag works very well but if i use another ratio, like 1:160 the drag event is not firing.

In resize method I update the camera:

camera.viewportHeight = H/RATE;
camera.viewportWidth = W/RATE;
camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
camera.update();

I read that if I use a stage I dont have to translate from screen coordinates to camera coordinates. The actor has set the position, width, height and also bounds. What am I doing wrong?

UPDATE:

Here is the code:

public class Pendulum extends ApplicationAdapter {

    private Stage stage;

    public static final float RATE = 160f; //with 1f..20f drag works

    float W;
    float H;

    @Override
    public void create() {

        W = Gdx.graphics.getWidth() / RATE;
        H = Gdx.graphics.getHeight() / RATE;

        Texture ballTexture = new Texture(Gdx.files.internal("ball.png"), true);
        ballTexture.setFilter(Texture.TextureFilter.MipMapLinearNearest, Texture.TextureFilter.Linear);
        TextureRegion ballRegion = new TextureRegion(ballTexture);

        final Image image = new Image(ballRegion);
        image.setSize(image.getWidth()/RATE, image.getHeight()/RATE);
        image.setPosition(0f, 0f);
        image.addListener(new DragListener() {
            public void drag(InputEvent event, float x, float y, int pointer) {
                Gdx.app.log("LOG", "DRAG IMAGE");
                image.moveBy(x - image.getWidth() / 2, y - image.getHeight() / 2);
            }
        });
        image.debug();
        image.setBounds(image.getX(), image.getY(), image.getWidth(), image.getHeight());

        stage = new Stage(new FitViewport(W, H));
        stage.addActor(image);

        Gdx.input.setInputProcessor(stage);
    }


    @Override
    public void resize(int width, int height) {
        stage.getViewport().update(width, height, true);
    }

    @Override
    public void render() {
        Gdx.gl.glClearColor(1, 1, 1, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        float delta = Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f);
        stage.act(delta);
        stage.draw();
    }

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

I need to have RATE bigger than 100f because Image actor has a Box2D Body attached. See here why.

2

2 Answers

0
votes

When using scene2d, you have to use a Viewport, and a Viewport manages the size of its camera. When you set explicit sizes on the camera, Stage will be confused because it assumes the Viewport is managing the camera (there is a now a mismatch between the world coordinates of the camera and the screen size of the viewport).

I'm not sure how you calculated RATE, but what you should probably be doing is using an ExtendViewport or FitViewport. And in your resize() method, instead of modifying the camera, you need to call update() on your viewport.

0
votes

As I saw your update, I saw, that you increase/decrease the size of your actor, while you increase/decrease the size of your viewport at the same time.

Do the following: give your Viewport a Fixed width/height, that's what it is for.
If you want to use a viewport, you Need to understand the following:
if you have a viewport from 20 * 20, than your WHOLE Screen will be in the size of "20x20".

It's just "imaginary" -- Magic

If you want to get a pretty small Object(for box2d) than you Need to use a small viewport.

So what do we do now? We want that the Screen Shows 20 Units of our game.

So we say new Viewport(20, 20)..

What we do now is, we "map" our 1280/800 to the 20/20.

so, now we can Display our Image. What do we do? we have a meterToPixel Ratio from 160. We have 600x600 Image (width, height) Now we calculate our Ratio on to this(600/160) = 3,75.
AND NOW the Image will fill 3/20 of your Screen.

our Screen is 20x20 and our Image is 3,75.

Short answer: Give your viewport a fixed size(how many Box2d Units(meters)) you want to see, and not a calculated size) and add a new cam to the viewport, or an existing.

OrthographicCamera cam = new OrthographicCamera();
cam.setToOrtho(false, 20,20);
Stage.setViewport(new FitViewport(20,20,cam));