使用箭头键或控制器导航MainMenu

时间:2013-10-27 16:02:24

标签: java libgdx ouya

我正在尝试使用箭头键或控制器上的d-pad使我的菜单可导航。到目前为止,我没有运气。

问题是有人可以告诉我如何使我的当前菜单或任何libgdx菜单键盘可访问吗?

我对某些东西有些愚蠢,我来自Javascript背景。

以下是我正在尝试做的一个例子:

http://dl.dropboxusercontent.com/u/39448/webgl/qb/qb.html

对于一个简单的菜单,您可以添加几个按钮,并且它开箱即用,请使用:

http://www.sadafnoor.com/blog/how-to-create-simple-menu-in-libgdx/

或者您可以使用我的代码,但我使用了很多自定义样式。

以下是我的代码示例:

import aurelienribon.tweenengine.Timeline;
import aurelienribon.tweenengine.Tween;
import aurelienribon.tweenengine.TweenManager;

import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.math.Vector2;
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.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.Align;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.project.game.tween.ActorAccessor;

public class MainMenu implements Screen {

 private SpriteBatch batch;
 private Sprite menuBG;
 private Stage stage;
 private TextureAtlas atlas;
 private Skin skin;
 private Table table;
 private TweenManager tweenManager;

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


  batch.begin();
     menuBG.draw(batch);
  batch.end();

  //table.debug();


  stage.act(delta);
  stage.draw();
  //Table.drawDebug(stage);

  tweenManager.update(delta);
}

@Override
public void resize(int width, int height) {
  menuBG.setSize(width,  height);
  stage.setViewport(width, height, false);
  table.invalidateHierarchy();
}

@Override
public void resume() {

}

@Override
public void show() {

  stage = new Stage();

  Gdx.input.setInputProcessor(stage);

  batch = new SpriteBatch();

  atlas = new TextureAtlas("ui/atlas.pack");
  skin = new Skin(Gdx.files.internal("ui/menuSkin.json"), atlas);

  table = new Table(skin);
  table.setBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());


  // Set Background 
  Texture menuBackgroundTexture = new Texture("images/mainMenuBackground.png");
  menuBG = new Sprite(menuBackgroundTexture);
  menuBG.setSize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());

  // Create Main Menu Buttons

  // Button Play
  TextButton buttonPlay = new TextButton("START", skin, "inactive");
  buttonPlay.addListener(new ClickListener() {
     @Override
     public void clicked(InputEvent event, float x, float y) {
        ((Game) Gdx.app.getApplicationListener()).setScreen(new LevelMenu());
     }
  });

  buttonPlay.addListener(new InputListener() {
       public boolean keyDown (InputEvent event, int keycode) {
               System.out.println("down");
               return true;
       }
  });

  buttonPlay.padBottom(12);
  buttonPlay.padLeft(20);
  buttonPlay.getLabel().setAlignment(Align.left);

  // Button EXTRAS
     TextButton buttonExtras = new TextButton("EXTRAS", skin, "inactive");
    buttonExtras.addListener(new ClickListener() {
         @Override
         public void clicked(InputEvent event, float x, float y) {
             ((Game) Gdx.app.getApplicationListener()).setScreen(new ExtrasMenu());
         }

    });
    buttonExtras.padBottom(12);
    buttonExtras.padLeft(20);
    buttonExtras.getLabel().setAlignment(Align.left);

    // Button Credits
     TextButton buttonCredits = new TextButton("CREDITS", skin, "inactive");
    buttonCredits.addListener(new ClickListener() {
         @Override
         public void clicked(InputEvent event, float x, float y) {
           ((Game) Gdx.app.getApplicationListener()).setScreen(new Credits());
         }

    });
    buttonCredits.padBottom(12);
    buttonCredits.padLeft(20);
    buttonCredits.getLabel().setAlignment(Align.left);

    // Button Settings
    TextButton buttonSettings = new TextButton("SETTINGS", skin, "inactive");
    buttonSettings.addListener(new ClickListener() {
         @Override
         public void clicked(InputEvent event, float x, float y) {
           ((Game) Gdx.app.getApplicationListener()).setScreen(new Settings());
         }

    });
    buttonSettings.padBottom(12);
    buttonSettings.padLeft(20);
    buttonSettings.getLabel().setAlignment(Align.left);

  // Button Exit
    TextButton buttonExit = new TextButton("EXIT", skin, "inactive");
  buttonExit.addListener(new ClickListener() {
     @Override
     public void clicked(InputEvent event, float x, float y) {
        Gdx.app.exit();
     }
  });
  buttonExit.padBottom(12);
  buttonExit.padLeft(20);
  buttonExit.getLabel().setAlignment(Align.left);


  // Adding Heading-Buttons to the cue
  table.add().width(190);
  table.add().width((table.getWidth() / 10) * 3);
  table.add().width((table.getWidth() / 10) * 5).height(140).spaceBottom(50);
  table.add().width(190).row();

  table.add().width(190);
  table.add(buttonPlay).spaceBottom(20).width(460).height(110);
  table.add().row();

  table.add().width(190);
  table.add(buttonExtras).spaceBottom(20).width(460).height(110);
  table.add().row();

  table.add().width(190);
  table.add(buttonCredits).spaceBottom(20).width(460).height(110);
  table.add().row();

  table.add().width(190);
  table.add(buttonSettings).spaceBottom(20).width(460).height(110);
  table.add().row();

  table.add().width(190);
  table.add(buttonExit).width(460).height(110);
  table.add().row();
  stage.addActor(table);

  // Animation Settings
  tweenManager = new TweenManager();
  Tween.registerAccessor(Actor.class, new ActorAccessor());


  // Heading and Buttons Fade In
  Timeline.createSequence().beginSequence()
     .push(Tween.set(buttonPlay, ActorAccessor.ALPHA).target(0))
     .push(Tween.set(buttonExtras, ActorAccessor.ALPHA).target(0))
     .push(Tween.set(buttonCredits, ActorAccessor.ALPHA).target(0))
     .push(Tween.set(buttonSettings, ActorAccessor.ALPHA).target(0))
     .push(Tween.set(buttonExit, ActorAccessor.ALPHA).target(0))

     .push(Tween.to(buttonPlay, ActorAccessor.ALPHA, .5f).target(1))
     .push(Tween.to(buttonExtras, ActorAccessor.ALPHA, .5f).target(1))
     .push(Tween.to(buttonCredits, ActorAccessor.ALPHA, .5f).target(1))
     .push(Tween.to(buttonSettings, ActorAccessor.ALPHA, .5f).target(1))
     .push(Tween.to(buttonExit, ActorAccessor.ALPHA, .5f).target(1))
     .end().start(tweenManager);

  tweenManager.update(Gdx.graphics.getDeltaTime());

}

public static Vector2 getStageLocation(Actor actor) {
   return actor.localToStageCoordinates(new Vector2(0, 0));
}

@Override
public void dispose() {
  stage.dispose();
  atlas.dispose();
  skin.dispose();
  menuBG.getTexture().dispose();
}

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

@Override
public void pause() {

}

}

2 个答案:

答案 0 :(得分:2)

我自己想出来了!

我制作了一个ControllerListener,它模拟了Scene2D按钮所期望的鼠标输入事件。至于使用箭头键控制它们,您可以轻松地将相同的方法应用于处理其各自键事件的新InputProccessor。

public class MenuControllerListener implements ControllerListener {

private final Group buttonGroup;

private int currentButtonIndex = 0;

public MenuControllerListener(Group buttonGroup) {
    this.buttonGroup = buttonGroup;
}

@Override public void connected(Controller controller) { }
@Override public void disconnected(Controller controller) { }

@Override
public boolean buttonDown(Controller controller, int buttonCode) {
    if(buttonGroup.getChildren().size == 0) return false;
    if(controller.getName().toLowerCase().contains("xbox") &&
       controller.getName().contains("360")){
        switch(buttonCode) {
        case Xbox360Pad.BUTTON_A:
            Actor currentButton = buttonGroup.getChildren().get(currentButtonIndex);
            return clickButton(currentButton);
        }
    }
    return false;
}

@Override
public boolean buttonUp(Controller controller, int buttonCode) {
    if(buttonGroup.getChildren().size == 0) return false;
    if(controller.getName().toLowerCase().contains("xbox") &&
       controller.getName().contains("360")){
        switch(buttonCode) {
        case Xbox360Pad.BUTTON_A:
            Actor currentButton = buttonGroup.getChildren().get(currentButtonIndex);
            return releaseButton(currentButton);
        }
    }
    return false;
}

/**
 * Simulate button click down.
 * @param button
 * @return
 */
private boolean clickButton(Actor button) {
    InputEvent event = Pools.obtain(InputEvent.class);
    event.setType(Type.touchDown);
    event.setButton(Input.Buttons.LEFT);

    button.fire(event);
    boolean handled = event.isHandled();
    Pools.free(event);
    return handled;
}

/**
 * Simulate button click release.
 * @param button
 * @return
 */
private boolean releaseButton(Actor button) {
    InputEvent event = Pools.obtain(InputEvent.class);
    event.setType(Type.touchUp);
    event.setButton(Input.Buttons.LEFT);

    button.fire(event);
    boolean handled = event.isHandled();
    Pools.free(event);
    return handled;
}

@Override
public boolean axisMoved(Controller controller, int axisCode, float value) { return false; }

@Override
public boolean povMoved(Controller controller, int povCode, PovDirection value) {
    if(buttonGroup.getChildren().size == 0) return false;
    if(controller.getName().toLowerCase().contains("xbox") &&
       controller.getName().contains("360")){

        unselectButton(buttonGroup.getChildren().get(currentButtonIndex));

        switch(value) {
        case north:
        case west:
            currentButtonIndex--;
            break;
        case south:
        case east:
            currentButtonIndex++;
            break;
        default:
            break;
        }

        currentButtonIndex = currentButtonIndex % buttonGroup.getChildren().size;
        if(currentButtonIndex < 0) currentButtonIndex = buttonGroup.getChildren().size - 1;

        return selectButton(buttonGroup.getChildren().get(currentButtonIndex));
    }

    return false;
}

/**
 * Simulate mousing over a button.
 * @param button
 * @return
 */
private boolean selectButton(Actor button) {
    InputEvent event = Pools.obtain(InputEvent.class);
    event.setType(Type.enter);

    button.fire(event);
    boolean handled = event.isHandled();
    Pools.free(event);
    return handled;
}

/**
 * Simulate mousing off of a button.
 * @param button
 * @return
 */
private boolean unselectButton(Actor button) {
    InputEvent event = Pools.obtain(InputEvent.class);
    event.setType(Type.exit);

    button.fire(event);
    boolean handled = event.isHandled();
    Pools.free(event);
    return handled;
}

@Override public boolean xSliderMoved(Controller controller, int sliderCode, boolean value) { return false; }
@Override public boolean ySliderMoved(Controller controller, int sliderCode, boolean value) { return false; }
@Override public boolean accelerometerMoved(Controller controller, int accelerometerCode, Vector3 value) { return false; }
}

这需要您将按钮添加到表中,例如使用:

TextButton.TextButtonStyle buttonStyle = new TextButton.TextButtonStyle();
buttonStyle.font = new BitmapFont();
buttonStyle.font.scale(2f);
buttonStyle.fontColor = Color.WHITE;
buttonStyle.overFontColor = Color.LIGHT_GRAY;
buttonStyle.downFontColor = Color.GRAY;

newGameButton = new TextButton("New Game", buttonStyle);
continueButton = new TextButton("Continue", buttonStyle);
optionsButton = new TextButton("Options", buttonStyle);
exitButton = new TextButton("Exit", buttonStyle);

Table buttonGroup = new Table();
buttonGroup.setFillParent(true);
buttonGroup.align(Align.center);
buttonGroup.add(newGameButton);
buttonGroup.row();
buttonGroup.add(continueButton);
buttonGroup.row();
buttonGroup.add(optionsButton);
buttonGroup.row();
buttonGroup.add(exitButton);

stage.addActor(buttonGroup);

Controllers.addListener(new MenuControllerListener(buttonWrapper));

答案 1 :(得分:1)

要处理事件,请使用InputProcessor界面开发一个简单的InputProcessor,您可以将其添加到Gdx输入事件中。

MyInputProcessor inputProcessor = new MyInputProcessor();
Gdx.input.setInputProcessor(inputProcessor);

只需处理

中的不同键即可
   @Override
   public boolean keyDown (int keycode) {
      return false;
   }

您确实使用了Keyinteger值。只需使用一个简单的开关盒来检查按下哪个键。

import com.badlogic.gdx.Input.Keys;

并使用静态示例Keys.LEFT。 像这样的简单开关箱:

@Override
public boolean keyDown (int keycode) {
        switch (keycode) {
        case Keys.LEFT:
            // handle left push
            break;
        case Keys.RIGHT:
            // handle right push
            break;
        case Keys.DOWN:
            // handle down push
            break;
        // handle more keys here if you need

        default:
            // unused key pushed
            break;
        }
    return false;
}

根据您的需要,不要忘记返回false或true。正如您所看到的,它是一个简单的整数值,因此如果控制器中有一个键,请检查在交换机内使用它的哪个intergervalue。

有关界面以及一切应如何工作的更多信息,请查看libgdx的Wiki并获得更详细的表达式。 InputHandling

此致