Auto Save and Auto Load Game Concept on Android Games and Saving on the Internal Vs. External (A.K.A. SD Card)

StackOverflow https://stackoverflow.com/questions/13446699

Frage

I have a question regarding on how to save and load game automatically. In this example, like Temple Run, it automatically saved the game on everything (records, money gained, and unlocked goodies) as straightforward as it seems. Comparing to the PlayStation 1 game, let's say Abe's Exodus for example, it doesn't have an auto save/load feature but it can save the game on the exact location of the area within the level of the game where Abe left and when you load the game, it automatically starts the game on the last location left within this level.

Now, I'm trying to test this feature of the auto load and save game by this simple app I've made, here are the sequence that I've expecting to succeed the following:

  1. Open the app for the first time and if this app is new, the movable sprite will start at the center by default.
  2. Next, I tried to move the sprite by tilting the device and placed it no top.
  3. Then, when I close the app by using the BACK key and not the HOME key to close the app by disposal.
  4. Finally, when I re-open the app, whenever that coordinate I placed it on the sprite will be the new starting point.

My program has some bugs on it. Instead of the sprite on top and this location will supposed to save this coordinate, the sprite goes back to the center once I re-opened! I tried the keyword Preferences in the render() method onto the code workspace straightforwardly to test the save game capability but confusing as it seems it only reads the value.

Here's my few questions regarding this above topic:

  1. Is it a good idea to use the SQL Lite for Java in LibGDX to save the game?
  2. Android smartphones like the the Samsung Galaxy SIII has the SD card slot but not in the Google Nexus Tablet and the main issue is: is there really an external drive in the Android tablets? Can I saved the game on internal instead by coding it?
  3. Is using the preferences the only one way to automatically save everything (i.e. characters, records, items, settings, levels, etc.) and automatically load everything only if after closing the app and re-open it?

Hope you can help me.

Here's my code:

Save_Load_Test.java

package com.test.save_and_load_test;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.utils.GdxRuntimeException;

public class Save_and_Load_Test implements Screen 
{

private OrthographicCamera camera;
private Texture texture;
private Texture background;
private SpriteBatch batch;
private Rectangle pos;
private Rectangle BG_pos;
private float w = 720;
private float h = 1280;

Start game;

public Save_and_Load_Test(Start game)
{
    this.game = game;
}

@Override
public void render(float delta) 
{
    // TODO render()
    Gdx.gl.glClearColor(0, 0, 0, 1);
    Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

    batch.setProjectionMatrix(camera.combined);
    batch.begin();

        batch.draw(background, BG_pos.x, BG_pos.y);
        batch.draw(texture, pos.x, pos.y);

    batch.end();

    if(Gdx.input.getAccelerometerX() >= 1 && pos.x >= 0)
    {
        pos.x -= 20;
    }

    if(Gdx.input.getAccelerometerX() <= -1 && pos.x <= (720 - pos.width))
    {
        pos.x += 20;
    }

    if(Gdx.input.getAccelerometerY() >= 1 && pos.y >=0)
    {
        pos.y -= 20;
    }

    if(Gdx.input.getAccelerometerY() <= -1 && pos.y <= (1280 - pos.height))
    {
        pos.y += 20;
    }

    if(Gdx.input.isKeyPressed(Keys.RIGHT) && pos.x <= (720 - pos.width - 35))
    {
        pos.x += 20;
    }

    if(Gdx.input.isKeyPressed(Keys.LEFT) && pos.x >=0)
    {
        pos.x -= 20;
    }

    if(Gdx.input.isKeyPressed(Keys.UP) && pos.y <= (1280 - pos.height - 35))
    {
        pos.y += 20;
    }

    if(Gdx.input.isKeyPressed(Keys.DOWN) && pos.y >= 0)
    {
        pos.y -= 20;
    }

    Preferences prefs = Gdx.app.getPreferences("my-preferences");

    prefs.putFloat("X", pos.x);
    prefs.putFloat("Y", pos.y);
    prefs.flush();
}

@Override
public void resize(int width, int height) {
    // TODO Auto-generated method stub

}

@Override
public void show() 
{
    // TODO show()
    camera = new OrthographicCamera();
    camera.setToOrtho(false, w, h);

    texture = new Texture(Gdx.files.internal("Jeff_the_Happy_Clown.png"));
    background = new Texture(Gdx.files.internal("babe_BG.png"));

    texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
    background.setFilter(TextureFilter.Linear, TextureFilter.Linear);

    batch = new SpriteBatch();

    pos = new Rectangle();
    pos.width = 100;
    pos.height = 100;
    pos.x = (w/2) - (pos.width/2);
    pos.y = (h/2) - (pos.height/2);

    BG_pos = new Rectangle();
    BG_pos.width = background.getWidth();
    BG_pos.height = background.getHeight();
    BG_pos.x = (w/2) - (BG_pos.width/2);
    BG_pos.y = (h/2) - (BG_pos.height/2);
}

@Override
public void hide() {
    // TODO Auto-generated method stub

}

@Override
public void pause() {
    // TODO Auto-generated method stub

}

@Override
public void resume() {
    // TODO Auto-generated method stub

}

@Override
public void dispose() 
{
    // TODO dispose
    batch.dispose();
    texture.dispose();
}

}

Start.java

package com.test.save_and_load_test;

import com.badlogic.gdx.Game;

public class Start extends Game
{

@Override
public void create() 
{
    setScreen(new Save_and_Load_Test(this));
}

@Override
public void resume()
{
    // Is this method involved for loading the last file game saved?
}

}
War es hilfreich?

Lösung

You should initialize pos in the resume and show methods from the saved preferences file. Something like:

Preferences prefs = Gdx.app.getPreferences("my-preferences");
pos.x = prefs.getFloat("X", 99.0f); // XXX use a better default
pos.y = prefs.getFloat("Y", 99.0f); // XXX use a better default

If you compute reasonable default values, you won't have to worry about the initial case.

Technically, you could just do this at the top of render (in the usual case you'll just re-read the values you just saved on the previous render, but in the case where this is the first render call it should help). But that seems a bit wasteful (and doing unnecessary stuff on the render thread, especially IO, is a bad idea).

It is a little excessive to flush on every render, and will lead to the occasional hiccup when the IO stalls your render thread. You should be able to just flush the preferences object in pause, as your app is on its way out. (You'll have to keep a reference to the Preferences object on your instance of course.)

Your other questions at the end of this question should be posted as a separate question. Before you do that, please be sure to read http://developer.android.com/guide/topics/data/data-storage.html

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top