在 libGDX 中使用带有按钮的动作而不是 Drawable?
Use actions instead Drawable with buttons in libGDX?
我正在 libGDX 开发游戏,我想添加自定义按钮。当按钮被按下时,我想添加一个像 scaleBy 这样的动作,因为它看起来像 Android 中那样更好。我制作了一个名为 Trigger 的 class,它是一个带有侦听器的空 actor,当按下、输入、释放、退出 Trigger 时,它会向 actor 添加动作...所以我创建了一个包含两个 actor 的组:一个 TextButton ( Touchable.disabled) 和触发器。
它确实有效,但我有一个问题:我无法在 Dialog 的按钮方法中添加组。
我认为更好的解决方案是创建一个 class 来扩展 TextButton 或 Button,但我不知道该怎么做。
如果你想要代码,请告诉。
谢谢。
编辑:我尝试制作 class:
private Runnable runnable;
private UIScreen screen;
public static TextButtonStyle transformStyle(Skin skin) {
TextButtonStyle s = skin.get(TextButtonStyle.class);
TextButtonStyle style = new TextButtonStyle(s.up, null, null, s.font);
return style;
}
public static TextButtonStyle transformStyle(TextButtonStyle style) {
TextButtonStyle s = new TextButtonStyle(style.up, null, null, style.font);
return s;
}
public DTextButton(String text, Skin skin, UIScreen screen, Runnable runnable) {
super(text, transformStyle(skin));
this.runnable = runnable;
this.screen = screen;
addListener(new ButtonListener());
setOrigin(Align.center);
setTransform(true);
}
@Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
}
public class ButtonListener extends ClickListener {
private boolean isPressed = false;
private int lastButton = 0;
public void press() {
screen.setButtonPressed(true);
UIFactory.applyPressedAction(DTextButton.this);
isPressed = true;
}
public void release(){
UIFactory.applyReleasedAction(DTextButton.this);
isPressed = false;
}
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
if(button == Buttons.LEFT)
press();
return true;
}
@Override
public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) {
lastButton = (Gdx.input.isButtonPressed(Buttons.LEFT)) ? Buttons.LEFT : -1;
if(pointer == 0 && !isPressed && screen.wasButtonPressed())
press();
}
@Override
public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) {
if(toActor == DTextButton.this && lastButton == Buttons.LEFT){
Gdx.app.postRunnable(runnable);
}
if(pointer == 0 && isPressed)
release();
}
@Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
lastButton = button;
if(pointer == 0 && isPressed && button == Buttons.LEFT)
release();
screen.setButtonPressed(false);
}
}
UIScreen:
public interface UIScreen {
/**
* Return if any UI is pressed.
* @return return buttonPressed
*/
public boolean wasButtonPressed();
/**
* Set if any UI is pressed.
* @param pressed if pressed or not.
*/
public void setButtonPressed(boolean pressed);
}
UIFactory:
public static void applyPressedAction(Actor actor) {
actor.addAction(Actions.scaleBy(-0.2f, -0.2f, 0.2f, Interpolation.pow2Out));
}
public static void applyReleasedAction(Actor actor) {
actor.addAction(Actions.scaleBy(0.2f, 0.2f, 0.3f, Interpolation.swingOut));
}
所以我只使用了 style.up 并添加了相同的 Trigger 监听器。听众不能很好地工作。有什么建议吗?
我认为你过于复杂了。您只需向按钮添加一个输入侦听器,并确保将其设置为转换。你可能希望它的原点居中。不需要子类或包装组或类似的东西。
此外,您希望将 缩放到 ,而不是 by,以避免在多次更改状态时累积错误。
这是一个辅助方法:
public static void makeButtonScale (final Button button, final float hoverScale, final float pressedScale, final float duration){
button.setTransform(true);
button.addListener(new ClickListener(){
void scaleTo (float targetScale){
button.setOrigin(Align.center);
button.clearActions();
button.addAction(Actions.scaleTo(targetScale, targetScale, duration, Interpolation.fade));
}
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
super.touchDown(event, x, y, pointer, button);
scaleTo(pressedScale);
return true;
}
public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
super.touchUp(event, x, y, pointer, button);
scaleTo(isOver() ? hoverScale : 1f);
}
public void enter (InputEvent event, float x, float y, int pointer, Actor fromActor) {
super.enter(event, x, y, pointer, fromActor);
scaleTo(isPressed() ? pressedScale : hoverScale);
}
public void exit (InputEvent event, float x, float y, int pointer, Actor toActor) {
super.exit(event, x, y, pointer, toActor);
scaleTo(1f);
}
});
用法示例:
makeButtonScale(myDialogButton, 1.2f, 1.5f, 0.2f);
请注意,除非您在纹理图集上使用线性 mag 过滤器,否则这看起来不会很好。
我正在 libGDX 开发游戏,我想添加自定义按钮。当按钮被按下时,我想添加一个像 scaleBy 这样的动作,因为它看起来像 Android 中那样更好。我制作了一个名为 Trigger 的 class,它是一个带有侦听器的空 actor,当按下、输入、释放、退出 Trigger 时,它会向 actor 添加动作...所以我创建了一个包含两个 actor 的组:一个 TextButton ( Touchable.disabled) 和触发器。
它确实有效,但我有一个问题:我无法在 Dialog 的按钮方法中添加组。
我认为更好的解决方案是创建一个 class 来扩展 TextButton 或 Button,但我不知道该怎么做。
如果你想要代码,请告诉。
谢谢。
编辑:我尝试制作 class:
private Runnable runnable;
private UIScreen screen;
public static TextButtonStyle transformStyle(Skin skin) {
TextButtonStyle s = skin.get(TextButtonStyle.class);
TextButtonStyle style = new TextButtonStyle(s.up, null, null, s.font);
return style;
}
public static TextButtonStyle transformStyle(TextButtonStyle style) {
TextButtonStyle s = new TextButtonStyle(style.up, null, null, style.font);
return s;
}
public DTextButton(String text, Skin skin, UIScreen screen, Runnable runnable) {
super(text, transformStyle(skin));
this.runnable = runnable;
this.screen = screen;
addListener(new ButtonListener());
setOrigin(Align.center);
setTransform(true);
}
@Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
}
public class ButtonListener extends ClickListener {
private boolean isPressed = false;
private int lastButton = 0;
public void press() {
screen.setButtonPressed(true);
UIFactory.applyPressedAction(DTextButton.this);
isPressed = true;
}
public void release(){
UIFactory.applyReleasedAction(DTextButton.this);
isPressed = false;
}
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
if(button == Buttons.LEFT)
press();
return true;
}
@Override
public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) {
lastButton = (Gdx.input.isButtonPressed(Buttons.LEFT)) ? Buttons.LEFT : -1;
if(pointer == 0 && !isPressed && screen.wasButtonPressed())
press();
}
@Override
public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) {
if(toActor == DTextButton.this && lastButton == Buttons.LEFT){
Gdx.app.postRunnable(runnable);
}
if(pointer == 0 && isPressed)
release();
}
@Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
lastButton = button;
if(pointer == 0 && isPressed && button == Buttons.LEFT)
release();
screen.setButtonPressed(false);
}
}
UIScreen:
public interface UIScreen {
/**
* Return if any UI is pressed.
* @return return buttonPressed
*/
public boolean wasButtonPressed();
/**
* Set if any UI is pressed.
* @param pressed if pressed or not.
*/
public void setButtonPressed(boolean pressed);
}
UIFactory:
public static void applyPressedAction(Actor actor) {
actor.addAction(Actions.scaleBy(-0.2f, -0.2f, 0.2f, Interpolation.pow2Out));
}
public static void applyReleasedAction(Actor actor) {
actor.addAction(Actions.scaleBy(0.2f, 0.2f, 0.3f, Interpolation.swingOut));
}
所以我只使用了 style.up 并添加了相同的 Trigger 监听器。听众不能很好地工作。有什么建议吗?
我认为你过于复杂了。您只需向按钮添加一个输入侦听器,并确保将其设置为转换。你可能希望它的原点居中。不需要子类或包装组或类似的东西。
此外,您希望将 缩放到 ,而不是 by,以避免在多次更改状态时累积错误。
这是一个辅助方法:
public static void makeButtonScale (final Button button, final float hoverScale, final float pressedScale, final float duration){
button.setTransform(true);
button.addListener(new ClickListener(){
void scaleTo (float targetScale){
button.setOrigin(Align.center);
button.clearActions();
button.addAction(Actions.scaleTo(targetScale, targetScale, duration, Interpolation.fade));
}
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
super.touchDown(event, x, y, pointer, button);
scaleTo(pressedScale);
return true;
}
public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
super.touchUp(event, x, y, pointer, button);
scaleTo(isOver() ? hoverScale : 1f);
}
public void enter (InputEvent event, float x, float y, int pointer, Actor fromActor) {
super.enter(event, x, y, pointer, fromActor);
scaleTo(isPressed() ? pressedScale : hoverScale);
}
public void exit (InputEvent event, float x, float y, int pointer, Actor toActor) {
super.exit(event, x, y, pointer, toActor);
scaleTo(1f);
}
});
用法示例:
makeButtonScale(myDialogButton, 1.2f, 1.5f, 0.2f);
请注意,除非您在纹理图集上使用线性 mag 过滤器,否则这看起来不会很好。