I want to save a highScore in my game made with libGDX.
I tried to use this tutorial :
http://niklasnson.com/programming/network/tips%20and%20tricks/2017/09/15/libgdx-save-and-load-game-data.html
There is my code :
GameData.class :
public class GameData {
private static double highScore;
public static double getHighScore() {
return highScore;
}
public static void setHighScore(double hs) {
highScore = hs;
}
}
PlayState.class :
#Override
public void render(SpriteBatch sb) {
[...]
if(GameData.getHighScore() < score) {
GameData.setHighScore(score);
}
[...]
sb.end();
}
MenuState.class :
public class MenuState extends State {
private BitmapFont font = new BitmapFont();
private String HS = String.valueOf(GameData.getHighScore());
DecimalFormat df = new DecimalFormat("#.#");
#Override
public void render(SpriteBatch sb) {
sb.begin();
[...]
font.draw(sb, "Score : " + HS, 20, 400);
sb.end();
}
}
Unfortunately, my highscore is reset each time a start a new game.
Where is my mistake ? I hope my question is not too stupid and I not forget something in my code here. Please forgive me in that case.
Thank you very much in advance.
Best regards,
Tenecifer
You are never saving the highscore, you just store it inside of a variable.
You are using a static variable but these are not saved after restarting your program.
I think LibGDX Preferences is that what you're searching for.
You can read about it here in their wiki.
Update your setHighscoreMethod:
First put in this line:
Preferences prefs = Gdx.app.getPreferences("My Preferences");
After that you can start storing your highscore, e.g.:
prefs.putInteger("highscore", 10);
After editing make sure to save:
prefs.flush();
You will also have to update the getHighscore method.
To read the saved highscore just call:
prefs.getInteger("highscore", 0);
Then 0 is the value that should be returned when no highscore is saved yet.
Actually you are not persisting highScore anywhere outside of your application instance context. Such private field as in your GameData will be destroyed as soon as you will close the game. Think about Word document window on your PC and what will happen if you will suddenly turn off your computer - it will dissapear, with the content, after reboot unless you will save it to the HDD
To save object to the persistent memory in LibGDX you can use Preferences
Preferences prefs = Gdx.app.getPreferences("My Preferences");
// Persist some value
prefs.putString("name", "Donald Duck");
prefs.flush();
// And load it after application restart (or event without restart)
String name = prefs.getString("name", "No name stored"); // 'No name stored' is default value in case such key does not exist
You can also implement some cloud service to keep your game state (and even share it between devices) like Saved Games from Google Services or App42 API from Shephertz (creators od AppWarp)
Related
I have a problem with save the value of string or editText in java android. When I redirect from FirstActivity to Second and return after it to First, I need that a String that i fill earlier stay in the place that I wrote it. (Like a cookies in js).
You could use shared preferences for this process.
In that case, Best practise to create SharedPreference and for global usage, you need to create a global class like below:
public class PreferenceHelper {
private final SharedPreferences mPrefs;
public PreferenceHelperDemo(Context context) {
mPrefs = getApplicationContext().getSharedPreferences("MyPref", 0); // 0 -for private mode
}
private String PREF_Key= "Key";
public String getKey() { // To retrieve data
String str = mPrefs.getString(PREF_Key, null);
return str;
}
public void setKey(String pREF_Key) { // To store and edit Data
Editor mEditor = mPrefs.edit();
mEditor.putString(PREF_Key, pREF_Key);
mEditor.commit();
}
public void clearData(string pREF_Key){ // To delete data
editor.remove(pREF_Key);
editor.commit();
}
}
Then you could use these functions with global class in your activity class to store, retrieve and delete the shared preference data.
Hope this will solve your problem!
Having an issue with tables and updating a label! Here is the dilemma, I have a sell button in my game that is updating the player's coins whenever they sell an item, that part is working perfectly. The issue I am having is trying to get the coin value to update on the screen while there in this separate menu (see pic attached, coins in the top left). The problem is that the coin value is in another stage in another class. This is because I have different tables that pop up in the middle when I click the different buttons at the bottom. I have tried helper methods for going in and clearing that table and updating it and then sending me back to this item page but it is not working, I can post any code needed but this is more of a general question on how to update a label within a table in a stage.
Update: So to kinda sum up my question, I have a Screen and I have have three tables in it the bottom table the top left and the top right. Then I add the table to the stage in the middle when they press the inventory or shop button etc. What I am looking to do is to keep the item page open and simply just update the value of the Coin label, I know I can change the text using .setText(); Im just not sure how I can update that portion of the screen etc..
Update 2: If I just set the screen back to a new screen of this screen it updates the coin value but then I am not on the item page anymore which is not ideal.
Update 3: Thanks for the help so far guys, #John your answer is super helpful aswell. Im still not getting this working though here is a little bit of the code where the label is being handled.
playerCoinLabel = new Label(playerSave.getCoinsString(),skin,"defaultMiddle");
This is where it is getting added to the table.
tableLeft = new Table(skin);
stage.addActor(tableLeft);
tableLeft.setBounds(0,0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
tableLeft.setFillParent(true);
tableLeft.top().left();
tableLeft.add(healthNonButton).size(84,80).left().padLeft(10).padTop(5);
tableLeft.add(playerHealthLabel).left().padLeft(15);
tableLeft.row();
tableLeft.add(levelNonButton).size(74,70).center().padLeft(10);
tableLeft.add(playerLevelLabel).left().padLeft(19);
tableLeft.row();
tableLeft.add(coinNonButton).size(74,70).center().padLeft(10);
tableLeft.add(this.playerCoinLabel).left().padLeft(15); //This line
tableLeft.row();
Then I have this method for updating my label using the setText like you guys were telling me about.
public void updatePlayerCoins() {
playerCoinLabel.setText(playerSave.getCoinsString());
}
and if I call this method anywhere, render() or where im setting the new coin value it is not updating/changing the label in the top left of my screen. I can post all the code to a github if I need to just posted the things involving the label. This is just a project im working on to increase my skill set so sorry if I sound amateur, it is because I am!
Thanks everyone!
It seems like you're asking two things- how do I update a label? and How do I structure my code? It's hard to tell what's going wrong with the former since we can't see your code, but #Tenfour04 is right- you want to retain a reference to the label somewhere and call setText() when you want to change the amount.
As far as structuring your code, I would suggest a simple OOP design and then evolve it like so:
First, we need an object to represent the player:
class Player {
private int coins; // Pretend there are getters / setters.
private int health;
private int level;
}
Now you probably have more than one way that you want to represent this player information, so we'll split the rendering code into a separate class or set of classes:
class StatWidget {
private Stage stage;
private Player player;
private Label lblCoins;
public StatWidget(Player player) { // Pseudo-code
this.player = player;
this.stage = new Stage();
Table tbl = new Table();
this.lblCoins = new Label(); // Notice we keep a reference to the label
tbl.add( this.coins );
}
public void update() {
lblCoins.setText(player.getCoins());
}
}
Now you can sync the UI with your player object's state simply by calling Player#update(). But when do you call it?
You could call update() in your render method. This is a little inefficient because you're updating the object whether it needs to be updated or not, but it's dead simple, and if you're only updating a few UI elements this way it probably doesn't matter. Personally, I'd stop here.
If you want to be more precise, you would only call update() when you actually make a change to the Player's coins. You can do this by finding the places in your code where you set the player's coins and add the update call like so:
player.setCoins( A_LOT_OF_MONEY );
statWidget.update();
Problem is this gets more cumbersome as you add more widgets- all your game logic now has to know about StatWidget and make calls to it. We could cut this dependency a little bit by using an event-driven architecture. Essentially, whenever player's state changes, it would send an event to interested parties notifying them of the change. You could use the pseudo-code below:
interface Publisher {
void subscribe(Subscriber subby);
void unsubscribe(Subscriber subby);
}
class Player implements Publisher {
private List<Subscriber> subscribers;
private int coins;
// ...
public void setCoins(int amount) {
this.coins = amount;
for(Subscriber subscriber : subscribers) subscriber.notify("COINS", amount);
}
public void subscribe(Subscriber subby) {
this.subscribers.add(subby);
}
public void unsubscribe(Subscriber subby) {
this.subscribers.remove(subby);
}
}
interface Subscriber {
void notify(String event, int qty);
void dispose();
}
class StatWidget implements Subscriber {
private Publisher player;
private Label label;
// ...
public StatWidget(Player player) {
this.player = player;
this.player.addSubscriber(this);
void notify(String event, int qty) {
if(event.equals("COINS")) label.setText(qty);
}
void dispose() {
this.player.unsubscribe(this);
}
}
The event system above could certainly be polished, and you could likely do clever things with generics (or use a library that has thought all this out for your), but hopefully it illustrates the concepts.
My app will carry two scores the entire time, calling them, adding to them, saving them, and later calling them back again for other functions and editing. What is the best method for this? These will be the only numbers needed throughout the app.
All I am looking for is the most efficient option I should implement. And if possible a simple example of making, editing, saving and recalling. Thank you.
I suggest using SharePreferences because you are only need to store very small data.
Hint:
synchronized void saveScores(final Context contex, final String scoreOneKey, final String scoreTwoKey, final Integer scoreOne, final Integer scoreTwo){
final SharedPreferences sharedPreferences = context.getSharedPreferences("user.score.key", Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS)
final SharedPreferences.Editor preferencesEditor = sharedPreferences.edit();
preferencesEditor.putInt(scoreOneKey, scoreOne);
preferencesEditor.putInt(scoreTwoKey, scoreTwo);
preferencesEditor.commit();
}
Things to Note here are:
You are method must synchronized as multiple threads can access the game score.
Notice the sharedPreference access controls (MODE_PRIVATE | MODE_MUTI_PROCESS) that tells the OS that this sharedPreference is not accessible by other apps but at same time it is possible to access it from multiple process of your app ( if you can even encrypt the scores before saving them.)
UpdatedYou can use SharedPreferences To save Scores When you will call getFirstScore() first Time it will return 0 as the variable is not yet created and then you can call setFirstScore() to save it.
public class ScoreDatabase{
private Context context;
private SharedPreferences pref;
private SharedPreferences.Editor editor;
public ScoreDatabase(Context context){
this.context=context;
pref = context.getSharedPreferences("MY_PREFS", Context.MODE_PRIVATE);
editor = pref.edit();
}
public int getFirstScore() {
return pref.getInt("FIRST_SCORE", 0);
}
public int getSecondScore() {
return pref.getInt("SECOND_SCORE", 0);
}
public void setFirstScore(int score) {
editor.putInt("FIRST_SCORE", score);
editor.commit();
}
public void setSecondScore(int score) {
editor.putInt("SECOND_SCORE", score);
editor.commit();
}
}
Now make instance of this class and use anywhere you want just pass getApplicationContext() in the constructor
//In your MainActivity class
ScoreDatabase scoreDatabase=new ScoreDatabase(getApplicationContext());
//call set function when you want to set score
scoreDatabase.setFirstScore(10);
scoreDatabase.setSecondScore(20);
//Call get function when you want to get score
int firstScore=scoreDatabase.getFirstScore();
int secondScore=scoreDatabase.getSecondScore();
Okay, so I have this code below and I keep getting run-time errors and I'm thinking its a flaw in the codes logic. I'm trying to use the setOneOtherPicture method to pick a picture and set it into an array to be later called on to be displayed in the showArtCollection method. I've been given two parameters, which and pRef. Can someone help me with this? Thanks.
public class House
{
String owner;
Picture pRef;
Picture favPic;
Picture [] picArray = new Picture [3];
public void showArtCollection ()
{
ArtWall aWall = new ArtWall(600,600);
aWall.copyPictureIntoWhere(favPic,250,100);
aWall.copyPictureIntoWhere(pRef,51,330);
aWall.copyPictureIntoWhere(pRef,151,330);
aWall.copyPictureIntoWhere(pRef,351,280);
aWall.show();
}
public void setOneOtherPicture (int which, Picture pRef)
{
this.picArray [which] = new Picture (FileChooser.pickAFile ());
}
public static void main (String [] args)
{
House PhDsHouse = new House ("Mad PH.D.");
Picture favPic = new Picture ();
Picture pRef = new Picture ();
PhDsHouse.setOneOtherPicture (0, pRef);
PhDsHouse.setOneOtherPicture (1, pRef);
PhDsHouse.setOneOtherPicture (2,pRef);
PhDsHouse.showArtCollection ();
}
Your House class has several fields, and your main method has local variables with the same names. Perhaps these should be sent into the constructor? Otherwise, these fields are null, which causes the crash in the showArtHouse method.
this method:
public void setOneOtherPicture (int which, Picture pRef)
{
this.picArray [which] = new Picture (FileChooser.pickAFile ());
}
shouldn't be calling FileChooser, and it shouldn't even be creating a new Picture object, but instead should just be putting pRef Picture object that you already have passed into the method into the array. Otherwise you're just throwing the pRef parameter away -- makes no sense.
I have a Settings activity in my android application which purpose is to save preferences upon an item selection. My problem is, my settings don't get saved. The following method is called every time a user selection is made:
public void savePreferences()
{
defaultVolumeUnit = MySingleton.getInstance().getDefaultVolumeUnit();
defaultPressureUnit = MySingleton.getInstance().getDefaultPressureUnit();
defaultTempUnit = MySingleton.getInstance().getDefaultTempUnit();
settings = getSharedPreferences(SettingsTAG, 0);
Editor editor = settings.edit();
editor.putInt("selectVolume", defaultVolumeUnit);
editor.putInt("selectPressure", defaultPressureUnit);
editor.putInt("selectTemperature", defaultTempUnit);
editor.commit();
}
I also use the following code in my MAIN activity where all the settings get restored upon start up:
public void restoreValues()
{
settings = getSharedPreferences(SettingsTAG, 0);
int SelectedVolume = settings.getInt("selectVolume", 0);
int SelectedPressure = settings.getInt("selectPressure", 0);
int SelectedTemperature = settings.getInt("selectTemperature", 0);
// Necessary assignments here...
}
I use global variables throughout my whole application and those get saved but the settings do not. I'm positive that both savePreferences() and restoreValues() method gets called but whatever the user had selected doesn't get saved.
In other words, nothing gets saved/restored. I don't know what I'm doing wrong but this issue has been driving me nuts. This used to work for me before but I'm doing a Settings UI revamp and the same code suddenly isn't working...
Any help please?
Think you should be doing this in your activity:
private SharedPreferences prefSettings;
public void restoreValues()
{
prefSettings = PreferenceManager.getDefaultSharedPreferences(this);
int SelectedVolume = prefSettings.getInt("selectVolume", 0);
int SelectedPressure = prefSettings.getInt("selectPressure", 0);
int SelectedTemperature = prefSettings.getInt("selectTemperature", 0);
// Necessary assignments here...
}
In your method that I've noticed, your parameters do not look right actually...why are you using SettingsTAG, with 0 as parameters to the getSharedPreference method? Is your activity extending PreferenceActivity? You should be using the context.
public void savePreferences()
{
defaultVolumeUnit = MySingleton.getInstance().getDefaultVolumeUnit();
defaultPressureUnit = MySingleton.getInstance().getDefaultPressureUnit();
defaultTempUnit = MySingleton.getInstance().getDefaultTempUnit();
//settings = getSharedPreferences(SettingsTAG, 0);
settings = PreferenceManager.getDefaultSharedPreferences(context); // Notice CONTEXT!
Editor editor = settings.edit();
editor.putInt("selectVolume", defaultVolumeUnit);
editor.putInt("selectPressure", defaultPressureUnit);
editor.putInt("selectTemperature", defaultTempUnit);
editor.commit();
}
Edit:
If you want to debug it, it might be better to do it this way:
public class PreferencesActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener{
private static final String TAG = "PreferencesActivity";
///.... code....
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key){
Log.d(TAG, "onSharedPreferenceChanged() - key = " + key);
// Yup! The key within the shared preferences was changed... inspect 'em via Log!
}
The reason: you're "listening" on the changes whenever its made to confirm that you are indeed saving the preferences. When you're done with debugging, be sure to take out the Log calls so that it does not appear in the logcat.