2017-03-23 38 views
2

我已經完成了一些研究,並且發現了很多關於如何在應用程序(LibGDX)中存儲關卡,高分,選項等數據的文章。但這些解決方案都不適合我。我閱讀了類Preferences的LibGDX描述並搜索了StackOverflow以獲取如何使用它的答案。LibGDX And​​roid偏好 - 如何將數據保存到應用程序

所有我想要做的就是保存應用的水平,因此用戶不必再輸入應用

首選項(LibGDX)時重新開始 - https://github.com/libgdx/libgdx/wiki/Preferences

但是,當我輸入了libGDX向我展示的代碼。使用首選項時,是否足以輸入此代碼或是否還需要執行其他操作?

// LibGDX - create() 
Preferences prefs = Gdx.app.getPreferences("My Preferences"); 

// LibGDX - render() 
prefs.putString("name", "Donald Duck"); 
String name = prefs.getString("name", "No name stored"); 

prefs.putBoolean("soundOn", true); 
prefs.putInteger("highscore", 10); 

// bulk update your preferences 
prefs.flush(); 

在完成這些之後,我必須獲取寫入名爲「我的首選項」的文件的數據並從中獲取它?但是,自從LibGDX顯示Windows的路徑後,我在哪裏可以在Android中找到該文件。

%UserProfile%/.prefs/My Preferences 

順便說一句,我需要使用這個類之前創建了一個名爲「我的首選項」文件,或將首選項創建文件本身?

LibGDX提供的代碼是否按特定順序放置?我知道我必須先創建一個Preferences參數,然後創建要存儲在文件中的值。但除此之外呢?我是否使用錯誤的LibGDX方法將代碼放入? (create(),render())。

我試圖剛剛從一個鏈接編寫代碼

Preferences pref = Gdx.app.getPreferences("somefile"); 
pref.putString("name", "Menyo"); 
pref.putInteger("level", 20); 

只是爲了看看它的工作。但它似乎並不像它那樣。我在代碼中丟失了什麼嗎?或者它是我缺少的需要創建的文件?

研究鏈接:

Using LibGDX with Android Preferences

Android libgdx preferences not working

http://www.badlogicgames.com/forum/viewtopic.php?f=11&t=6365#p32981

How do apps save data

Android libgdx preferences not working

編輯:

我得到了我問的解釋,但我需要更多的信息。在我的LibGDX應用程序中,我有方法渲染,並且在該方法中我有menu(),game()。我不應該在渲染方法中調用首選項?它們應該在哪裏被調用,因爲如果它們在create()方法中,它們只會被調用一次?

我想我退出應用程序時可以調用Preferences(Prefs)方法來保存關卡數據。但它不起作用,應用程序仍然回到第一級。所以我決定在這裏發佈我的代碼,這樣每個人都可以看到我做錯了什麼。

(可以使用CTRL + F找到變量 「水平」 和 「首選項」 無處不在的代碼)

package com.game.whatstheanswer; 

import com.badlogic.gdx.ApplicationAdapter; 
import com.badlogic.gdx.Gdx; 
import com.badlogic.gdx.Input; 
import com.badlogic.gdx.InputProcessor; 
import com.badlogic.gdx.graphics.Color; 
import com.badlogic.gdx.graphics.GL20; 
import com.badlogic.gdx.graphics.Texture; 
import com.badlogic.gdx.graphics.g2d.BitmapFont; 
import com.badlogic.gdx.graphics.g2d.GlyphLayout; 
import com.badlogic.gdx.graphics.g2d.SpriteBatch; 
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator; 
import com.badlogic.gdx.graphics.glutils.ShapeRenderer; 

public class MyGdxGame extends ApplicationAdapter implements InputProcessor { 
private SpriteBatch batch; 

private GAME STATE; 
private BitmapFont font; 
private BitmapFont fontTextAdjustment; 
private GlyphLayout layout; 
private String message; 

private Texture logo; 
private Texture questionmarks; 
private Texture keyboard; 

private Texture btnReset; 
private Texture btnMenu; 

@Override 
public void create() { 
    batch = new SpriteBatch(); 

    // Configure the Android keyboard 
    Gdx.input.setInputProcessor(this); 
    isAndroidKeyboardShowing = true; 

    // Menu logo 
    logo = new Texture("logo.png"); 
    questionmarks = new Texture("questionmarks.png"); 
    //level = 1; 

    STATE = GAME.MENU; 
    btnPlay = new Texture("play.png"); 
    btnInfo = new Texture("info.png"); 
    btnQuit = new Texture("quit.png"); 

    // The game over menu 
    btnMenu = new Texture("menu.png"); 
    btnReset = new Texture("reset.png"); 

    FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("Amethysta.ttf")); 
    FreeTypeFontGenerator.FreeTypeFontParameter parameter = new FreeTypeFontGenerator.FreeTypeFontParameter(); 
    parameter.size = 66; 
    font = generator.generateFont(parameter); // font size 66 pixels 

    parameter.size = 28; 
    fontTextAdjustment = generator.generateFont(parameter); 
    generator.dispose(); // don't forget to dispose to avoid memory leaks! 


    layout = new GlyphLayout(); 

    keyboard = new Texture("keyboard/keyboard.png"); 

    userInput = ""; 
    message = ""; 
    /* 
    prefs = Gdx.app.getPreferences("com.game.whatstheanswer.settings"); 
    String name = prefs.getString("Level", "0");*/ 

    prefs = new Prefs(); 
} 

private Prefs prefs; 
//private static Preferences prefs; 

//private String letter; 
private String userInput; 
private String answer; 
private int level; 

@Override 
public void render() { 
    Gdx.gl.glClearColor(255, 255, 255, 1); 
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); 

    batch.begin(); 

    //STATE = GAME.OVER; 
    switch (STATE) { 
     case MENU: menu(); break; 
     case PLAY: 
      Gdx.gl.glClearColor(0, 0, 0, 1); 
      Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); 
      game(); 
      break; 
     case PAUSE: break; 
     case RESUME: break; 
     case OVER: gameComplete(); break; 
    } 
    batch.end(); 
} 

private Texture btnPlay, btnInfo, btnQuit; 
private void menu() { 
    // Draw a colorful background 
    batch.draw(logo, Gdx.graphics.getWidth()/2 - logo.getWidth()/2, Gdx.graphics.getHeight() - logo.getHeight()); 
    batch.draw(questionmarks, Gdx.graphics.getWidth()/2 - logo.getWidth()/2, Gdx.graphics.getHeight() - logo.getHeight() - 460); 
    batch.draw(btnPlay, Gdx.graphics.getWidth()/2 - btnPlay.getWidth()/2, 600); 
    batch.draw(btnInfo, Gdx.graphics.getWidth()/2 - btnInfo.getWidth()/2, 400); 
    batch.draw(btnQuit, Gdx.graphics.getWidth()/2 - btnQuit.getWidth()/2, 200); 

    // Play button 
    if (Gdx.input.justTouched() && 
      Gdx.input.getX() >= Gdx.graphics.getWidth()/2 - btnPlay.getWidth()/2 && 
      Gdx.input.getX() <= (Gdx.graphics.getWidth()/2 - btnPlay.getWidth()/2) + btnPlay.getWidth() && 
      Gdx.input.getY() >= Gdx.graphics.getHeight() - 600 - btnPlay.getHeight() && 
      Gdx.input.getY() <= Gdx.graphics.getHeight() - 600) { 
     STATE = GAME.PLAY; 
     isAndroidKeyboardShowing = true; 
     System.out.println("Main Menu: Play"); 
    } 

    // Info button 
    if (Gdx.input.justTouched() && 
      Gdx.input.getX() >= Gdx.graphics.getWidth()/2 - btnPlay.getWidth()/2 && 
      Gdx.input.getX() <= (Gdx.graphics.getWidth()/2 - btnPlay.getWidth()/2) + btnPlay.getWidth() && 
      Gdx.input.getY() >= Gdx.graphics.getHeight() - 400 - btnPlay.getHeight() && 
      Gdx.input.getY() <= Gdx.graphics.getHeight() - 400) { 
     System.out.println("Main Menu: Info"); 
    } 

    // Quit button 
    if (Gdx.input.justTouched() && 
      Gdx.input.getX() >= Gdx.graphics.getWidth()/2 - btnPlay.getWidth()/2 && 
      Gdx.input.getX() <= (Gdx.graphics.getWidth()/2 - btnPlay.getWidth()/2) + btnPlay.getWidth() && 
      Gdx.input.getY() >= Gdx.graphics.getHeight() - 200 - btnPlay.getHeight() && 
      Gdx.input.getY() <= Gdx.graphics.getHeight() - 200) { 
     level = prefs.getLevel(); 
     Gdx.app.exit(); 
     System.out.println("Main Menu: Quit"); 
    } 
} 

/* 
public void increaseLevel() { 
    prefs.putString("Level", String.valueOf(level)); 
    prefs.flush(); 
    Gdx.app.log("level", level+""); 
}*/ 

private void game() { 
    // Set the color of the text 
    font.setColor(Color.WHITE); 

    level = prefs.getLevel(); 
    /* 
    font.draw(batch, "MENU", 120, Gdx.graphics.getHeight() - 80); 
    font.draw(batch, "CLEAR", 420, Gdx.graphics.getHeight() - 80); 
    font.draw(batch, "SOLVE", 740, Gdx.graphics.getHeight() - 80);*/ 

    font.draw(batch, "MENU", Gdx.graphics.getWidth()/7, Gdx.graphics.getHeight() - 80); 
    font.draw(batch, "CLEAR", (((7/2)*Gdx.graphics.getWidth()/7)), Gdx.graphics.getHeight() - 80); 
    font.draw(batch, "SOLVE", 5*Gdx.graphics.getWidth()/7, Gdx.graphics.getHeight() - 80); 

    System.out.println(userInput); 

    layout.setText(font, "Question " + level); 
    font.draw(batch, "Question " + level, Gdx.graphics.getWidth()/2 - layout.width/2, 5*Gdx.graphics.getHeight()/6); 

    switch (level) { 
     default: break; 
     // my cases are in here, removed them to shortned the code 
     case 1: break; 
     case 2: break; 
     ... 
     case n: break; 
    } 

    // The user input 
    layout.setText(font, userInput); 
    font.draw(batch, userInput, Gdx.graphics.getWidth()/2 - layout.width/2, 880); 

    //layout.setText(font, letter = "Q"); 

    drawnKeyboard(); 
    inputKeyboard(); 

    ShapeRenderer shapeRenderer = new ShapeRenderer(); 
    shapeRenderer.begin(ShapeRenderer.ShapeType.Line); 
    shapeRenderer.setColor(com.badlogic.gdx.graphics.Color.WHITE); 

    // Horizontal line, user input above it 
    shapeRenderer.rectLine(110, 800, Gdx.graphics.getWidth() - 110, 800, 4); // shapeRenderer.rectLine(120, 800, 940, 800, 4); 

    shapeRenderer.end(); 

} 

// Questions on one line 
private void msgOneLine(String message, String answer) { 
    this.message = message; 
    this.answer = answer; 
    layout.setText(font, message); 
    font.draw(batch, message, (Gdx.graphics.getWidth()/2) - layout.width/2, 1200); 
} 

private void msgTwoLines(String msg1, String msg2, String answer) { 
    this.message = msg1; 
    this.answer = answer; 
    layout.setText(fontTextAdjustment, message); 
    font.draw(batch, message, (Gdx.graphics.getWidth()/2) - layout.width - 80, 1200); 
    message = msg2; 
    layout.setText(fontTextAdjustment, message); 
    font.draw(batch, message, (Gdx.graphics.getWidth()/2) - layout.width - 80, 1200 - layout.height - 50); 
} 

private void msgThreeLines(String msg1, String msg2, String msg3, String answer) { 
    this.message = msg1; 
    this.answer = answer; 
    layout.setText(fontTextAdjustment, message); 
    font.draw(batch, message, (Gdx.graphics.getWidth()/2) - layout.width - 80, 1200); 

    message = msg2; 
    layout.setText(fontTextAdjustment, message); 
    font.draw(batch, message, (Gdx.graphics.getWidth()/2) - layout.width - 80, 1200 - layout.height - 50); 

    message = msg3; 
    layout.setText(fontTextAdjustment, message); 
    font.draw(batch, message, (Gdx.graphics.getWidth()/2) - layout.width - 80, 1200 - layout.height - 120); 
} 

private void msgFourLines(String msg1, String msg2, String msg3, String msg4, String answer) { 
    this.message = msg1; 
    this.answer = answer; 
    layout.setText(fontTextAdjustment, message); 
    font.draw(batch, message, (Gdx.graphics.getWidth()/2) - layout.width - 80, 1200); 

    message = msg2; 
    layout.setText(fontTextAdjustment, message); 
    font.draw(batch, message, (Gdx.graphics.getWidth()/2) - layout.width - 80, 1200 - layout.height - 50); 

    message = msg3; 
    layout.setText(fontTextAdjustment, message); 
    font.draw(batch, message, (Gdx.graphics.getWidth()/2) - layout.width - 80, 1200 - layout.height - 120); 

    message = msg4; 
    layout.setText(fontTextAdjustment, message); 
    font.draw(batch, message, (Gdx.graphics.getWidth()/2) - layout.width - 80, 1200 - layout.height - 190); 
} 

private void drawnKeyboard() { 

    batch.draw(keyboard, 440, 400); 

} 

private boolean isAndroidKeyboardShowing; 
private void inputKeyboard() { 
    if (Gdx.input.justTouched()) { 
     System.out.println("(" + Gdx.input.getX() + ", " + Gdx.input.getY() + ")"); 

     // ####################### BOTTOM BUTTONS ####################### 

     // Menu button 
     if (Gdx.input.getX() > 76 && Gdx.input.getX() < 350 && Gdx.input.getY() > 40 && Gdx.input.getY() < 116) { 
      STATE = GAME.MENU; 
      isAndroidKeyboardShowing = false; 
     } 

     // Clear button 
     if (Gdx.input.getX() > 350 && Gdx.input.getX() < 676 && Gdx.input.getY() > 40 && Gdx.input.getY() < 116) { 
      userInput = ""; 
     } 

     // Solve button 
     if (Gdx.input.getX() > 676 && Gdx.input.getX() < 976 && Gdx.input.getY() > 40 && Gdx.input.getY() < 116) { 
      System.out.println("SOLVE"); 
      solve(); 
     } 

    } 

    // Android keyboard 
    Gdx.input.setOnscreenKeyboardVisible(isAndroidKeyboardShowing); 
} 

// The solve algorithm 
private void solve() { 

    if (userInput.equalsIgnoreCase(answer)) { 
     //level++; 
     prefs.increaseLevel(); 
     userInput = ""; 
    } 

    userInput = ""; 
} 

@Override 
public boolean keyDown(int keycode) { 

    switch (keycode) { 
     // Numbers 
     case Input.Keys.NUM_0: userInput += '0'; break; 
     case Input.Keys.NUM_1: userInput += '1'; break; 
     case Input.Keys.NUM_2: userInput += '2'; break; 
     case Input.Keys.NUM_3: userInput += '3'; break; 
     case Input.Keys.NUM_4: userInput += '4'; break; 
     case Input.Keys.NUM_5: userInput += '5'; break; 
     case Input.Keys.NUM_6: userInput += '6'; break; 
     case Input.Keys.NUM_7: userInput += '7'; break; 
     case Input.Keys.NUM_8: userInput += '8'; break; 
     case Input.Keys.NUM_9: userInput += '9'; break; 

     // All english letters 
     case Input.Keys.A: userInput += 'A'; break; 
     case Input.Keys.B: userInput += 'B'; break; 
     case Input.Keys.C: userInput += 'C'; break; 
     case Input.Keys.D: userInput += 'D'; break; 
     case Input.Keys.E: userInput += 'E'; break; 
     case Input.Keys.F: userInput += 'F'; break; 
     case Input.Keys.G: userInput += 'G'; break; 
     case Input.Keys.H: userInput += 'H'; break; 
     case Input.Keys.I: userInput += 'I'; break; 
     case Input.Keys.J: userInput += 'J'; break; 
     case Input.Keys.K: userInput += 'K'; break; 
     case Input.Keys.L: userInput += 'L'; break; 
     case Input.Keys.M: userInput += 'M'; break; 
     case Input.Keys.N: userInput += 'N'; break; 
     case Input.Keys.O: userInput += 'O'; break; 
     case Input.Keys.P: userInput += 'P'; break; 
     case Input.Keys.Q: userInput += 'Q'; break; 
     case Input.Keys.R: userInput += 'R'; break; 
     case Input.Keys.S: userInput += 'S'; break; 
     case Input.Keys.T: userInput += 'T'; break; 
     case Input.Keys.U: userInput += 'U'; break; 
     case Input.Keys.V: userInput += 'V'; break; 
     case Input.Keys.W: userInput += 'W'; break; 
     case Input.Keys.X: userInput += 'X'; break; 
     case Input.Keys.Y: userInput += 'Y'; break; 
     case Input.Keys.Z: userInput += 'Z'; break; 

     // Special keys 
     case Input.Keys.ENTER: solve(); break; 

     case Input.Keys.BACKSPACE: 
      if (userInput.length() > 0) 
       userInput = userInput.substring(0, userInput.length()-1); 
      break; 
    } 

    return true; 
} 

private void gameComplete() { 
    font.setColor(Color.BLACK); 
    layout.setText(font, "Play again? Reset?"); 
    font.draw(batch, "Play again? Reset?", Gdx.graphics.getWidth()/2 - layout.width/2, Gdx.graphics.getHeight() - 400); 

    batch.draw(btnMenu, Gdx.graphics.getWidth()/2 - btnMenu.getWidth()/2, 600); 
    batch.draw(btnReset, Gdx.graphics.getWidth()/2 - btnReset.getWidth()/2, 400); 
    batch.draw(btnQuit, Gdx.graphics.getWidth()/2 - btnQuit.getWidth()/2, 200); 

    // Menu button 
    if (Gdx.input.justTouched() && 
      Gdx.input.getX() >= Gdx.graphics.getWidth()/2 - btnMenu.getWidth()/2 && 
      Gdx.input.getX() <= (Gdx.graphics.getWidth()/2 - btnMenu.getWidth()/2) + btnMenu.getWidth() && 
      Gdx.input.getY() >= Gdx.graphics.getHeight() - 600 - btnMenu.getHeight() && 
      Gdx.input.getY() <= Gdx.graphics.getHeight() - 600) { 
     STATE = GAME.MENU; 
     System.out.println("Game Over Menu: Menu"); 
    } 

    // Reset button 
    if (Gdx.input.justTouched() && 
      Gdx.input.getX() >= Gdx.graphics.getWidth()/2 - btnReset.getWidth()/2 && 
      Gdx.input.getX() <= (Gdx.graphics.getWidth()/2 - btnReset.getWidth()/2) + btnReset.getWidth() && 
      Gdx.input.getY() >= Gdx.graphics.getHeight() - 400 - btnReset.getHeight() && 
      Gdx.input.getY() <= Gdx.graphics.getHeight() - 400) { 
     level = 1; 
     System.out.println("Game Over Menu: Reset"); 
    } 

    // Quit button 
    if (Gdx.input.justTouched() && 
      Gdx.input.getX() >= Gdx.graphics.getWidth()/2 - btnQuit.getWidth()/2 && 
      Gdx.input.getX() <= (Gdx.graphics.getWidth()/2 - btnQuit.getWidth()/2) + btnQuit.getWidth() && 
      Gdx.input.getY() >= Gdx.graphics.getHeight() - 200 - btnQuit.getHeight() && 
      Gdx.input.getY() <= Gdx.graphics.getHeight() - 200) { 
     Gdx.app.exit(); 
     System.out.println("Game Over Menu: Quit"); 
    } 
} 

// Usual input 
@Override 
public boolean keyUp(int keycode) { 
    return false; 
} 

@Override 
public boolean keyTyped(char character) { 
    return false; 
} 

@Override 
public boolean touchDown(int screenX, int screenY, int pointer, int button) { 
    return false; 
} 

@Override 
public boolean touchUp(int screenX, int screenY, int pointer, int button) { 
    return false; 
} 

@Override 
public boolean touchDragged(int screenX, int screenY, int pointer) { 
    return false; 
} 

@Override 
public boolean mouseMoved(int screenX, int screenY) { 
    return false; 
} 

@Override 
public boolean scrolled(int amount) { 
    return false; 
} 

}

編輯 對不起的人,我有試圖實現你給我的代碼,但仍然做錯了什麼。我的所有方法game(),menu(),gameComplete()都在batch.begin()和batch.end()之間的render()方法中。 我需要在關閉應用程序時保存關卡。

但是我如何檢查確實發生了一些事情,以便知道我的首選項已創建?此外,如果不建議在render()方法中調用偏好,我應該在哪裏調用它們? create()方法只調用一次偏好,因此不會保存關卡。

回答

0

無需創建My Preferences,它創建它自己。偏好相關的工作不應該在render方法中完成。

在Android上,使用了系統的[SharedPreferences] [1]類。這意味着首選項可以在應用程序更新後保留,但在卸載應用程序時會被刪除。 SharedPreferences將私有原始數據存儲在鍵值對中。

public class TestGame2 extends Game { 

    public Prefs prefs; 

    @Override 
    public void create() { 

     prefs=new Prefs(); 

     System.out.printf("Current Sound Status"+prefs.hasSound()); 

     // I need to to change sound Status 
     prefs.setSound(false); 

     //Now sound is off 

    } 

    public void playSound(){ 

     if(prefs.hasSound()) { 
      Sound sound=Gdx.audio.newSound("...."); 
      sound.play(); 
     } 
    } 

    public void startGame(){ 

     //what is my previous highest saved game level, last time 

     int level=prefs.getLevel(); 
    } 

    public void levelCompleted(){ 

     // wow last Level completed so now i need to increase level 
     prefs.increaseLevel(); 
    } 
} 

而且偏好設置是:

public class Prefs { 

    private Preferences pref ; 
    private boolean hasSound; 
    private int completedLevel; 

    public Prefs(){ 
     pref = Gdx.app.getPreferences("My Preferences"); 
     hasSound = pref.getBoolean("hasSound",true); 
     completedLevel=pref.getInteger("level",0); 

    } 

    public void setSound(boolean hasSound){ 
     this.hasSound=hasSound; 
     pref.putBoolean("hasSound",hasSound); 
     pref.flush(); 
    } 

    public boolean hasSound(){ 
     return hasSound; 
    } 

    //should be called once when we need to increase my level 
    public void increaseLevel(){ 
     completedLevel++; 
     pref.putInteger("level",completedLevel); 
     pref.flush(); 
    } 

    public int getLevel(){ 
     return completedLevel; 
    } 
} 

編輯

使用計數器一樣。

boolean isDataSaved; 

private void gameComplete() { // your method 

    if(!isDataSaved){ 
     levelCompleted(); 
     isDataSaved=true; 
    } 

    font.setColor(Color.BLACK); 
    layout.setText(font, "Play again? Reset?"); 
} 

private void menu() { 
    isDataSaved=false; 
} 

而你已經在你的game方法使用的startGame()代碼。

+0

我瞭解首選項如何工作的基礎知識,但如果不能在render()方法中使用,我應該在哪裏調用startGame(),levelCompleted()方法?這些方法不是自動調用的嗎? 我將我的應用程序的代碼添加到StackOverflow,以便我的錯誤可以顯示出來。那麼每個人都可能更容易發現錯誤。 – kevvex

+0

請檢查更新的答案:) – Aryan

+0

是levelCompleted()prefs.increaseLevel()的方法,還是您稍後定義的方法? 順便說一下,當用戶回答所有問題時,纔會調用gameComplete()方法。在完成關卡後不會調用它。 這是solve()方法,它增加了level變量。 – kevvex