在 Android 的游戏循环中,我应该在哪里使用共享首选项保存数据?

Where should I save data using Shared Preferences in the game loop in Android?

尝试在 Android 中编写一个简单的游戏时,我遇到了保存数据的问题。我采用了使用共享首选项使用简单键值对的方法,主要是因为我只保存了 10 - 15 个简单整数。但是我无法将其保存在主 Activity 中。因为我似乎无法在 Surface Created(在游戏面板中)上调用它。我也尝试过在游戏面板中保存数据的功能,但它不能用静态方法创建。游戏面板是哪个。所以好像不知道放哪里了

这是游戏面板代码:

public class GamePanel extends SurfaceView implements SurfaceHolder.Callback {

    private MainThread thread;
    private UserObject player = new UserObject();
    private MainActivity activity = new MainActivity();
    private loadImage background;
    private loadImage house;
    private loadImage constructionWorker;
    private loadImage houseUpgrade;
    private loadImage bob;
    private loadImage workGroup;
    private loadImage bank;
    private loadImage factory;
    private loadImage superTapping;
    private loadImage unlockStore;
    private loadImage store;
    int screenWidth = this.getResources().getDisplayMetrics().widthPixels;
    int screenHeight = this.getResources().getDisplayMetrics().heightPixels;

    Bitmap buttonVars = BitmapFactory.decodeResource(getResources(), R.drawable.house_upgrade);
    int buttonWidth = buttonVars.getWidth();
    int buttonHeight = buttonVars.getHeight();

    Bitmap houseVars = BitmapFactory.decodeResource(getResources(), R.drawable.house_upgrade);
    int houseWidth = houseVars.getWidth();
    int houseHeight = houseVars.getHeight();

    public GamePanel(Context context) {
        super(context);

        //add the callback to the surface holder to intercept events
        getHolder().addCallback(this);

        //make gamePanel focusable so it can handle events
        setFocusable(true);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        activity.saveData();
        boolean retry = true;
        while (retry) {
            try {
                thread.setRunning(false);
                thread.join();
                retry = false;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        //we can safely start the game loop
        activity.getData()
        thread = new MainThread(getHolder(), this);
        thread.setRunning(true);
        thread.start();

        //Create Bitmaps
        background = new loadImage(BitmapFactory.decodeResource(getResources(), R.drawable.blue_background), 0, 0);
        house = new loadImage(BitmapFactory.decodeResource(getResources(), R.drawable.crap_shack), ((screenWidth / 2) - houseWidth), (houseHeight * 2));
        houseUpgrade = new loadImage(BitmapFactory.decodeResource(getResources(), R.drawable.house_upgrade), 0, (screenHeight - buttonHeight));
        constructionWorker = new loadImage(BitmapFactory.decodeResource(getResources(), R.drawable.construction_worker), ((screenWidth / 2) - (buttonWidth / 2)), (screenHeight - buttonHeight));
        bob = new loadImage(BitmapFactory.decodeResource(getResources(), R.drawable.bob), (screenWidth - buttonWidth), (screenHeight - buttonHeight));
        workGroup = new loadImage(BitmapFactory.decodeResource(getResources(), R.drawable.work_group), 0, (screenHeight - (buttonHeight * 3)));
        bank = new loadImage(BitmapFactory.decodeResource(getResources(), R.drawable.bank), ((screenWidth / 2) - (buttonWidth / 2)), (screenHeight - (buttonHeight * 3)));
        factory = new loadImage(BitmapFactory.decodeResource(getResources(), R.drawable.factory), (screenWidth - buttonWidth), (screenHeight - (buttonHeight * 3)));
        superTapping = new loadImage(BitmapFactory.decodeResource(getResources(), R.drawable.super_tapping), 0, (screenHeight - (buttonHeight * 5)));
        unlockStore = new loadImage(BitmapFactory.decodeResource(getResources(), R.drawable.unlock_store), ((screenWidth / 2) - (buttonWidth / 2)), (screenHeight - (buttonHeight * 5)));
        store = new loadImage(BitmapFactory.decodeResource(getResources(), R.drawable.store), (screenWidth - buttonWidth), (screenHeight - (buttonHeight * 5)));

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            //handle house
            house.handleActionDown((int) event.getX(), (int) event.getY());
            if (house.touched) {
                player.money += player.MPC;
                house.setTouched(false);
            }

            //handle houseUpgrade
            houseUpgrade.handleActionDown((int) event.getX(), (int) event.getY());
            if (houseUpgrade.touched && player.money >= player.houseUpgradeCost) {
                player.money -= player.houseUpgradeCost;
                player.MPC += 1;
                player.houseUpgradeCost += 250;
                houseUpgrade.setTouched(false);
            }

            //handle ConstructionWorker
            constructionWorker.handleActionDown((int) event.getX(), (int) event.getY());
            if (constructionWorker.touched && player.money >= player.constructionWorkerCost) {
                player.money -= player.constructionWorkerCost;
                player.MPS += 1;
                player.constructionWorkerCost += 25;
                constructionWorker.setTouched(false);
            }

            //handle bob
            bob.handleActionDown((int) event.getX(), (int) event.getY());
            if (bob.touched && player.money >= player.bobCost) {
                player.money -= player.bobCost;
                player.MPS += 5;
                player.bobCost += 200;
                bob.setTouched(false);
            }

            //handle workGroup
            workGroup.handleActionDown((int) event.getX(), (int) event.getY());
            if (workGroup.touched && player.money >= player.workGroupCost) {
                player.money -= player.workGroupCost;
                player.MPS += 50;
                player.workGroupCost += 1250;
                workGroup.setTouched(false);
            }

            //handle bank
            bank.handleActionDown((int) event.getX(), (int) event.getY());
            if (bank.touched && player.money >= player.bankCost) {
                player.money -= player.bankCost;
                player.MPS += 250;
                player.bankCost += 5000;
                bank.setTouched(false);
            }

            //handle Factory
            factory.handleActionDown((int) event.getX(), (int) event.getY());
            if (factory.touched && player.money >= player.factoryCost) {
                player.money -= player.factoryCost;
                player.MPS += 1000;
                player.factoryCost += 25000;
                factory.setTouched(false);
            }

            //handle superTapping
            superTapping.handleActionDown((int) event.getX(), (int) event.getY());
            if (superTapping.touched && player.money >= player.superTappingCost) {
                player.money -= player.superTappingCost;
                player.MPC += 25;
                player.superTappingCost += 7500;
                superTapping.setTouched(false);
            }

            //handle unlockStore
            unlockStore.handleActionDown((int) event.getX(), (int) event.getY());
            if (unlockStore.touched && player.money >= player.unlockStoreCost && !player.storeUnlocked) {
                player.money -= player.unlockStoreCost;
                player.storeUnlocked = true;
                unlockStore.setTouched(false);
            }

            //handle store
            store.handleActionDown((int) event.getX(), (int) event.getY());
            if (store.touched && player.storeUnlocked) {

            }
        }

        if (event.getAction() == MotionEvent.ACTION_UP) {
            house.setTouched(false);
            houseUpgrade.setTouched(false);
            constructionWorker.setTouched(false);
            bob.setTouched(false);
            workGroup.setTouched(false);
            bank.setTouched(false);
            factory.setTouched(false);
            superTapping.setTouched(false);
            unlockStore.setTouched(false);
        }

        return super.onTouchEvent(event);
    }

    public void draw(Canvas canvas) {

        //Draws to canvas
        background.draw(canvas);
        house.draw(canvas);
        houseUpgrade.draw(canvas);
        constructionWorker.draw(canvas);
        bob.draw(canvas);
        workGroup.draw(canvas);
        bank.draw(canvas);
        factory.draw(canvas);
        superTapping.draw(canvas);
        unlockStore.draw(canvas);
        if (player.storeUnlocked) {
            store.draw(canvas);
        }

        writeText(canvas, "Money: $" + player.money, Paint.Align.CENTER, Color.BLACK, 25, (screenWidth / 2), 50);
        writeText(canvas, "MPS: " + player.MPS, Paint.Align.CENTER, Color.BLACK, 25, (screenWidth / 2), 75);
        writeText(canvas, "MPC: " + player.MPC, Paint.Align.CENTER, Color.BLACK, 25, (screenWidth / 2), 100);
        writeText(canvas, "Cost: $" + player.houseUpgradeCost, null, Color.BLACK, 15, 0, (screenHeight - buttonHeight));
        writeText(canvas, "Cost: $" + player.constructionWorkerCost, Paint.Align.CENTER, Color.BLACK, 15, (screenWidth / 2), (screenHeight - buttonHeight));
        writeText(canvas, "Cost: $" + player.bobCost, Paint.Align.LEFT, Color.BLACK, 15, screenWidth, (screenHeight - buttonHeight));
        writeText(canvas, "Cost: $" + player.workGroupCost, null, Color.BLACK, 15, 0, ((screenHeight - (buttonHeight * 3))));
        writeText(canvas, "Cost: $" + player.bankCost, Paint.Align.CENTER, Color.BLACK, 15, (screenWidth / 2), ((screenHeight - (buttonHeight * 3))));
        writeText(canvas, "Cost: $" + player.factoryCost, Paint.Align.LEFT, Color.BLACK, 15, (screenWidth), ((screenHeight - (buttonHeight * 3))));
        writeText(canvas, "Cost: $" + player.superTappingCost, null, Color.BLACK, 15, 0, ((screenHeight - (buttonHeight * 5))));
        writeText(canvas, "Cost: $" + player.unlockStoreCost, Paint.Align.CENTER, Color.BLACK, 15, (screenWidth / 2), ((screenHeight - (buttonHeight * 5))));
    }

    private void writeText(Canvas canvas, String text, Paint.Align align, int color, int textSize, int x, int y) {

        //Sets default align if null
        if (align == null) {
            align = Paint.Align.RIGHT;
        }

        //Sets paint using values
        Paint paint = new Paint();
        paint.setTextAlign(align);
        paint.setColor(color);
        paint.setTextSize(textSize);

        canvas.drawText(text, x, y, paint);

    }
}

这是我试图保存数据的实际主要 Activity。

public class MainActivity extends Activity {

    private UserObject player = new UserObject();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //Sets window settings FULLSCREEN, NO TITLE, NO ACTION BAR.
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

        setContentView(new GamePanel(this));
    }

    public void saveData() {
        SharedPreferences sharedPreferences = getSharedPreferences("houseTapper_dataSaveFile", MODE_PRIVATE);
        SharedPreferences.Editor sharedPreferencesEditor = sharedPreferences.edit();
        sharedPreferencesEditor.putInt("money", player.money);
        sharedPreferencesEditor.putInt("MPS", player.MPS);
        sharedPreferencesEditor.putInt("MPC", player.MPC);
        sharedPreferencesEditor.putInt("houseUpgradeCost", player.houseUpgradeCost);
        sharedPreferencesEditor.putInt("constructionWorkerCost", player.constructionWorkerCost);
        sharedPreferencesEditor.putInt("bobCost", player.bobCost);
        sharedPreferencesEditor.putInt("workGroupCost", player.workGroupCost);
        sharedPreferencesEditor.putInt("bankCost", player.bankCost);
        sharedPreferencesEditor.putInt("factoryCost", player.factoryCost);
        sharedPreferencesEditor.putInt("superTappingCost", player.superTappingCost);
        sharedPreferencesEditor.putBoolean("storeUnlocked", player.storeUnlocked);
        sharedPreferencesEditor.apply();
    }

    public void getData() {
        SharedPreferences sharedPreferences = getSharedPreferences("houseTapper_dataSaveFile", MODE_PRIVATE);
        player.money = sharedPreferences.getInt("money", 0);
        player.MPS = sharedPreferences.getInt("MPS", 0);
        player.MPC = sharedPreferences.getInt("MPC", 0);
        player.houseUpgradeCost = sharedPreferences.getInt("houseUpgradeCost", 0);
        player.constructionWorkerCost = sharedPreferences.getInt("constructionWorkerCost", 0);
        player.bobCost = sharedPreferences.getInt("bobCost", 0);
        player.workGroupCost = sharedPreferences.getInt("workGroupCost", 0);
        player.bankCost = sharedPreferences.getInt("bankCost", 0);
        player.factoryCost = sharedPreferences.getInt("factoryCost", 0);
        player.superTappingCost = sharedPreferences.getInt("superTappingCost", 0);
        player.storeUnlocked = sharedPreferences.getBoolean("storeUnlocked", false);
    }
}

最后是mainThread

public class MainThread extends Thread {

    private UserObject player = new UserObject();
    private int FPS = 30;
    private SurfaceHolder surfaceHolder;
    private GamePanel gamePanel;
    private boolean running;
    public static Canvas canvas;
    //Game variables

    public MainThread(SurfaceHolder surfaceHolder, GamePanel gamePanel) {
        super();
        this.surfaceHolder = surfaceHolder;
        this.gamePanel = gamePanel;
    }

    @Override
    public void run() {
        long startTime;
        long timeMillis;
        long waitTime;
        long targetTime = 1000/FPS;
        int frames = 0;

        while(running) {
            startTime = System.nanoTime();
            canvas = null;

            if (frames == 30) {
                frames = 0;
                player.money += player.MPS;
            }

            //try locking the canvas for pixel editing
            try {
                canvas = this.surfaceHolder.lockCanvas();
                synchronized (surfaceHolder) {
                    this.gamePanel.draw(canvas);
                }
            } catch (Exception e) {
            }
            finally{
                if(canvas!=null)
                {
                    try {
                        surfaceHolder.unlockCanvasAndPost(canvas);
                    }
                    catch(Exception e){e.printStackTrace();}
                }
            }

            timeMillis = (System.nanoTime() - startTime) / 1000000;
            waitTime = targetTime-timeMillis;
            frames++;

            try {
                this.sleep(waitTime);
            } catch(Exception e) {}
        }
    }
    public void setRunning(boolean b)
    {
        running=b;
    }
}

我遗漏了 LoadImage 和 UserObject 类。因为它们不重要。

使用 getActivity() 而不是 new MainActivity()。

Activity activity = getActivity();

saving/loading 与 activity 有什么关系?没什么,您可能只是在那里开始使用它,但没有理由留在那里。

因此,将 Persistence 分离出来拥有 class,然后您可以在任何有 Context 的地方调用:

public final class Persistence {
    private final SharedPreferences sharedPreferences;

    public Persistence(Context context) {
        sharedPreferences = context.getSharedPreferences("houseTapper_dataSaveFile", MODE_PRIVATE);
    }

    public void saveData(Player player) {
        SharedPreferences.Editor sharedPreferencesEditor = sharedPreferences.edit();
        sharedPreferencesEditor.putInt("money", player.money);
        sharedPreferencesEditor.putInt("MPS", player.MPS);
        sharedPreferencesEditor.putInt("MPC", player.MPC);
        // etc...
        sharedPreferencesEditor.apply();
    }

    public void getData(Player player) {
        player.money = sharedPreferences.getInt("money", 0);
        player.MPS = sharedPreferences.getInt("MPS", 0);
        player.MPC = sharedPreferences.getInt("MPC", 0);
        // etc...
    }    
}

用法:

public class GamePanel extends SurfaceView implements SurfaceHolder.Callback {
     private final Persistence persistence = new Persistence(getContext());

     @Override
     public void surfaceCreated(SurfaceHolder holder) {
        //we can safely start the game loop
        persistence.getData(player);


}