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
的新位置。
我刚刚开始使用 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
的新位置。