LibGDX 舞台和演员、事件和演员属性

LibGDX Stage and Actor, Events and Actor properties

我刚刚开始使用 LibGdx 框架进行 android 游戏开发。 到目前为止,我阅读了很多在线教程,但我阅读得越多,我就越困惑:ApplicationListener、ApplicationAdapter、Stages、Game、Screens、Actors、Sprites、Images...更不用说 Input 和 Gesture 监听器了。

我终于明白我心目中的游戏(一种益智游戏)应该用什么样的"model":Game、Screens、Stage和Actor。

这是我的第一个代码。

这是主要应用(游戏):

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

public class MyGame extends Game {

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

这是主屏幕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();
    }  

}

下面是扩展Actor的class:

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);          
    }
}

屏幕正确显示了演员,但我无法设置演员的位置或比例,似乎也没有检测到 "tap" 事件;而且颜色没有改变。

我做错了什么?

有几处是错误的。首先,就侧面而言,您不想从 Screen 的 hide() 方法调用 dispose()hide() 可以简单地在屏幕关闭时调用,或者当应用程序切换到后台时调用,并且在此期间处理 Screen 会导致恢复时出现严重问题。

除此之外,您的 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.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,我们可以使用附加到 Sprite 本身的 draw() 方法并将其提供给 Batch,而不是调用Batch 的平局。

最后,当你想改变图像的位置时,对演员本身调用 setPosition,并利用 positionChanged() 方法的覆盖来设置 Sprite' s 的位置基于 Actor 的新位置。