Навигация по MainMenu с помощью клавиш со стрелками или контроллера
Я пытаюсь сделать свое меню доступным с помощью клавиш со стрелками или с помощью 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 ответа
Я сам понял это!
Я создал 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));
Для обработки событий используйте 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 в зависимости от того, что вам нужно. Как вы можете видеть, это простое целочисленное значение, поэтому, если есть ключ от контроллера, проверьте, какое межзначное значение оно должно использовать внутри переключателя.
Для получения дополнительной информации об интерфейсе и о том, как все должно работать, взгляните на Wiki libgdx и получите более подробное объяснение. InputHandling
С уважением