Libgdx Screen Confusion - java

Hello this is my first time posting on here and am relatively new to coding. I've been playing around with java and libgdx for a month or two and I'm confused about one thing for screens.
If I have a GameScreen class that is active when playing the game, and then wanted to switch momentarily to another screen for inventory or a pause screen or something, if I make the game switch back to the game screen it seems everything resets and a new game starts. What would be the correct way to make sure the screen reloads in the same state it was just in?

If you want to keep a screen alive in the background such as you described, you need to make sure you separate your game initialization code so it is only called when you are starting a new level. There are a million ways you could do this. Here's an example:
public class MyGameScreen {
public MyGameScreen (){
//load textures and sounds here if you aren't managing them somewhere else.
startNewGameRound();
}
#Override
public void show (){
//this is only for stuff you need to reset every time the screen comes back.
//Generally, you would undo stuff that you did in `hide()`.
}
public void startNewGameRound (){
//Reset all your variables and reinitialize state for a new game round.
//This is called in the constructor for first time setup, and then it
//can also be called by a button anywhere that starts a new round.
//But do not load textures and sounds here. Do that in the constructor
//so it only happens once.
}
}
Then in your Game class, you also need to make sure you keep your game screen instance and reuse it.
Don't do this:
setScreen(new MyGameScreen());
Do this instead:
//member variable:
private MyGameScreen myGameScreen;
//In some method:
if (myGameScreen == null)
myGameScreen = new MyGameScreen();
setScreen(myGameScreen);

Related

How do action events work with players' turns, need help showing which card the user played before the computer shows what card it played

Im creating an uno game and it is almost fully functional and i'm using javaFX to create it. It is Computer vs User and the problem is that when a user clicks on a card button, the middle card is supposed to be replaced with that card and then the computer goes, however what ends up happening is that the computer goes right away and so you only see the computer's card played in the middle. I am sure this has something to do with how i structured my code specifically the action event pertaining to the button clicked. However, since this is my first ever java GUI and i am fairly new to java i am struggling to understand how to structure it so that i am able to show the user's move. Also due to this, i am unable to implement a skip card even though i have tried using a boolean and creating another method i think the main problem lies within how the main gameloop and the actionevent inside is set up.
This method is called and it checks for a button click and then gets the index of the button in the player's arraylist/hand/ The boolean was my attempt at implementing a skip card but what kept happening is the computer would always play right after the user's move when a skip card was played.
public void gameLoop(){
for(int i =0; i<buttonList.size();i++){
buttonList.get(i).setOnAction((ActionEvent)->{
indexOfHandButton = buttonList.indexOf((Button)ActionEvent.getSource());
humanMakeMove();
if(!isReverseTurn()) {
computerMakeMove();
}
});
}
}
This method used the index given from the gameloop actionevent and makes the actual move in the backend. It then clears the hbox containing the users hands and calls showhumanHand which fills it up with the updated cards and similarily with the middle card. The if statements to try and implement the skip cards have not worked, i have also tried creating a new action even inside the if statement and creating a method or recursively calling humanMakeMove but of course the index will be the same and will cause an error.
public void humanMakeMove() {
String result = human.makeMove(game, theDeck, indexOfHandButton, computer);
if(result.equals("skip")){
setReverseTurn(true);
}
hbHumanHandBtn.getChildren().clear();
hbMiddleCard.getChildren().remove(middle);
middle = generateMiddleCard();
hbMiddleCard.getChildren().add(middle);
showHumanHand();
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>" + buttonList);
System.out.println(result);
if (middleCard.getType() != null) {
if (middleCard.getType().equals("skip") && isReverseTurn()) {
System.out.println(isReverseTurn());
gameLoop();
setReverseTurn(false);
}
}
}
So my main question is how can i restructure this or add something that allows for the user's card to show in the middle before the computer goes right away, i have tried a timer/sleep method too. And my skip card doesnt work but i think that has to do with how i set up my action listener which is messing up two problems. Thank you for reading this and let me know if you have any input!

Libgdx Game: Delay Action Based on Score Count

I'm still a bit new at Java and need some help with a game I'm currently working on. I've already implemented the core of the game where balls drop from the top of the screen and the user controls platforms to bounce the balls to the right side of the screen. If the player succeeds, then a point is awarded. I already implemented the code for the bouncing balls, platforms, score, and various states.
The thing I'm stuck on is controlling the number of balls that drop depending on the score. I already have a rough idea of the algorithm. Without going into too much detail it goes something like this:
public class BallContainer{
public ArrayList<Ball> balls;
public BallContainer(ArrayList<Ball> balls){
this.balls = balls;
}
public void drop(int howMany){
//code to activate the gravity of "howMany" random balls with a .5 second delay between them
}
public class MainGame{
public void update(float dt){
//check score and drop a selection of balls with random seconds of delay between each group of balls dropped at a time
}
}
I already have an idea of how many balls and how much of a random delay will occur depending on the score. One thing I'm just stuck on the delaying of the action. I know we can use the java.util.Timer and TimerTask, but I also hear libgdx also has some built in delay methods. Anyway, any help would be appreciated.
Thanks.
You can use libgx Timer class to provide actions to happen after a certain delay.
Here is an example -
Timer.schedule(new Task() {
#Override
public void run() {
//create new balls here or do whatever you want to do.
}
}, DELAY_TIME_IN_SECONDS);
What happens here is you are calling a static method of Timer class called schedule which takes a Task and delaySeconds in float as parameters.
Now as parameter you are creating a new Anonymous inner class object as Task is an abstract class. In the anonymous inner class object, you override the run method and put what you want it to do.
Place the above snippet in the place where you want to create new balls or do some action.
You can just create a new thread, where you will place a flag, then sleep the newly created thread, and after sleep finishes - set your flag to true.
So ur game won't freeze like it will if you gonna sleep the main thread.

Libgdx on desktop, how to handle disposing when window is closed

I'm using libgdx (com.badlogic.gdx.Game and Screens and that stuff) to make a game. I have the following problem: on desktop, when I close the window (from the cross on top), of course the application closes. But I would like to go back to menu screen and dispose there, since I do disposing of resources there (via asset manager). I have buttons for exiting in the game and if exiting is done that way, it's fine. The trouble is that the red cross can be pressed. So how could I handle disposing properly in that case?
On the android version, I catch the back key and handle leaving different parts of the game and the whole game in my own way. And there it works OK.
Another related question I have:
On desktop the application cannot get stopped and then disposed (on it's own, without user explicitly exiting it) like the android version can (the android life cycle), right? So is it a good idea, if I do a temporary save on pause() and restore game state from that on resume(), that I don't restore on desktop (since the restoring isn't a complete restore and I don't want restoring to happen if, on desktop, the window is just minimized (as I noticed, pause()/resume() gets called when minimizing/restoring window )).
Hope this wasn't too unclear :D. I've tried to google for answers but don't seem to find anything. Any help is much appreciated.
I suggest using the libgdx life-cycle methods
To dispose you should use the dispose() method. You don't need to call dispose yourself! It will be called automatically when the application gets destroyed, see documentation:
dispose () Called when the application is destroyed. It is preceded by a call to pause().
So just implement the dispose method in your Screens:
#Override
public void dispose () {
//your code needs to get added here, like for example:
stage.dispose();
texture.dispose();
//etc..
}
Update: Note that dispose() of AppliacationListener gets called automatically, not dispose() of Screen, see comment of Springrbua
You can call dispose() of your Screen by calling it explicitly from your Game Class dispose() like this
MyScreen Class:
public class MyScreen implements Screen {
// Not going to write all other methods that need to be overridden
#Override
public void dispose() {
// Clear you Screen Resources here
}
}
MyGame Class:
public class MyGame extends Game {
// Not going to write all other methods that need to be overridden
#Override
public void create() {
setScreen(new MyScreen());
}
#Override
public void dispose() {
// Clear you Screen Explicitly
getScreen().dispose();
}
}
Hope this helps
As mentioned above, the Screen interface contains a dispose method. Additionally, the dispose method of Game can be overridden to dispose of the current screen automatically. However, there is a reason this is not the default. Let's say you have multiple Screens - Screen1and Screen2. Screen1 was active, then changed the screen to 2. The game is then exited, and the dispose method is called, which calls the current screen's dispose method - leaving screen 1 alone.
My preferred method is to have the game keep track of screens set by overriding the setScreen method and adding a Screen[] screens, a boolean[] scrDiss, and an index. When dispose is called on Game, it checks through all screens set, checks if previously disposed, and disposes if not. Additionally, the Screen dispose methods should call a method on the Game that finds it in the array, and marks it disposed. This way, screens can be disposed before the end of the Game, but when Game is disposed, all Screens will be as well.
Call dispose on all your screens when your application is disposed.

UI not updating smoothly due to a background Thread

I am writing an android game and here is what i have:
Game loop is implemented as:
I have made a custom view which extends the view.Then inside my onDraw() method, i call invalidate();
MainActivity:
Here i make an instance of a custom view and use setContentView() to set that as my current view.
I also use OnTouch() method to get touch events
Everything was working fine and smoothly till i did this:
I made a new class Graphthread and inside the run method, i created a loop.
public class Graphthread extends Thread
{
#Override
public void run() {
while(true)
{
}
}
}
Then i created an instance of this in my MainActivity
Graphthread gth = new Graphthread();
and used gth.start() in my onCreate method.
Now following happened:
The game did not run smoothly.Or i should say it was like..run for sometime..freeze for a few milliseconds...run again ...freeze again and so on.
What is happening?
Slight jitters like that sounds like garbage collection. If your background thread (or something else) is consuming a very large amount of memory, the GC may need to run more often then expected. That would cause momentary jitters such as you described.
Try more suitable approach for games: use SurfaceView and background thread to draw on it. This should free you from stuttering, cased by irregular message processing by main thread.
onDraw hack, from my point of view, suitable only if you want to animate something inside a regular app (not game), and animation framework has little use for you. Panning and scaling image for example.

How do I delay a method for turn-based game in Java Android

In a simple card game (human vs. CPU) the logic works, but I want to delay the computer's turn.
I have tried using Thread.sleep(int milliseconds) which works, but it messes up the order images are displayed. I'm not using a game loop, I am just dynamically updating ImageViews whenever cards are changed. The problem with Thread.sleep is all the images only update after Thread.sleep, there is no displaying only the human card before Thread.sleep. The human's card and computer's card display after Thread.sleep.
I've used Thread.sleep like so:
playPlayerCard(player); // Human first
displayPile(); // Display card pile (ImageView's)
player = nextPlayer(player); // Get's next player in Player mPlayers List<Player>
// Wait for computer to 'Think'
Thread.sleep(500);
playPlayerCard(player); //Computer's turn
displayPile(); // Display card pile (ImageView's)
Am I using Thread.sleep() wrong? Is there a better/correct way? I've searched online and tried using new Thread(), using handler.postDelayed(Runnable r, long milliseconds) and also CountDownTimer but none work since my variables: playPlayerCard(player); aren't final variables.
I've always had problems delaying actions and the images appearing at the correct times. Any suggestions? Thanks in advance.
Couldn't you just implement the Computer Playing logic in a AsyncTask and fire it when the human turn is done ?
I think it would make much more sense, that way, as soon as the computer is done "playing" you can determine the actions to take in the onPostExecute() method, in your case I think that would be dealing cards.
It would also be really simple to block user inputs while the computer is playing, either with a progress dialog (which isn't all that pleasent for a game I understand) or simply by disabling buttons :)
Here's the documentation for it.
Hope this helps!
I used the solution from #Jakar and changed my variables to class-scope in order to use the Handler and Runnable correctly. This worked, the delay works correctly using
Runnable r = new Runnable() {
public void run() {
playPlayerCard();
}
};
mHandler.postDelayed(r, 500);
To clarify the solution, I had to take out the arguments from playPlayerCard(Player player) and use a class-scope Player mPlayer; variable in playPlayerCard() instead.

Categories

Resources