JAlmazan
JAlmazan

Reputation: 40

Actor in Stage Does Not Update the MoveTo XY Location

I am creating a game wherein an apple is being shot with an arrow. The apple's location is the XY location of the user input and the arrow actor has to move to that location using the code actor.moveto. The problem is the arrow only moves only once to the user input's direction. I know that the moveTo action of the actor is updated many times per second when I called stageArrow.act in the update method so I am wondering why the arrow only moves once. Here's my code:

appleclass.java

public class AppleClass implements Screen {

Arrow arrow;
private final MainApp app;
public Image ShotImage;

public AppleClass(final MainApp app){
        this.app = app;
        this.stageApple = new Stage(new StretchViewport(app.screenWidth,app.screenHeight , app.camera));
        this.stageArrow =new Stage(new StretchViewport(app.screenWidth,app.screenHeight , app.camera));

        arrow = new ArrowClass(app);

    }

@Override
    public void show() {

        InputMultiplexer inputMultiplexer = new InputMultiplexer();
        inputMultiplexer.addProcessor(stageApple);
        inputMultiplexer.addProcessor(stageArrow);
        Gdx.input.setInputProcessor(inputMultiplexer);

        arrow();

    }

    public void arrow(){
        arrow.isTouchable();
        stageArrow.addActor(arrow);
        arrow.addAction((moveTo(Gdx.input.getX(),Gdx.input.getY(),0.3f)));   //===> only executes once.
        arrow.addListener(new InputListener(){
            public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor){


            if (Gdx.input.isTouched()){
                        ShotImage.setVisible(true);

                          }
                        }
                    });}

}

@Override
    public void render(float delta) {                        

        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        update(delta);
}

public void update(float deltaTime){


        stageApple.draw();
        stageArrow.draw();

        stageApple.act(deltaTime);
        stageArrow.act(deltaTime);


    }

ArrowClass.java

public class ArrowClass extends Actor {
    MainApp app;
    AppleClass appleClass;
    public Texture arrowTexture;

    public ArrowClass(final MainApp app){
        this.app = app;
        arrowTexture = new Texture("medievalarrow.png");
        this.setSize(arrowWidth, arrowHeight);
        this.setTouchable(Touchable.enabled);
        this.setBounds(app.screenWidth*0.45f,0,arrowWidth,arrowHeight);
        this.setOrigin(0,0);

}
@Override
    public void draw(Batch batch, float parentAlpha) {
        super.draw(batch, parentAlpha);


        final float delta = Gdx.graphics.getDeltaTime();
        this.act(delta);

        app.batch.begin();
        app.batch.draw(arrowTexture, getX(),getY(),getWidth(),getHeight());
        app.batch.end();

    }
}

Any help will be highly appreciated. Thanks.

Upvotes: 0

Views: 796

Answers (1)

John
John

Reputation: 1490

I think the problem is because you are calling this.act(delta) in your ArrowClass' draw method. When you call Stage#act(), it will call the act method on all of its actors for you. Since you're calling it once when you draw and again when you update the stage, it's moving at twice the normal speed and that could be causing it to reach its destination prematurely.

A few other comments about your code, if I may:

First, you probably don't want two separate stages- unless you're using Scene2D.UI, you would normally have a single stage with Arrow and Apple added to it as actors.

Second, when you override Actor#draw(), you should use the batch it passes you to do the rendering instead of using the one from app. You also don't want to call begin() and end() inside your draw method- these are 'expensive' and you only want to call them once per frame. However, if you just use the batch that is passed to draw(), the Stage class will handle beginning and ending for you and you won't need to call them explicitly.

Third, you actually don't need to call super.draw(batch, parentAlpha) because it's an empty method in the Actor class.

Thus, your class could be simplified to the following:

public class ArrowClass extends Actor {
    AppleClass appleClass; // You never set this; you may not need it
    Texture arrowTexture;

    public ArrowClass(MainApp app, arrowWidth, arrowHeight) {
        arrowTexture = new Texture("medievalarrow.png");
        this.setSize(arrowWidth, arrowHeight);
        this.setTouchable(Touchable.enabled);
        this.setBounds(app.screenWidth*0.45f,0,arrowWidth,arrowHeight);
        this.setOrigin(0,0);

}
@Override
    public void draw(Batch batch, float parentAlpha) {
        batch.draw(arrowTexture, getX(),getY(),getWidth(),getHeight());
    }
}

Upvotes: 2

Related Questions