手游《奔跑吧?骚年!》技术分享(三):文件处理
由于这个游戏是单机游戏所以用户的数据被保存在本地磁盘里。采用的是很方便的对象序列化技术所以不需要解析数据库,或者XML的步骤。但是对象序列化技术很容易就被人破解,但是。。。忽略不计
另一个问题是图片获取,Android对图片的大小有限制,所以不能一次载入过多图片。所以关键就是用Bitmap.Config.RGB_565格式来将图片载入内存。
还有一个游戏地图数据的获取就是很简单的读取文本,在我之前的博客也讨论过。
package com.baohanbin.run_boy_run.game_util;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.baohanbin.run_boy_run.game_data.GameUserData;
import com.baohanbin.run_boy_run.game_run.MainActivity;
import android.app.Activity;
import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
/**
* 资源文件处理
*
* @author 包汉彬同学
*
*/
public class FileDispose {
/**
* 从资源路径里获取图片的位图
*
* @param activity
* 活动
* @param fileName
* 图片路径
* @return 位图
*/
public static Bitmap getImageFromAssetsFile(Activity activity,
String fileName) {
Bitmap image = null;
AssetManager am = activity.getResources().getAssets();
image = getImageFromAssetsFile(activity, am, fileName);
return image;
}
/**
* 根据路径获取图片
*
* @param activity
* 活动
* @param am
* 资源管理
* @param fileName
* 文件名
* @return 图片文件
*/
public static Bitmap getImageFromAssetsFile(Activity activity,
AssetManager am, String fileName) {
Bitmap image = null;
try {
InputStream is = am.open(fileName);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inPurgeable = true;
options.inInputShareable = true;
image = BitmapFactory.decodeStream(is, null, options);
is.close();
} catch (IOException e) {
e.printStackTrace();
}
return image;
}
public static Bitmap[] getImageArrayAssetsFolder(Activity activity,
String folderName) {
return getImageArrayAssetsFolder(activity, folderName, "png");
}
/**
* 获取文件夹里的所有图片的位图并按数字排序
*
* @param activity
* 活动
* @param folderName
* 文件夹路径
* @return 位图数组
*/
public static Bitmap[] getImageArrayAssetsFolder(Activity activity,
String folderName, String type) {
Bitmap[] bitmaps = null;
AssetManager am = activity.getResources().getAssets();
Pattern pattern = Pattern.compile(".+\\." + type);
List<String> names = new ArrayList<String>();
try {
for (String str : am.list(folderName)) {
if (pattern.matcher(str).matches()) {
names.add(str);
}
}
Collections.sort(names, new Comparator<String>() {
private Pattern pattern = Pattern.compile("\\d+");
@Override
public int compare(String lhs, String rhs) {
// TODO Auto-generated method stub
Matcher m_l = pattern.matcher(lhs);
Matcher m_r = pattern.matcher(rhs);
int l = 0;
while (m_l.find()) {
l = Integer.valueOf(m_l.group());
}
int r = 0;
while (m_r.find()) {
r = Integer.valueOf(m_r.group());
}
if (l > r) {
return 1;
} else if (l == r) {
return 0;
} else if (l < r) {
return -1;
}
return 0;
}
});
bitmaps = new Bitmap[names.size()];
int i = 0;
for (String str : names) {
bitmaps[i++] = getImageFromAssetsFile(activity, am, folderName
+ "/" + str);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return bitmaps;
}
/**
* 获取序列化的用户数据<br>
* 失败或者没有用户数据返回null
*
* @param main
* @param userData
*/
public static void saveUserData(MainActivity main, GameUserData userData) {
try {
FileOutputStream output = main.openFileOutput(
MainActivity.userDataString, Context.MODE_PRIVATE);
ObjectOutputStream objOutput = new ObjectOutputStream(output);
objOutput.writeObject(userData);
objOutput.close();
output.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 获取序列化的用户数据<br>
* 获取失败时返回null
*
* @param main
* @return 返回用户数据
* @throws IOException
* @throws ClassNotFoundException
*/
public static GameUserData readUserData(MainActivity main)
throws IOException, ClassNotFoundException {
GameUserData userData = null;
FileInputStream input = main.openFileInput(MainActivity.userDataString);
ObjectInputStream objInput = new ObjectInputStream(input);
userData = (GameUserData) objInput.readObject();
objInput.close();
input.close();
return userData;
}
/**
* 从data文件获取包含地图数据的字符串
*
* @param main
* @param level
* 关卡
* @return
* @throws IOException
*/
public static String readerMap(MainActivity main, int level)
throws IOException {
AssetManager aManager = main.getResources().getAssets();
InputStream iStream = aManager.open("map/map" + level + ".data");
InputStreamReader iSReader = new InputStreamReader(iStream);
BufferedReader reader = new BufferedReader(iSReader);
StringBuilder sBuider = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sBuider.append(line);
// 在reader读取一行时会自动去掉换行符,所以在这里加上
sBuider.append("\r\n");
}
reader.close();
return sBuider.toString();
}
}
在这个游戏中图片是一张一张储存的,不过通常会将某些图片组合成一张大图来载入,然后剪裁该图片。至于为什么没有用呐,,其实是因为游戏的素材在开发游戏过程中经常变化,这导致剪裁的算法改来改去。。索性直接就不剪裁了。。。