Libgdx, Why Should I Use Constructors When Switching Screens? - memory-management

I am a beginner in libgdx and was wondering in what cases you would need to use a constructor when switching screens (examples would be helpful). Is it to save memory? Also, is it better to create instances of all the screens in the main class that extends the game?
Here is an example of instances from https://code.google.com/p/libgdx-users/wiki/ScreenAndGameClasses :
public class MyGame extends Game {
MainMenuScreen mainMenuScreen;
AnotherScreen anotherScreen;
#Override
public void create() {
mainMenuScreen = new MainMenuScreen(this);
anotherScreen = new AnotherScreen(this);
setScreen(mainMenuScreen);
}
}
The constructor is in the next class:
public class MainMenuScreen implements Screen {
MyGame game; // Note it's "MyGame" not "Game"
// constructor to keep a reference to the main Game class
public MainMenuScreen(MyGame game){
this.game = game;
}
...

You should avoid creating all screens in Game class in create() method (you will allocate much memory at once and pointlesly). Create only one screen at a time when do you need It. So e.g. you click button New game in menu and there you call game.setScreen(new NextScreen(this));
You do not have to make constructor with Game parameter - but you will not have reference to the main Game class. Having reference to main game class is good for changing screens, method setScreen(screen).

You need the constructor because your changing to a screen that doesnt extend the Game class which is what u need to call setScreen(); Since ur passing the game class to the constructor you can use it to get back to the screen you were at (or another screen) without creating another class that extends Game

I prefer using a singleton.
Something like
public class MyGame extends Game {
private static MyGame myGame;
public static MyGame getInstance() {
if (myGame == null) {
myGame = new MyGame();
}
return myGame;
}
#Override
public void create() {
setScreen(new MainMenuScreen();
}
}
And the example for desktop main class
public class Main {
public static void main(String[] args) {
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
cfg.width = 800;
cfg.height = 480;
new LwjglApplication(MyGame.getInstance(), cfg);
}
}
Now whenever you need to change your screen use MyGame.getInstance().setScreen(new ScreenName());

Related

What would be a good way to replace a static class used to hold Application settings?

I have an application that uses a static class to store settings:
namespace ABC
{
public static class MS
{
public static bool abc;
public static bool def;
...
}
}
When the app starts up it goes to the database and updates some of these settings.
I have been told that holding them in a static class is not ideal for when I am doing bindings and adding notification so I'm thinking I should new a class and the hold them in an instance. If that's the case can someone give me some advice. Should I do that when the application starts up and should it be in the constructor of the App() if that is the best way to do it then how can I do this. Any small 4-5 line example would be a big help
public partial class App : Application
{
public static xxx
public App()
{
AS.appUpdated = "Feb 1, 2017";
AS.appVersion = "0.1";
InitializeComponent();
MainPage = new MS.MainPage();
}
}
Have a look at James Montemagno's settings plugin.
https://github.com/jamesmontemagno/SettingsPlugin
This abstracts away a lot of the plumbing around settings and persisting them locally. Calling one of your settings from anywhere in your application then becomes as simple as calling Settings.MySettingName.
When it comes to binding these values to a view I would always create a property for them in your view model that simply returns the value from the settings. If need be you can put them in a base viewmodel and go from there.
public class MyViewModel : BaseViewModel
{
}
public class BaseViewModel
{
public bool SettingA => Settings.SettingA;
public bool SettingB => Settings.SettingB;
}

Java: Call method in Controller from another class? [duplicate]

I would like to communicate with a FXML controller class at any time, to update information on the screen from the main application or other stages.
Is this possible? I havent found any way to do it.
Static functions could be a way, but they don't have access to the form's controls.
Any ideas?
You can get the controller from the FXMLLoader
FXMLLoader fxmlLoader = new FXMLLoader();
Pane p = fxmlLoader.load(getClass().getResource("foo.fxml").openStream());
FooController fooController = (FooController) fxmlLoader.getController();
store it in your main stage and provide getFooController() getter method.
From other classes or stages, every time when you need to refresh the loaded "foo.fxml" page, ask it from its controller:
getFooController().updatePage(strData);
updatePage() can be something like:
// ...
#FXML private Label lblData;
// ...
public void updatePage(String data){
lblData.setText(data);
}
// ...
in the FooController class.
This way other page users do not bother about page's internal structure like what and where Label lblData is.
Also look the https://stackoverflow.com/a/10718683/682495. In JavaFX 2.2 FXMLLoader is improved.
Just to help clarify the accepted answer and maybe save a bit of time for others that are new to JavaFX:
For a JavaFX FXML Application, NetBeans will auto-generate your start method in the main class as follows:
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
Now, all we need to do to have access to the controller class is to change the FXMLLoader load() method from the static implementation to an instantiated implementation and then we can use the instance's method to get the controller, like this:
//Static global variable for the controller (where MyController is the name of your controller class
static MyController myControllerHandle;
#Override
public void start(Stage stage) throws Exception {
//Set up instance instead of using static load() method
FXMLLoader loader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
Parent root = loader.load();
//Now we have access to getController() through the instance... don't forget the type cast
myControllerHandle = (MyController)loader.getController();
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
Another solution is to set the controller from your controller class, like so...
public class Controller implements javafx.fxml.Initializable {
#Override
public void initialize(URL location, ResourceBundle resources) {
// Implementing the Initializable interface means that this method
// will be called when the controller instance is created
App.setController(this);
}
}
This is the solution I prefer to use since the code is somewhat messy to create a fully functional FXMLLoader instance which properly handles local resources etc
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("/sample.fxml"));
}
versus
#Override
public void start(Stage stage) throws Exception {
URL location = getClass().getResource("/sample.fxml");
FXMLLoader loader = createFXMLLoader(location);
Parent root = loader.load(location.openStream());
}
public FXMLLoader createFXMLLoader(URL location) {
return new FXMLLoader(location, null, new JavaFXBuilderFactory(), null, Charset.forName(FXMLLoader.DEFAULT_CHARSET_NAME));
}
On the object's loading from the Main screen, one way to pass data that I have found and works is to use lookup and then set the data inside an invisible label that I can retrieve later from the controller class. Like this:
Parent root = FXMLLoader.load(me.getClass().getResource("Form.fxml"));
Label lblData = (Label) root.lookup("#lblData");
if (lblData!=null) lblData.setText(strData);
This works, but there must be a better way.

Libgdx multiple screens

Thanks to the help I got with my other problems on this forum, I managed to advance my project, but yet another obstacle appears in my way.
I am having trouble implementing multiple Screens in libgdx for java. I would like to know how can I implement multiple screens (one for the main menu, one for play, one for loading screen, ...).
An example or some explanations of how should I structure my screen classes would be really helpful. I tried implementing my own screen manager but that didn't go very well... Also some pointers on how should I dispose screens, since creating screens every time you go from main menu to play or to options menu isn't a very good idea. Any ideas or code example or advice is much appreciated.
What I have now are some classes of game screens which when you render them they will draw some GUI on the screen, but functions like the back button don't work since I don't know how to make the link between them.
Let's say you got 3 screens, MainMenuScreen, OptionsScreen, GameScreen.
First you need to declare them in your main class.
It will look like this
public class MainClass extends Game implements ApplicationListener {
private GameScreen gameScreen;
private MenuScreen menuScreen;
private OptionsScreen optionsScreen;
#Override
public void create() {
}
setGameScreen()
{
gameScreen=new GameScreen(this);
setScreen(gameScreen);
}
setMenuScreen()
{
menuScreen=new menuScreen(this);
setScreen(menuScreen);
}
setOptionsScreen()
{
optionsScreen=new OptionsScreen(this);
setScreen(gameScreen);
}
#Override
public void dispose() {
super.dispose();
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
super.render();
}
#Override
public void resize(int width, int height) {
super.resize(width, height);
}
#Override
public void pause() {
super.pause();
}
#Override
public void resume() {
super.resume();
}
}
Now every screen you got, needs to have a MainClass variable and a constructor of it.
Lets say for the GameScreen class, it will be like
public class GameScreen implements Screen{
private MainClass mainClass;
public GameScreen(MainClass mc)
{
mainClass=mc;
}
// your methods (show,render, pause, etc)
}
Now when you want to change the screen just use in your screen
mainClass.setMenuScreen();

Trying to move my object initialisation and method calls out of my Main method

I am trying to move some code out of the main method and use it in another class. The reason for doing this is that I learnt it was advised convention to do so and I am relatively new to Java so looking to try it out. Currently when I move the code into the 'Game' class I cannot resolve the errors that eclipse is showing.
Any help would be appreciated.
Main method in playGame class-
public class playGame {
public static void main(String[] args) {
// TODO Auto-generated method stub
player playerOne = new player();
GameHelper gameHelper = new GameHelper();
wordManipulator thisWord = new wordManipulator();
gameHelper.showDisplay();
playerOne.setPlayerName();
gameHelper.showIntro(playerOne.getPlayerName());
thisWord.showHiddenWord();
playerOne.setPlayerGuess();
}
}
The Game class
public class Game {
//other code for the game logic
}
Make sure to put your code in a method in the Game class, and then call that specific method.
Another hint : use capitals for class names.

BlackBerry - Fun with FieldManagers

I am trying to make a View class that provides a Horizontal or Vertical layout depending on how it is created. I'm using a delegate to achieve this.
class View extends Manager {
private Manager mDelegate;
public View(Manager inDelegate) {
mDelegate = inDelegate;
// the delegate is the only child of "this" manager.
super.add(mDelegate);
}
public void add(Field f) {
// all other children go into the delegate.
mDelegate.add(f);
}
// other methods that also delegate
}
When I instantiate a View object I pass in a Horizontal or Vertical field manager and then delegate calls to that. This is kinda what the Screen class does in blackberry.
Actually I am looking at the blackberry docs for Screen to see what calls it delegates (so I can emulate that) and I notice calls like this in Screen...
protected boolean keyChar(char c, int status, int time)
Delegates key generation event to the controlled field with focus.
This method invokes Manager.keyChar(char, int, int) on this screen's delegate manager.
So then it immediately dawns on me, how in the world are they calling a protected method on the screen's delegate? Or are the docs wrong and this method isn't delegated?
Anyone know how they accomplish this?
Reminding myself what protected means:
A protected method can be called by
any subclass within its class, but not
by unrelated classes.
This doesn't directly answer your question, but could you extend Screen (API here) instead of Manager and then call super(mDelegate) in your constructor? Then presumably whatever magic is necessary will just work?
Aside from that I would just suggest you try it and see if you can override the supposedly protected method!
I managed to work out a solution to this problem with help from some other SO questions.
My solution is to create an interface that provides the public access points for the protected methods and then subclass the Manager class and mix in that interface. The public method will then call its super's protected method.
Then the View class is then passed one of these Manager subclasses.
public interface ManagerDelegate {
Manager asManager();
// Provide public access points to any protected methods needed.
void doProtectedMethod();
}
public HorizontalDelegate extends HorizontalFieldManager implements ManagerDelegate {
public Manager asManager() {
return this;
}
public void doProtectedMethod() {
// call the Manager's protected method.
protectedMethod();
}
}
public VerticalDelegate extends VerticalFieldManager implements ManagerDelegate {
public Manager asManager() {
return this;
}
public void doProtectedMethod() {
// call the Manager's protected method.
protectedMethod();
}
}
public class View extends Manager {
private final ManagerDelegate mDelegate;
public View(ManagerDelegate inDelegate) {
mDelegate = inDelegate;
}
protected void protectedMethod() {
// Call into our delegate's public method to access its protected method.
mDelegate.doProtectedMethod();
}
public void publicMethod() {
// For public delegated methods I can just get the Manager instance from
// the delegate and call directly.
mDelegate.asManager().publicMethod();
}
}

Resources