box2d + scene2d the actor does not behave naturally

Anything libgdx related goes here!

box2d + scene2d the actor does not behave naturally

Postby TruePlayer » Tue Sep 03, 2019 12:33 pm

I’ve watched and tested a lot, I also tried debugging, but I can’t find the reason. I do everything according to official documentation.
I have a summer and a sprite that I want to combine with the size of the actor. In class, the ball is completely successful. But there is no player in the class.
Code: Select all
public Player(World world) {
        super(world);
        setBounds(320/2 - getWidth()/2, 480/3f-getHeight()/2, 64, 64);

        CircleShape shape = new CircleShape();
        shape.setRadius(32);
        createBody(shape, BodyDef.BodyType.KinematicBody);
        body.setUserData("player");

        sprite = Resource.player;
        sprite.setBounds(0, 0, 64, 64);
    }

    @Override
    public void act(float delta) {
        sprite.setOriginCenter();
        sprite.setPosition(body.getPosition().x - sprite.getWidth()/2,
                           body.getPosition().y - sprite.getHeight()/2);
        body.setTransform(this.getX(), this.getY(), 0);
    }

if you take such a code, then when debugging it is clear that the position of the actor is positioned offset to the position of the body(Yes, I know that the actor is drawn from the initial angle, and the body from the middle):
Image


as soon as I add the setPosition line to the act method (to shift the position of the actor) I get the expected shift of the actor, but then the actor, sprite and body go down and to the side. I recorded a video to show what is going on:
Code: Select all
    @Override
    public void act(float delta) {
        sprite.setOriginCenter();
        sprite.setPosition(body.getPosition().x - sprite.getWidth()/2,
                           body.getPosition().y - sprite.getHeight()/2);
        body.setTransform(this.getX(), this.getY(), 0);
        setPosition(body.getPosition().x-getWidth()/2,body.getPosition().y-getHeight()/2); <= this
}

while my second class ball works the way I want.

Video: https://www.youtube.com/watch?v=hAh1gw5oXE8




full codes
Code: Select all
public class Player extends ActorObject {


    public Player(World world) {
        super(world);
        setBounds(320/2 - getWidth()/2, 480/3f-getHeight()/2, 64, 64);

        CircleShape shape = new CircleShape();
        shape.setRadius(32);
        createBody(shape, BodyDef.BodyType.KinematicBody);
        body.setUserData("player");

        sprite = Resource.player;
        sprite.setBounds(0, 0, 64, 64);
    }

    @Override
    public void act(float delta) {
        sprite.setOriginCenter();
        sprite.setPosition(body.getPosition().x - sprite.getWidth()/2,
                           body.getPosition().y - sprite.getHeight()/2);
        body.setTransform(this.getX(), this.getY(), 0);
        setPosition(body.getPosition().x-getWidth()/2,body.getPosition().y-getHeight()/2);
    }
}


Code: Select all
public class Ball extends ActorObject {


    public Ball(World world) {
        super(world);
        setBounds(320/2 - getWidth()/2, 450, 32, 32);

        CircleShape shape = new CircleShape();
        shape.setRadius(16);
        createBody(shape, BodyDef.BodyType.DynamicBody);
        body.setUserData("ball");

        sprite = Resource.ball;
        sprite.setBounds(getX(), getY(), 32, 32);
    }

    @Override
    public void act(float delta) {
        sprite.setOriginCenter();
        sprite.setRotation(MathUtils.radiansToDegrees * body.getAngle());
        sprite.setPosition(body.getPosition().x-getWidth()/2,
                           body.getPosition().y-getHeight()/2);
        setPosition(body.getPosition().x-getWidth()/2,
                    body.getPosition().y-getHeight()/2);
    }
}


Code: Select all
public class GameView extends GameState implements Screen, GestureDetector.GestureListener, InputProcessor {

    private float CAMERA_WIDTH;
    private float CAMERA_HEIGHT;
    private float ASPECT_RATIO;
    private Viewport viewPort;

    private long toched;

    private World world;
    private Player player;
    private Ball ball;

    private Box2DDebugRenderer rend;

    private Stage stage;

    public GameView(GameStateManager gsm) {
        super(gsm);
        CAMERA_WIDTH = game.getWeight();
        CAMERA_HEIGHT = game.getHeight();
        ASPECT_RATIO = gsm.getWeight() / gsm.getHeight();
        viewPort = new FillViewport(CAMERA_WIDTH,CAMERA_WIDTH/ASPECT_RATIO);
        this.camera.setToOrtho(true, CAMERA_WIDTH, CAMERA_WIDTH / ASPECT_RATIO);
        this.camera.position.set(new Vector3(CAMERA_WIDTH / 2f, (CAMERA_WIDTH / ASPECT_RATIO) / 2f, 0));
    }

    @Override//вызывается при переключении на этот экран
    public void show() {
        Resource.load();

        world = new World(new Vector2(0, -100), true);
        world.setContactListener(new MyListener());
        player = new Player(world);
        ball = new Ball(world);
        rend =  new  Box2DDebugRenderer ();


        stage = new Stage(viewPort);
        stage.addActor(new Background(world));
        stage.addActor(new Ground(world));
        stage.addActor(player);
        stage.addActor(ball);
        stage.addListener(new InputListener() {
            @Override
            public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
                if (toched + 200 > System.currentTimeMillis()) {
                    gsm.setState(0);
                } else {
                    toched = System.currentTimeMillis();
                }
                player.setPosition(x, y);
                return true;
            }
            @Override
            public void touchDragged(InputEvent event, float x, float y, int pointer) {
                player.setPosition(x, y);
                super.touchDragged(event, x, y, pointer);
            }
            @Override
            public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
                super.touchUp(event, x, y, pointer, button);
            }
        });
        stage.setDebugAll(true);

        InputMultiplexer im = new InputMultiplexer();
        GestureDetector gd = new GestureDetector(this);
        im.addProcessor(stage);
        im.addProcessor(gd);
        im.addProcessor(this);
        Gdx.input.setInputProcessor(im);
    }

    @Override// delta - время между кадрами в секунду
    public void render(float delta) {
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        world.step(1/60f, 6,2);//в идеале делить на FPS
        stage.act(delta);
        stage.draw();
        rend.render(world,stage.getCamera().combined);
    }

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

    }
    @Override
    public void resume() {

    }
    @Override
    public void hide() {

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



    @Override
    public boolean keyDown(int keycode) {
        return false;
    }
    @Override
    public boolean keyUp(int keycode) {
        return false;
    }
    @Override
    public boolean keyTyped(char character) {
        return false;
    }
    @Override
    public boolean touchDown(int screenX, int screenY, int pointer, int button) {
        return false;
    }

    @Override
    public boolean touchUp(int screenX, int screenY, int pointer, int button) {
        return false;
    }
    @Override
    public boolean touchDragged(int screenX, int screenY, int pointer) {
        return false;
    }
    @Override
    public boolean mouseMoved(int screenX, int screenY) {
        return false;
    }
    @Override
    public boolean scrolled(int amount) {
        return false;
    }
    @Override
    public boolean touchDown(float x, float y, int pointer, int button) {
        return false;
    }
    @Override
    public boolean tap(float x, float y, int count, int button) {
        return false;
    }
    @Override
    public boolean longPress(float x, float y) {
        return false;
    }
    @Override
    public boolean fling(float velocityX, float velocityY, int button) {
        return false;
    }
    @Override
    public boolean pan(float x, float y, float deltaX, float deltaY) {
        return false;
    }
    @Override
    public boolean panStop(float x, float y, int pointer, int button) {
        return false;
    }
    @Override
    public boolean zoom(float initialDistance, float distance) {
        return false;
    }
    @Override
    public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2) {
        return false;
    }
    @Override
    public void pinchStop() {

    }
}
TruePlayer
 
Posts: 103
Joined: Sun Jul 28, 2019 12:22 pm

Re: box2d + scene2d the actor does not behave naturally

Postby shatterblast » Tue Sep 03, 2019 4:29 pm

In your video, does the "bug" involve the player picture sweeping down to the bottom-left every time it moves?
shatterblast
 
Posts: 414
Joined: Sun Jul 06, 2014 1:14 pm

Re: box2d + scene2d the actor does not behave naturally

Postby TruePlayer » Tue Sep 03, 2019 5:31 pm

Yes! before adding the setPosition function, my player moves and stops at the place of finger touch, after adding the setPosition function my player goes down the screen, this is not normal!
TruePlayer
 
Posts: 103
Joined: Sun Jul 28, 2019 12:22 pm

Re: box2d + scene2d the actor does not behave naturally

Postby shatterblast » Tue Sep 03, 2019 6:27 pm

You will very likely need to tweak the math in the code I present and maybe the order of it, but this general format should help fix your issue I think. Please, tell me if the image keeps sweeping to the bottom-left once things work. I wonder if setPosition() is accidentally getting called twice on the same thing from inheritance. If so, another possible fix would involve temporarily removing sprite.setPosition() to see what happens.

Code: Select all
@Override
public void act(float delta) {

        sprite.setOriginCenter();

        body.setTransform( this.getX(), this.getY(), 0 );

        int xPosition = body.getPosition().x - getWidth() / 2;
        int yPosition = body.getPosition().y - getHeight() / 2;

        sprite.setPosition( xPosition, yPosition );

        setPosition( xPosition, yPosition ); <= this

    }
Last edited by shatterblast on Tue Sep 03, 2019 6:33 pm, edited 1 time in total.
shatterblast
 
Posts: 414
Joined: Sun Jul 06, 2014 1:14 pm

Re: box2d + scene2d the actor does not behave naturally

Postby TruePlayer » Tue Sep 03, 2019 6:32 pm

you gave a code that differs from mine only in variables) I inserted it for the test, the error did not disappear, the player also goes down!
TruePlayer
 
Posts: 103
Joined: Sun Jul 28, 2019 12:22 pm

Re: box2d + scene2d the actor does not behave naturally

Postby shatterblast » Tue Sep 03, 2019 6:34 pm

Just to repeat:
I wonder if setPosition() is accidentally getting called twice on the same thing from inheritance. If so, another possible fix would involve temporarily removing sprite.setPosition() to see what happens.
shatterblast
 
Posts: 414
Joined: Sun Jul 06, 2014 1:14 pm

Re: box2d + scene2d the actor does not behave naturally

Postby shatterblast » Tue Sep 03, 2019 6:44 pm

Assuming that does not fix anything, the next step involves temporarily removing touchUp() from your InputListener in your GameView class. The below code should give an idea. I just commented out the touchUp() block. This is because Ball works fine in your code, but your input for your Player does not. Basically, I believe your game accepts two methods for input at the same time, which can happen with listeners.

Code: Select all
stage.addListener(new InputListener() {
        @Override
        public boolean touchDown(InputEvent event, float x,
                float y, int pointer, int button) {

                    if (toched + 200 > System.currentTimeMillis()) {
                        gsm.setState(0);
                    } else {
                        toched = System.currentTimeMillis();
                    }
                    player.setPosition(x, y);
                    return true;

                }

            @Override
            public void touchDragged(InputEvent event, float x, float y, int pointer) {

                player.setPosition(x, y);
                super.touchDragged(event, x, y, pointer);

            }

                /*           
                @Override
                public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
                    super.touchUp(event, x, y, pointer, button);
                */

        }
});
shatterblast
 
Posts: 414
Joined: Sun Jul 06, 2014 1:14 pm

Re: box2d + scene2d the actor does not behave naturally

Postby TruePlayer » Tue Sep 03, 2019 7:00 pm

TouchDown code is needed for TouchDragged so that the player follows the movement of the finger
TruePlayer
 
Posts: 103
Joined: Sun Jul 28, 2019 12:22 pm

Re: box2d + scene2d the actor does not behave naturally

Postby shatterblast » Tue Sep 03, 2019 7:03 pm

"touchUp()", not touchDown().
shatterblast
 
Posts: 414
Joined: Sun Jul 06, 2014 1:14 pm

Re: box2d + scene2d the actor does not behave naturally

Postby TruePlayer » Tue Sep 03, 2019 7:11 pm

I tried to remove TouchUp it did not work

it’s strange that you give this advice, these things are not related
TruePlayer
 
Posts: 103
Joined: Sun Jul 28, 2019 12:22 pm

Next

Return to Libgdx

Who is online

Users browsing this forum: MSN [Bot] and 1 guest