LibGDX Stage and Actor, Events and Actor properties

时间:2015-07-28 22:30:59

标签: libgdx screen actor stage

I'm just starting android game development with LibGdx framework. I read many online tutorial so far and the more I read the more I got confused: ApplicationListener, ApplicationAdapter, Stages, Game, Screens, Actors, Sprites, Images... not mentioning Input and Gesture listeners of all king).

I finally understood what kind of "model" I should use for the game I have in mind (a kind of puzzle game): Game, Screens, Stage and Actor.

So here is my first code.

This is the main application (Game):

package com.my.game1;
import com.badlogic.gdx.Game;

public class MyGame extends Game {

    @Override
    public void create () {
        setScreen(new StarterScreen());
    } 
}

This is the main screen class:

package com.my.game1;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.scenes.scene2d.Stage;

public class StarterScreen implements Screen {

    private Stage stage;
    private float screenW, screenH;
    private Tess tessera;

    @Override
    public void show() {
        tessera = new Tess("image.png");
        stage = new Stage();
        screenW = stage.getViewport().getWorldWidth();
        screenH = stage.getViewport().getWorldHeight();
        Gdx.input.setInputProcessor(stage);
        stage.addActor(tessera);
    }

    @Override
    public void render(float delta) {
        Gdx.gl.glClearColor(0,0,0,1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        stage.act();
        stage.draw();
    }

    @Override
    public void resize(int width, int height) {
        // TODO Auto-generated method stub

    }

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

    }

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

    }

    @Override
    public void hide() {
        dispose();
    }

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

}

And the following is the class that extends Actor:

package com.my.game1;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.utils.ActorGestureListener;

public class Tess extends Actor {

    private Texture texture;
    private boolean selected = false;

    public Tess (String img) {
        this.texture = new Texture(Gdx.files.internal(img));
        this.setBounds(0f, 0f, this.texture.getWidth(), this.texture.getHeight());
        this.setOrigin(this.texture.getWidth() / 2, this.texture.getHeight() / 2);
        this.setScale(0.25f);
        this.addListener(new ActorGestureListener() {
            public void tap(InputEvent event, float x, float y, int pointer, int button) {
                ((Tess)event.getTarget()).toggleSelect();
                ((Tess)event.getTarget()).setColor(0.5f, 0f, 0.5f, 1f);
            }
        });
    }

    @Override
    public void draw(Batch batch, float alpha){
        batch.draw(texture, 0, 0);
    }

    public void finalize() {
        this.texture.dispose();
    }

    public void toggleSelect(){
        this.selected = !this.selected;
        if (this.selected == true)
            this.setColor(0.5f, 0f, 0.5f, 1f);
        else
            this.setColor(0f, 0f, 0f, 0f);          
    }
}

The screen shows correctly the actor, but I cannot set the Actor's position or its scale, nor the "tap" event seems to get detected; and the color doesn't change.

What I did wrong?

1 个答案:

答案 0 :(得分:1)

有些事情是错的。首先,您不希望从屏幕dispose()方法中调用hide()。只需在屏幕关闭或应用切换到后台时调用hide(),并在此期间处置Screen会导致严重问题。

有了这个,这就是你的演员看起来应该是什么样的:

package com.my.game1;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.Touchable;

public class Tess extends Actor {

    private Sprite sprite;
    private boolean selected = false;

    public Tess (String img) {
        this.sprite = new Sprite(new Texture(Gdx.files.internal(img)));
        this.setTouchable(Touchable.enabled);
        this.setBounds(this.sprite.getX(), this.sprite.getY(), this.sprite.getWidth(), this.sprite.getHeight());
        this.setOrigin(this.sprite.getWidth() / 2, this.sprite.getHeight() / 2);
        this.setScale(0.25f);
        this.addListener(new ActorGestureListener() {
            @Override
            public void tap (InputEvent event, float x, float y, int pointer, int button) {
                ((Tess)event.getTarget()).toggleSelect();
            }
        });
    }

    @Override
    public void draw(Batch batch, float alpha){
        sprite.draw(batch);
    }

    @Override
    public void positionChanged(){
        sprite.setPosition(getX(), getY());
    }

    public void toggleSelect(){
        this.selected = !this.selected;
        if (this.selected == true)
            sprite.setColor(0.5f, 0f, 0.5f, 1f);
        else
            sprite.setColor(0f, 0f, 0f, 0f);          
    }
}

首先改变了:你应该使用Sprite而不是Texture来轻松处理颜色,绘图和变换。 Texture是可能的,但不像Sprite那样简单。

接下来,您需要在actor内部调用setTouchable(Touchable.enabled)以实际启用命中检测。没有这个,没有触摸事件传递给Actor

之后,使用setBounds(),您需要使用sprite.getX()sprite.getY()来使用Sprite的位置值。将它们设置为任意数字似乎会禁用Actor的任何触摸容量。

另一件事,如果所有这一切都没问题,那就是你为每次触摸设置了两次颜色,一次是基于selected字段,然后在直接变成深紫色后立即设置,所以我删除了第二组,只使用了你的切换方法。

接下来,由于我们现在有一个Sprite,我们可以使用附加到draw()本身的Sprite方法并将其提供给Batch,而不是调用{ {1}}的平局。

最后,当您想要更改图片的位置时,请在演员本身上调用Batch,并使用覆盖setPosition方法来设置positionChanged()&#39 ; s的位置基于Sprite的新职位。