我目前正在开展一个学校项目,我遇到了一个我无法单独解决的错误:/
我有2个屏幕:MainMenue和LoginScreen。两个屏幕都在我的ScreenMap中(只是一个包含我所有屏幕的简单HashMap)
如果我触摸“btnLogin”按钮即将进入LoginScreen(还没有登录逻辑)。通过按钮“btnLogin”,我回到MainMenue。现在奇怪的部分即将来临。回到主菜单我点击任何按钮都无关紧要我做什么。该按钮甚至没有像平常一样突出显示,他只是不起作用。
MainMenue:
private int xSize;
private int ySize;
private long lastStarSpawnTime;
final Main game;
private Texture smallStar_Texture;
private Texture gameName_Texture;
private Texture playerShip_Texture;
private AssetLoader assetLoader;
private OrthographicCamera camera;
private Array<Rectangle> starBuffer;
private Rectangle gameNameRect;
private Rectangle startGameRect;
private Rectangle loginRect;
private Rectangle playerShipRect;
private Stage stage;
private TextButton btnStartGame;
private TextButton btnLogin;
// TODO Positionierung der Menueelemente nochmal anschauen
public MainMenueScreen(final Main gam) {
game = gam;
this.assetLoader = game.getAssetLoader();
starBuffer = new Array<Rectangle>();
xSize = Gdx.graphics.getWidth();
ySize = Gdx.graphics.getHeight();
loadAssets();
initMenueElements();
initStage();
camera = new OrthographicCamera();
camera.setToOrtho(false, xSize, ySize);
game.screenMap.put("mainmenue", MainMenueScreen.this);
}
@Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0.0f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
game.batch.setProjectionMatrix(camera.combined);
stage.act(delta);
stage.draw();
game.batch.begin();
for (int i = 0; i < starBuffer.size; i++) {
game.batch.draw(smallStar_Texture, starBuffer.get(i).x, starBuffer.get(i).y);
}
game.batch.draw(playerShip_Texture, playerShipRect.x, playerShipRect.y);
game.batch.draw(gameName_Texture, gameNameRect.x, gameNameRect.y);
game.batch.end();
if (TimeUtils.nanoTime() - lastStarSpawnTime > 10000000) {
spawnStarSmall();
spawnStarSmall();
spawnStarSmall();
}
Iterator<Rectangle> iter = starBuffer.iterator();
// StarAnimation Logic
try {
while (iter.hasNext()) {
Rectangle star = iter.next();
star.y -= 1500 * Gdx.graphics.getDeltaTime();
if (star.x < 0 || star.x > xSize) {
iter.remove();
}
if (star.y + 2 < 0) {
iter.remove();
}
}
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
}
}
private void initStage() {
stage = new Stage();
Skin skin = new Skin(Gdx.files.internal("uiskin.json"), assetLoader.getBtn_300x80_black_grey());
//BtnStartGame
btnStartGame = new TextButton("Start Game", skin);
startGameRect = new Rectangle();
startGameRect.height = btnStartGame.getHeight();
startGameRect.width = btnStartGame.getWidth();
startGameRect.x = (xSize / 2) - (startGameRect.width / 2);
startGameRect.y = ySize - ((gameNameRect.height / 2 + 5) + 4 * (startGameRect.height / 2 + 50));
btnStartGame.setPosition(startGameRect.x, startGameRect.y);
btnStartGame.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
game.setScreen(new GameScreen(game, new quickmode_Level_02(game.getAssetLoader())));
dispose();
}
});
stage.addActor(btnStartGame);
//BtnLogin
btnLogin = new TextButton("Login", skin);
loginRect = new Rectangle();
loginRect.height = btnLogin.getHeight();
loginRect.width = btnLogin.getWidth();
loginRect.x = (xSize /2) - (loginRect.getWidth() / 2);
loginRect.y = ySize - ((loginRect.height / 2 + 5) + 4 * (loginRect.height / 2 + 100));
btnLogin.setPosition(loginRect.x, loginRect.y);
btnLogin.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
game.setScreen(new LoginScreen(game));
dispose();
}
});
stage.addActor(btnLogin);
Gdx.input.setInputProcessor(stage);
}
@Override
public void resize(int width, int height) {
}
@Override
public void show() {
//reInitListeners();
}
@Override
public void hide() {
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void dispose() {
}
private void loadAssets() {
gameName_Texture = assetLoader.getMainMenue_GameName_Texture();
smallStar_Texture = assetLoader.getMainMenue_Star_Small_Texture();
playerShip_Texture = assetLoader.getPlayerShipTexture_normal();
}
private void spawnStarSmall() {
Rectangle star = new Rectangle();
star.x = MathUtils.random(0, xSize);
star.y = MathUtils.random(ySize, ySize + 50);
star.height = smallStar_Texture.getHeight();
star.width = smallStar_Texture.getWidth();
starBuffer.add(star);
lastStarSpawnTime = TimeUtils.nanoTime();
}
private void initMenueElements() {
//GameName
gameNameRect = new Rectangle();
gameNameRect.height = gameName_Texture.getHeight();
gameNameRect.width = gameName_Texture.getWidth();
gameNameRect.x = (xSize / 2) - (gameNameRect.width / 2);
gameNameRect.y = ySize - 1.5f * (gameNameRect.height / 2 + 100);
//Playership
playerShipRect = new Rectangle();
playerShipRect.width = playerShip_Texture.getWidth();
playerShipRect.height = playerShip_Texture.getHeight();
playerShipRect.x = xSize / 2;
playerShipRect.y = 0 + playerShip_Texture.getHeight() + 50;
}
private void reInitListeners() {
btnLogin.clearListeners();
btnStartGame.clearListeners();
btnLogin.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
game.setScreen(new LoginScreen(game));
dispose();
}
});
btnStartGame.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
game.setScreen(new GameScreen(game, new quickmode_Level_02(game.getAssetLoader())));
dispose();
}
});
}
LoginScreen:
final Main game;
private OrthographicCamera camera;
//Textures
private Texture username_Texture;
private Texture password_Texture;
private Texture gameName_Texture;
private AssetLoader assetLoader;
private Rectangle gameNameRect;
private Rectangle usernameRect;
private Rectangle loginRect;
private Rectangle newaccountRect;
private Rectangle passwordRect;
private Rectangle usernametxfRect;
private int xSize;
private int ySize;
private Stage stage;
private Skin skin;
private TextButton btnLogin;
private TextButton btnNewAccount;
private TextField txfUsername;
private TextField txfPassword;
public LoginScreen(final Main game) {
this.game = game;
this.assetLoader = game.getAssetLoader();
xSize = Gdx.graphics.getWidth();
ySize = Gdx.graphics.getHeight();
loadAssets();
initLoginMenue();
initStage();
camera = new OrthographicCamera();
camera.setToOrtho(false, xSize, ySize);
game.screenMap.put("loginscreen", LoginScreen.this);
}
@Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0.0f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
game.batch.setProjectionMatrix(camera.combined);
stage.act(delta);
stage.draw();
game.batch.begin();
//Draw
game.batch.draw(gameName_Texture, gameNameRect.x, gameNameRect.y);
game.batch.draw(username_Texture, usernameRect.x, usernameRect.y);
game.batch.draw(password_Texture, passwordRect.x, passwordRect.y);
game.batch.end();
}
private void initLoginMenue() {
//GameName
gameNameRect = new Rectangle();
gameNameRect.height = gameName_Texture.getHeight();
gameNameRect.width = gameName_Texture.getWidth();
gameNameRect.x = (xSize / 2) - (gameNameRect.width / 2);
gameNameRect.y = ySize - 1.5f * (gameNameRect.height / 2 + 100);
//username
usernameRect = new Rectangle();
usernameRect.height = username_Texture.getHeight();
usernameRect.width = username_Texture.getWidth();
usernameRect.x = (xSize / 4) - (usernameRect.width / 2);
usernameRect.y = ySize - 1.5f * (usernameRect.height / 2 + 300);
//password
passwordRect = new Rectangle();
passwordRect.height = username_Texture.getHeight();
passwordRect.width = username_Texture.getWidth();
passwordRect.x = (xSize / 4) - (passwordRect.width / 2);
passwordRect.y = ySize - 1.5f * (passwordRect.height / 2 + 430);
//loginButton
btnLogin = new TextButton("Login", skin);
loginRect = new Rectangle();
loginRect.height = btnLogin.getHeight();
loginRect.width = btnLogin.getWidth();
loginRect.x = (xSize / 3) - (loginRect.width / 2);
loginRect.y = ySize - 1.5f * (loginRect.height / 2 + 580);
//newAccountButton
btnNewAccount = new TextButton("New Account", skin);
newaccountRect = new Rectangle();
newaccountRect.height = btnNewAccount.getHeight();
newaccountRect.width = btnNewAccount.getWidth();
newaccountRect.x = (xSize / 3 * 2) - (newaccountRect.width / 2);
newaccountRect.y = ySize - 1.5f * (newaccountRect.height / 2 + 580);
//usernameTextfield
txfUsername = new TextField("Klick mich!", skin);
usernametxfRect = new Rectangle();
usernametxfRect.height = 300;
usernametxfRect.width = 80;
usernametxfRect.x = usernameRect.x;
usernametxfRect.y = usernameRect.y + 300;
}
private void loadAssets() {
username_Texture = assetLoader.getLoginScreen_username_Texture();
password_Texture = assetLoader.getLoginScreen_password_Texture();
gameName_Texture = assetLoader.getMainMenue_GameName_Texture();
skin = new Skin(Gdx.files.internal("uiskin.json"), assetLoader.getBtn_300x80_black_grey());
}
private void initStage() {
stage = new Stage();
//BtnLogin
btnLogin.setPosition(loginRect.x, loginRect.y);
btnLogin.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
game.setScreen(game.screenMap.get("mainmenue"));
//dispose();
}
});
stage.addActor(btnLogin);
//BtnNewAccount
btnNewAccount.setPosition(newaccountRect.x, newaccountRect.y);
btnNewAccount.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
game.setScreen(new NewAccountScreen(game));
dispose();
}
});
stage.addActor(btnNewAccount);
//txfUsername
txfUsername.setPosition(usernametxfRect.x, usernametxfRect.y);
txfUsername.setWidth(usernametxfRect.getWidth());
txfUsername.setHeight(usernametxfRect.getHeight());
stage.addActor(txfUsername);
Gdx.input.setInputProcessor(stage);
}
@Override
public void resize(int width, int height) {
}
@Override
public void show() {
}
@Override
public void hide() {
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void dispose() {
}
答案 0 :(得分:0)
一旦您离开屏幕并返回屏幕,它就不再是输入处理器而且不会因为您使用的是之前使用过的旧屏幕。您正在屏幕的构造函数中设置输入处理器(Gdx.input.setInputProcessor(stage);)。当我切换屏幕时,我这样做:
game.setScreen(new MainMenuScreen());
如果你创建一个新实例,你的构造函数将被调用(这是你设置输入处理器的地方)。制作一个新实例可能看起来很浪费,但我从未经历过任何延迟。相反,如果您将所有屏幕保留在地图中,则在程序的整个生命周期中都会占用一定的堆空间(尽管可能不多)。我会抛弃地图并根据需要实例化屏幕。
答案 1 :(得分:0)
问题是,Stage
不再是您的InputProcessor
了
这是因为,只要您拨打new LoginScreen()
,就拨打Gdx.input.setInputProcessor(stage);
,用新的InputProcessor
替换当前stage
(MainMenue
中的stage
)( LoginScreen
中的MenuScreen
如果然后切换回InputProcessor
,则永远不会调用``Gdx.input.setInputProcessor`。
解决方案:
在show()
方法中设置initStage()
,或者甚至更好,在show()
方法中调用stage
并重置null
(将其设置为hide()
在setScreen(newScreen)
方法中,释放资源
要通知您:如果您为游戏调用oldScreen.hide()
,则会调用newScreen.show()
和tehn {{1}}。
希望它有所帮助。