0
\$\begingroup\$

Objective: to rotate an image in the center of the screen with movement equal to left or right touchDragged event.

Right now I have a basic Stage that is created and adds an actor (centerMass.png) to the stage. it is created and rendered like this:

public class Application extends ApplicationAdapter {
Stage stageGamePlay;

@Override
public void create () {
    //setup game stage variables
    stageGamePlay = new Stage(new ScreenViewport());
    stageGamePlay.addActor(new CenterMass(new Texture(Gdx.files.internal("centerMass.png"))));

    Gdx.input.setInputProcessor(stageGamePlay);

}

@Override
public void render () {
    Gdx.gl.glClearColor(255f/255, 249f/255, 236f/255, 1f);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    //before drawing, updating actions that have changed
    stageGamePlay.act(Gdx.graphics.getDeltaTime());
    stageGamePlay.draw();

    }
}

I then have a separate class file that contains the CenterMass class, extending Image. I am familiar enough to know I could extend Actor, but I am not sure the benefit I would gain using Actor vs Image.

In the CenterMass class I create the texture, set bounds, set touchable and center it on the screen.

Inside CenterMass class I also have an InputListener listening for events. I have an override set for touchDragged where I am trying to get the X and Y of the drag, and use that to set the rotate actions accordingly. That class looks like this:

//extend Image vs Actor classes
public class CenterMass extends Image {
public CenterMass(Texture centerMassSprite) {
    //let parent be aware
    super(centerMassSprite);
    setBounds(getX(), getY(), getWidth(), getHeight());
    setTouchable(Touchable.enabled);
    setPosition(Gdx.graphics.getWidth()/2, Gdx.graphics.getHeight()/2);
    setRotation(90f);


    addListener(new InputListener(){
        private int dragX, dragY;
        private float duration;
        private float rotateBy = 30f;

        @Override
        public void touchDragged(InputEvent event, float x, float y, int pointer) {
            //get
            float dX = (float)(x-dragX)/(float)Gdx.graphics.getWidth();
            float dY = (float)(dragY-y)/(float)Gdx.graphics.getHeight();

            duration = 1.0f; // 1 second

            Actions.sequence(
                    Actions.parallel(
                            Actions.rotateBy(rotateBy, duration),
                            Actions.moveBy( dX, dY, duration)
                    )
            );


        }
    });
}

@Override
protected void positionChanged() {
    //super.positionChanged();
}

@Override
public void draw(Batch batch, float parentAlpha) {
    //draw needs to be available for changing color and rotation, I think
    batch.setColor(this.getColor());
    //cast back to texture because we use Image vs Actor and want to rotate and change color safely
    ((TextureRegionDrawable)getDrawable()).draw(batch, getX(), getY(),
            getOriginX(), getOriginY(),
            getWidth(), getHeight(),
            getScaleX(), getScaleY(),
            getRotation());
}

@Override
public void act(float delta) {
    super.act(delta);
    }
}

The Problem: I have not been able to get it to rotate the way I would like. I have been able to get it to shift around in unpredictable ways. Any guidance would be much appreciated.

\$\endgroup\$
0
\$\begingroup\$

Actions.sequence() is a convenience method to create a SequenceAction object. You have to give this action to your Actor for it to do anything.

//addAction() is a member of Actor
this.addAction(Actions.sequence(...))

However, this is probably not what you want. Firstly, a SequenceAction is an action where it waits for each action to finish before the next action is applied. To execute both at the same time, you don't need the sequence() or parallel() calls, just

this.addAction(Actions.rotateBy(rotateBy, duration));
this.addAction(Actions.moveBy( dX, dY, duration));

They will execute in parallel and remove themselves when they have finished after duration seconds.

That being said, you might not want to use actions in the first place As your code is now, you will add Actions to the image actor each time that the touchDragged() event fires, regardless of whether the prior Actions have completed. You could wait until the Actions are finished (via Actor.hasAction()) or clear the existing Actions from the Actor before re-adding them. Or you could forgo adding any Actions at all and have your touchDragged() event directly move and rotate the image.

P.S. There really is no reason at this point to inherit from Actor since Image already inherits from Actor

\$\endgroup\$

Your Answer

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