问题
I created a simple game in LibGDX that has multiple screens. I want to restart a certain screen after touching a restart button but I'm not sure how to do that. I made some research about this and all answers lead to not loading my assets in show() but rather in an init() method that I am not really familiar with. I want to know how can I restart a screen using this init() method. As of now I put most of my initialization in the constructor and some were initialized in methods such as the restartButton() method. Any other corrections or improvements in my code will be highly appreciated. Here is a snippet of my code:
public class LevelOneScreen implements Screen {
public MainShooter app;
private Stage stage;
private Stage stageCoin;
private Stage stageScore;
private Stage stageEnemies;
private Stage stageFX;
private Stage stageButton;
public Image aImage;
public Image bImage;
public Image cImage;
public Image dImage;
public Array<AntAnimation> AntAnimate;
public Array<CrumbAnimation> CrumbAnimate;
public Array<CoinAnimation> CoinAnimate;
public Texture firstTex;
public Texture secTex;
public Texture thirdTex;
public Texture fourthTex;
public LevelOneScreen(final MainShooter app){
this.app = app;
this.stage = new Stage(new StretchViewport(app.screenWidth, app.screenHeight, app.camera));
this.stageCoin = new Stage(new StretchViewport(app.screenWidth, app.screenHeight, app.camera));
this.stageScore = new Stage(new StretchViewport(app.screenWidth, app.screenHeight, app.camera));
this.stageEnemies = new Stage(new StretchViewport(app.screenWidth, app.screenHeight, app.camera));
this.stageFX = new Stage(new StretchViewport(app.screenWidth, app.screenHeight, app.camera));
this.stageButton = new Stage(new StretchViewport(app.screenWidth, app.screenHeight, app.camera));
AntAnimate = new Array<AntAnimation>();
CrumbAnimate = new Array<CrumbAnimation>();
CoinAnimate = new Array<CoinAnimation>();
restartButton();
levelOneBackground();
coinScore();
}
public void show() {
inputMultiplexer = new InputMultiplexer();
inputMultiplexer.addProcessor(stageCoin);
inputMultiplexer.addProcessor(stageScore);
inputMultiplexer.addProcessor(stageEnemies);
inputMultiplexer.addProcessor(stageFX);
inputMultiplexer.addProcessor(stageButton);
Gdx.input.setInputProcessor(inputMultiplexer);
}
public void levelOneBackGround(){
//code for the background
}
public void coinScore(){
//code for coinScore
}
public void restartButton(){
firstTex = MainShooter.manager.get("button.png", Texture.class);
aImage = new Image(firstTex);
stageButton.addActor(aImage);
aImage.addListener(new ActorGestureListener() {
public void touchDown(InputEvent event, float x, float y, int pointer, int button) {
// Creating new LevelOneScreen somehow affects the fps of my game.
app.setScreen(new LevelOneScreen(app));
}});
}
//some other codes like dispose, hide, etc.
}
This edit is a response to an answer provided by IronMonkey which seems to solve the problem but needs additional code. The problem here is that whenever the game is restarted, the actors from the restarted screen is on top of the actors on the previous screen(the screen before restarting). Here is a new snippet of my code showing how to restart the game using my GameInit():
public void GameInit(){
levelOneBackground();
scoreInt = 0;
coinInt = 0;
}
public void levelOneBackground(){
Runnable runAntAct1 = new Runnable(){
public void run(){
antAct1();
}
};
Runnable runAntAct2= new Runnable(){
public void run(){
antAct2();
}
};
Runnable runAntAct3 = new Runnable(){
public void run(){
antAct3();
}
};
Runnable runCoins = new Runnable(){
public void run(){
coinScattered();
}
};
levelOneTexture = CoinAssets.manager.get("woodenTable.png",Texture.class);
levelOneImage = new Image(levelOneTexture);
levelOneImage.setSize(app.screenWidth,app.screenHeight);
levelOneImage.setPosition(0,0);
stage.addActor(levelOneImage);
levelOneImage.addAction(sequence(run(runAct1),delay(2f),run(runAct2),delay(2f),run(runAct3),delay(2f),run(runCoins)));
}
public void restartButton(){
//some code for the position, size, texture of the button.
restartButton.addListener(new ActorGestureListener() {
public void touchDown(InputEvent event, float x, float y, int pointer, int button) {
GameInit();}});
}
public void antAct1(){
for(int i = 1; i < 4; i++){AntAnimate.add(new AntAnimation(app));}
AntAnimate.get(1).setPosition(x,y);
stageEnemies.addActor.(AntAnimate.get(1));
AntAnimate.get(1).addAction(//some actions);
AntAnimate.get(2).setPosition(x,y);
stageEnemies.addActor.(AntAnimate.get(2));
AntAnimate.get(2).addAction(//some actions);
AntAnimate.get(3).setPosition(x,y);
stageEnemies.addActor.(AntAnimate.get(3));
AntAnimate.get(3).addAction(//some actions);
}
public void antAct2(){
//almost the same with antAct1()
}
public void antAct3(){
//almost the same with antAct1()
}
public void coinScattered(){
//almost the same with antAct1()
}
回答1:
show() is called automatically when the screen is first shown.
The init() method is one you create yourself. You can call it whatever you want. You should not load all the assets in init() just set everything up, score = 0, player.setPosition(0,0) etc.
So when you first call init() you set all variables. When you call init() again you set them again. (reset)
Efter edit of question:
In the methods called from GameInit() you load files that are already loaded and add actors to stages where those actors are already there and therefore now overlapping. You also add actions and create objects already created.
All GameInit() should do is set values for those already created objects. So basically:
private void GameInit(){
AntAnimate.get(1).setPosition(x,y);
AntAnimate.get(2).setPosition(x,y);
AntAnimate.get(3).setPosition(x,y);
levelOneImage.setPosition(0,0);
scoreInt = 0;
coinInt = 0;
}
Loading and creation of objects should not be done more than once. Try just adding my GameInit() method, call it GameReset() and call it from your reset button.
来源:https://stackoverflow.com/questions/42971321/how-to-restart-screen-in-libgdx-using-init-methods