`
mmdev
  • 浏览: 12892161 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

Android游戏开发基础part9--游戏数据存储

 
阅读更多

Android游戏开发基础part9--游戏数据存储

在Android中,对于数据的存储,提供了4种保存方式:

1.SharedPreference

此方式适用于简单的数据的保存,文如其名,属于配置性质的保存,不适合数据比较大的情况,默认存放在手机内存里。

2.FileInputStream/FileOutputStream

此方式比较适合游戏的保存和使用,流文件存储可以保存较大的数据,而且通过此方式不仅能把数据存储在手机内存中,也能将数据保存到手机的SDcard

3.SQLite

此方式也适合游戏的保存和使用,不仅可以保存较大的数据,而且可以将自己的数据存放在文件系统或者数据库当中,如SQLite数据库,也能将数据保存到SDcard中。

4.ContentProvider

此方式不推荐用于游戏保存,虽然次方式能存储较大的数据,还支持多个程序之间的数据进行交换,但由于游戏中基本就不可能访问外部应用的数据。

1.SharedPreference

SharedPreference实例是通过Context对象得到的:

Context.getSharedPreference(String name, int mode)

作用:利用Context对象获取一个SharedPreference实例

第一个参数:生成保存记录的文件名

第二个参数:操作模式

操作模式:

·Context.MODE_PRIVATE:新内容覆盖原内容。

·Context.MODE_APPEND:新内容追加到原内容后。

·Context.MODE_WORLD_READABLE:允许其他应用程序读取。

·Context.MODE_WORLD_WRITEABLE:允许其他应用程序写入,会覆盖原数据。

常用函数:

·getFloat(String key, float defValue)

·getInt(String key, int defValue)

·getLong(String key, long defValue)

·getString(String key, String defValue)

·getBoolean(String key, Boolean defValue)

对存储文件的数据进行存入操作时,首先需要利用SharedPreference实例得到一个编辑对象:SharedPreferences.Editor edit();

得到一个编辑对象后就可以对SharedPreference中的数据进行操作。

·SharedPreferences.Editor.putFloat(arg0, arg1)

·SharedPreferences.Editor.putFInt(arg0, arg1)

·SharedPreferences.Editor.putLong(arg0, arg1)

·SharedPreferences.Editor.putString(arg0, arg1)

·SharedPreferences.Editor.putBoolean(arg0, arg1)

以上方法的作用是对存储的数据进行操作(写入、保存),其中的第一个参数是需要保存数据的Key值索引,第二个参数是需要保存的数据。

数据要真正写入到SharedPreferences生成的存储文件中,还需要提交:

SharedPreference.Editor.commit();

创建实例:SharedPreferenceProject

==>MySurfaceView.java

package com.spfp;

import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.SurfaceHolder.Callback;

/**
 * 
 * @author Himi
 *
 */
public class MySurfaceView extends SurfaceView implements Callback, Runnable {
	private SurfaceHolder sfh;
	private Paint paint;
	private Thread th;
	private boolean flag;
	private Canvas canvas;
	private int screenW, screenH;
	//记录当前圆形所在九宫格的位置下标
	private int creentTileIndex;
	//声明一个SharedPreferences对象
	private SharedPreferences sp;

	/**
	 * SurfaceView初始化函数
	 */
	public MySurfaceView(Context context) {
		super(context);
		sfh = this.getHolder();
		sfh.addCallback(this);
		paint = new Paint();
		paint.setColor(Color.BLACK);
		paint.setAntiAlias(true);
		setFocusable(true);
		//通过Context获取SharedPreference实例
		sp = context.getSharedPreferences("SaveName", Context.MODE_PRIVATE);
		//每次程序运行时获取圆形的下标
		int tempIndex = sp.getInt("CirCleIndex", -1);
		//判定如果返回-1 说明没有找到,就不对当前记录圆形的变量进行赋值
		if (tempIndex != -1) {
			creentTileIndex = tempIndex;
		}
	}

	/**
	 * SurfaceView视图创建,响应此函数
	 */
	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		screenW = this.getWidth();
		screenH = this.getHeight();
		flag = true;
		//实例线程
		th = new Thread(this);
		//启动线程
		th.start();
	}

	/**
	 * 游戏绘图
	 */
	public void myDraw() {
		try {
			canvas = sfh.lockCanvas();
			if (canvas != null) {
				canvas.drawColor(Color.WHITE);
				paint.setColor(Color.BLACK);
				paint.setStyle(Style.STROKE);
				//绘制九宫格(将屏幕九等份)
				//得到每个方格的宽高
				int tileW = screenW / 3;
				int tileH = screenH / 3;
				for (int i = 0; i < 3; i++) {
					for (int j = 0; j < 3; j++) {
						canvas.drawRect(i * tileW, j * tileH, (i + 1) * tileW, (j + 1) * tileH, paint);
					}
				}
				//根据得到的圆形下标位置进行绘制相应的方格中
				paint.setStyle(Style.FILL);
				canvas.drawCircle(creentTileIndex % 3 * tileW + tileW / 2, creentTileIndex / 3 * tileH + tileH / 2, 30, paint);
				//操作说明
				canvas.drawText("上键:保存游戏", 0, 20, paint);
				canvas.drawText("下键:读取游戏", 110, 20, paint);
				canvas.drawText("左右键:移动圆形", 215, 20, paint);
			}
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			if (canvas != null)
				sfh.unlockCanvasAndPost(canvas);
		}
	}

	/**
	 * 触屏事件监听
	 */
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		return true;
	}

	/**
	 * 按键事件监听
	 */
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		//上键保存游戏状态
		if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
			sp.edit().putInt("CirCleIndex", creentTileIndex).commit();
			//下键读取游戏状态
		} else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
			int tempIndex = sp.getInt("CirCleIndex", -1);
			if (tempIndex != -1) {
				creentTileIndex = tempIndex;
			}
			//圆形的移动
		} else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
			if (creentTileIndex > 0) {
				creentTileIndex -= 1;
			}
		} else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
			if (creentTileIndex < 8) {
				creentTileIndex += 1;
			}
		}
		return super.onKeyDown(keyCode, event);
	}

	/**
	 * 游戏逻辑
	 */
	private void logic() {
	}

	@Override
	public void run() {
		while (flag) {
			long start = System.currentTimeMillis();
			myDraw();
			logic();
			long end = System.currentTimeMillis();
			try {
				if (end - start < 50) {
					Thread.sleep(50 - (end - start));
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * SurfaceView视图状态发生改变,响应此函数
	 */
	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
	}

	/**
	 * SurfaceView视图消亡时,响应此函数
	 */
	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		flag = false;
	}
}


2.流文件存储 FileInputStream/FileOutputStream

创建实例:修改SharedPreference项目中“读取”与“保存的操作” StreamProject

代码:MySurfaceView.java

package com.stp;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.os.Environment;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.SurfaceHolder.Callback;

/**
 * 
 * @author Himi
 *
 */
public class MySurfaceView extends SurfaceView implements Callback, Runnable {
	private SurfaceHolder sfh;
	private Paint paint;
	private Thread th;
	private boolean flag;
	private Canvas canvas;
	private int screenW, screenH;
	//记录当前圆形所在九宫格的位置下标
	private int creentTileIndex;

	/**
	 * SurfaceView初始化函数
	 */
	public MySurfaceView(Context context) {
		super(context);
		sfh = this.getHolder();
		sfh.addCallback(this);
		paint = new Paint();
		paint.setColor(Color.BLACK);
		paint.setAntiAlias(true);
		setFocusable(true);
	}

	/**
	 * SurfaceView视图创建,响应此函数
	 */
	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		screenW = this.getWidth();
		screenH = this.getHeight();
		flag = true;
		//实例线程
		th = new Thread(this);
		//启动线程
		th.start();
	}

	/**
	 * 游戏绘图
	 */
	public void myDraw() {
		try {
			canvas = sfh.lockCanvas();
			if (canvas != null) {
				canvas.drawColor(Color.WHITE);
				paint.setColor(Color.BLACK);
				paint.setStyle(Style.STROKE);
				//绘制九宫格(将屏幕九等份)
				//得到每个方格的宽高
				int tileW = screenW / 3;
				int tileH = screenH / 3;
				for (int i = 0; i < 3; i++) {
					for (int j = 0; j < 3; j++) {
						canvas.drawRect(i * tileW, j * tileH, (i + 1) * tileW, (j + 1) * tileH, paint);
					}
				}
				//根据得到的圆形下标位置进行绘制相应的方格中
				paint.setStyle(Style.FILL);
				canvas.drawCircle(creentTileIndex % 3 * tileW + tileW / 2, creentTileIndex / 3 * tileH + tileH / 2, 30, paint);
				//操作说明
				canvas.drawText("上键:保存游戏", 0, 20, paint);
				canvas.drawText("下键:读取游戏", 110, 20, paint);
				canvas.drawText("左右键:移动圆形", 215, 20, paint);
			}
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			if (canvas != null)
				sfh.unlockCanvasAndPost(canvas);
		}
	}

	/**
	 * 触屏事件监听
	 */
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		return true;
	}

	/**
	 * 按键事件监听
	 */
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		//用到的读出、写入流
		FileOutputStream fos = null;
		FileInputStream fis = null;
		DataOutputStream dos = null;
		DataInputStream dis = null;
		//上键保存游戏状态
		if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
			try {
				// 从SDcard中写入数据
				// 试探终端是否有sdcard! 并且探测SDCard是否处于被移除的状态
				if (Environment.getExternalStorageState() != null && !Environment.getExternalStorageState().equals("removed")) {
					Log.v("Himi", "写入,有SD卡");
					File path = new File("/sdcard/himi");// 创建目录  
					File f = new File("/sdcard/himi/save.himi");// 创建文件  
					if (!path.exists()) {// 目录存在返回true  
						path.mkdirs();// 创建一个目录  
					}
					if (!f.exists()) {// 文件存在返回true  
						f.createNewFile();// 创建一个文件  
					}
					fos = new FileOutputStream(f);// 将数据存入sd卡中  
				} else {
					//默认系统路径
					//利用Activity实例打开流文件得到一个写入流
					fos = MainActivity.instance.openFileOutput("save.himi", Context.MODE_PRIVATE);
				}
				//将写入流封装在数据写入流中
				dos = new DataOutputStream(fos);
				//写入一个int类型(将圆形所在格子的下标写入流文件中)
				dos.writeInt(creentTileIndex);
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally {
				//即使保存时发生异常,也要关闭流
				try {
					if (fos != null)
						fos.close();
					if (dos != null)
						dos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			//下键读取游戏状态
		} else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
			boolean isHaveSDCard = false;
			// 从SDcard中读取数据
			// 试探终端是否有sdcard! 并且探测SDCard是否处于被移除的状态
			if (Environment.getExternalStorageState() != null && !Environment.getExternalStorageState().equals("removed")) { 
				Log.v("Himi", "读取,有SD卡");
				isHaveSDCard = true;
			}
			try {
				if (isHaveSDCard) {
					File path = new File("/sdcard/himi");// 创建目录  
					File f = new File("/sdcard/himi/save.himi");// 创建文件  
					if (!path.exists()) {// 目录存在返回true
						return false;
					} else {
						if (!f.exists()) {// 文件存在返回true  
							return false;
						}
					}
					fis = new FileInputStream(f);// 将数据存入sd卡中  
				} else {
					if (MainActivity.instance.openFileInput("save.himi") != null) {
						//利用Activity实例打开流文件得到一个读入流
						fis = MainActivity.instance.openFileInput("save.himi");
					}
				}
				//将读入流封装在数据读入流中
				dis = new DataInputStream(fis);
				//读出一个Int类型赋值与圆形所在格子的下标
				creentTileIndex = dis.readInt();
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally {
				//即使读取时发生异常,也要关闭流
				try {
					if (fis != null)
						fis.close();
					if (dis != null)
						dis.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		} else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
			if (creentTileIndex > 0) {
				creentTileIndex -= 1;
			}
		} else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
			if (creentTileIndex < 8) {
				creentTileIndex += 1;
			}
		}
		return super.onKeyDown(keyCode, event);
	}

	/**
	 * 游戏逻辑
	 */
	private void logic() {
	}

	@Override
	public void run() {
		while (flag) {
			long start = System.currentTimeMillis();
			myDraw();
			logic();
			long end = System.currentTimeMillis();
			try {
				if (end - start < 50) {
					Thread.sleep(50 - (end - start));
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * SurfaceView视图状态发生改变,响应此函数
	 */
	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
	}

	/**
	 * SurfaceView视图消亡时,响应此函数
	 */
	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		flag = false;
	}
}


将流文件保存在SDcard中的步骤:

(1)声明写入权限:

<uses-permission android:name="android.premission.WRITE_EXTERNAL_STORAGE"/>

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
	package="com.stp" android:versionCode="1" android:versionName="1.0">

	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
	<application android:icon="@drawable/icon" android:label="@string/app_name">
		<activity android:name=".MainActivity" android:label="@string/app_name">
			<intent-filter>
				<action android:name="android.intent.action.MAIN" />
				<category android:name="android.intent.category.LAUNCHER" />
			</intent-filter>
		</activity>

	</application>
</manifest>


(2)创建目录和存储文件

1.首先需要创建路径:/sdcard/wwj

//声明一个路径

File path = new File("/sdcard/wwj");

if(!path.exists()){

path.mkdirs();

}

2.然后创建存储文件:/sdcard/wwj/save.wwj

//声明一个路径

File f = new File("/sdcard/wwj/save.wwj");

if(!f.exist()){//文件存在就返回true

f.createNewFile();//创建一个文件

}

(3)通过加载指定路径的存储文件获取输入输出流

·输入流:FileInputStream fis = new FileInputStream(File file);

·输出流:FileOutputSteam fos = new FileOutputSteam(File file);

分享到:
评论

相关推荐

    Android自学视频教程 part1

    《Android自学视频教程》[1] 分3篇共21章,其中,第1篇为入门篇,主要包括Android入门、搭建Android开发环境、认识Android模拟器、剖析Android程序、Android常用组件的使用、掌握布局管理器、Android程序调试与错误...

    Android应用开发揭秘 源码 part2

    本书内容全面,不仅详细讲解了Android框架、Android组件、用户界面开发、游戏开发、数据存储、多媒体开发和网络开发等基础知识,而且还深入阐述了传感器、语音识别、桌面组件开发、Android游戏引擎设计、Android应用...

    android应用开发揭秘.part3

    本书内容全面,不仅详细讲解了Android框架、Android组件、用户界面开发、游戏开发、数据存储、多媒体开发和网络开发等基础知识,而且还深入阐述了传感器、语音识别、桌面组件开发、Android游戏引擎设计、Android应用...

    android应用开发揭秘.part2

    本书内容全面,不仅详细讲解了Android框架、Android组件、用户界面开发、游戏开发、数据存储、多媒体开发和网络开发等基础知识,而且还深入阐述了传感器、语音识别、桌面组件开发、Android游戏引擎设计、Android应用...

    android应用开发揭秘.part1

    本书内容全面,不仅详细讲解了Android框架、Android组件、用户界面开发、游戏开发、数据存储、多媒体开发和网络开发等基础知识,而且还深入阐述了传感器、语音识别、桌面组件开发、Android游戏引擎设计、Android应用...

    Android应用开发揭秘 源码 part1

    本书内容全面,不仅详细讲解了Android框架、Android组件、用户界面开发、游戏开发、数据存储、多媒体开发和网络开发等基础知识,而且还深入阐述了传感器、语音识别、桌面组件开发、Android游戏引擎设计、Android应用...

    Android自学视频教程 part2

    《Android自学视频教程》[1] 分3篇共21章,其中,第1篇为入门篇,主要包括Android入门、搭建Android开发环境、认识Android模拟器、剖析Android程序、Android常用组件的使用、掌握布局管理器、Android程序调试与错误...

    Android应用开发揭秘高清版(全附带源码).part1

    讲解了Android框架、Android组件、用户界面开发、游戏开发、数据存储、多媒体开发和网络开发等基础知识,而且还深入阐述了传感器、语音识别、桌面组件开发、Android游戏引擎设计、Android应用优化、OpenGL等高级知识...

    Android应用开发揭秘高清版(全附带源码).part4

    讲解了Android框架、Android组件、用户界面开发、游戏开发、数据存储、多媒体开发 和网络开发等基础知识,而且还深入阐述了传感器、语音识别、桌面组件开发、Android游戏引擎设计、Android应用优化、OpenGL 等高级...

    Android应用开发揭秘高清版(全附带源码).part3

    讲解了Android框架、Android组件、用户界面开发、游戏开发、数据存储、多媒体开发 和网络开发等基础知识,而且还深入阐述了传感器、语音识别、桌面组件开发、Android游戏引擎设计、Android应用优化、OpenGL 等高级...

    Android应用开发揭秘高清版(全附带源码).part2

    讲解了Android框架、Android组件、用户界面开发、游戏开发、数据存储、多媒体开发 和网络开发等基础知识,而且还深入阐述了传感器、语音识别、桌面组件开发、Android游戏引擎设计、Android应用优化、OpenGL 等高级...

    Android移动网站开发详解.part2

    其中,第1~3章是基础篇,包括Android技术概述、Android网络开发技术基础、创建移动Web的方法;第4~13章是HTML5篇,讲解了在Android中使用HTML5技术设计移动Web网页的基本知识,包括HTML5架构、基本元素、表单元素...

    Google Android SDK开发范例大全(第3版)part2

     《Google Android SDK开发范例大全(第3版)》在上一版的基础上,以Android手机应用程序开发(采用Android SDK 2.3.3)为主题,超过200多个范例全面且深度地整合了手机、网络及服务等多个开发领域,为读者提高程序...

    Google Android开发入门实战 pdf 和 实例代码.part3

    本章介绍了在Windows、Linux、Mac OS平台上搭建Android开发环境的过程,通过本章学习,可以很顺利的搭建起自己的开发环境,做好开发前的准备。 第3章 清点可用资本—Android SDK介绍。主要介绍了Android SDK中包含的...

    Google Android开发入门实战 pdf 和 实例代码.part2

    本章介绍了在Windows、Linux、Mac OS平台上搭建Android开发环境的过程,通过本章学习,可以很顺利的搭建起自己的开发环境,做好开发前的准备。 第3章 清点可用资本—Android SDK介绍。主要介绍了Android SDK中包含的...

    Google Android开发入门实战 pdf 和 实例代码.part1

    本章介绍了在Windows、Linux、Mac OS平台上搭建Android开发环境的过程,通过本章学习,可以很顺利的搭建起自己的开发环境,做好开发前的准备。 第3章 清点可用资本—Android SDK介绍。主要介绍了Android SDK中包含的...

    疯狂Android讲义.part2

    1.2 搭建Android开发环境 5 1.2.1 下载和安装Android SDK 5 1.2.2 安装Eclipse和ADT插件 7 1.3 Android常用开发工具的用法 10 1.3.1 创建、删除和浏览AVD 10 1.3.2 使用Android模拟器 (Emulator) 14 1.3.3 使用...

    疯狂Android讲义.part1

    1.2 搭建Android开发环境 5 1.2.1 下载和安装Android SDK 5 1.2.2 安装Eclipse和ADT插件 7 1.3 Android常用开发工具的用法 10 1.3.1 创建、删除和浏览AVD 10 1.3.2 使用Android模拟器 (Emulator) 14 1.3.3 使用...

Global site tag (gtag.js) - Google Analytics