博客已迁移:更多精彩内容尽在AyoCrazy.com
在Libgdx开发过程中,对资源的引用是直接通过一个资源路径的字符串来获取的,这给我们开发过程中造成了很大的不便。例如我们修改了某个资源文件的路径后,编译器并不会报错,但是运行的时候却提示找不到这个文件,因为编译器无法判断这个资源路径是否为有效路径,这个时候我们需要手动去修改这个路径字符串,如果是一个两个倒还好,但如果是批量修改呢,又怎么保证路径不会输错。要解决这个问题,我们可以通过将资源路径与变量对应起来,因为编译器可以判断一个变量是否存在。于是,我们很容易想到Android中的R文件,每个资源对应一个整型id,通过id去访问资源。那么在Libgdx中我们同样可以采取类似的方式,手动生成一个R文件,通过访问R文件中的变量去访问资源。这也是很多libgdx开发者通用的做法。
原理
通过遍历资源目录(android工程下的assets文件夹),获取每个资源的路径,然后将这些资源路径储存为Java的一个String类型常量,那么用的时候就可以直接使用R文件中的这个常量就行了,如果资源发生变动,只需要重新生成一下R文件就行了,十分方便。
好处
有效防止路径拼写错误资源变动后,编译器会给予错误提示遍历文件夹为耗时操作,若遍历R文件则方便快速得多
步骤
1.在core工程下创建一个R文件的包和一个生成R文件的类
如下图的包和AutoR类
2.在AutoR类中写入生成R文件的代码
package com.mytian.mypet.R;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Locale;
import com.badlogic.gdx.utils.Array;
/**
* 自动生成R文件,在电脑上运行本程序,将会对assetPath路径下的所有文件进行遍历,生成R文件
*
* @author AyoCrazy
*
*/
public class AutoR {
private String assetPath =
"E:\\workspace\\MyPet\\mypet\\android\\assets";
public static void main(String[] args) {
new AutoR().start();
}
public void start() {
Group root =
new Group(
"R");
getFiles(root,
new File(assetPath));
writeFiles(root);
}
private void writeFiles(Group group) {
String packName = getClass().getPackage().getName();
String RFilePath = assetPath.replace(
"\\android\\assets",
"\\core\\src\\" + packName.replace(
".",
"\\") +
"\\R.java");
String head =
"package " + packName +
";\n";
String info =
"\n/** 此文件为自动生成,请勿随意手动修改 */";
String body = head + info + group.toString();
try {
FileOutputStream os =
new FileOutputStream(
new File(RFilePath));
os.write(body.getBytes(),
0, body.getBytes().length);
os.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
private void getFiles(Group group, File parent) {
File[] fs = parent.listFiles();
for (File f : fs) {
String fileName = f.getName();
if (f.isDirectory()) {
Group g =
new Group(fileName);
group.addGroup(g);
getFiles(g, f);
}
else {
group.addFile(fileName);
}
}
}
private int index;
/** 一个Group对应一个文件目录*/
private class Group {
private String name;
private Array<Group> groups =
new Array<AutoR.Group>();
private Array<String> fileNames =
new Array<String>();
private Group parent;
private String space =
"";
public Group(String dirName) {
name = dirName;
}
@Override
public String
toString() {
String fileString =
"";
for (String fileName : fileNames) {
String outPath = (outPath() +
"/" + fileName).substring(
1);
fileString += space +
" public static final String "
+ fileName.toUpperCase(Locale.ENGLISH).replace(
".",
"_").replace(
"-",
"_") +
" = \"" + outPath
+
"\";\n";
System.out.println(
">> " + (++index) +
" <<------- " + outPath);
}
String groupString =
"";
for (Group g : groups) {
groupString += g.toString();
}
return "\n" + space +
"public class " + name +
" {\n" + fileString + groupString + space +
"}\n";
}
private void addGroup(Group g) {
groups.add(g);
g.parent =
this;
g.space = space +
" ";
}
private void addFile(String fileName) {
fileNames.add(fileName);
}
private String
outPath() {
if (parent ==
null) {
return "";
}
else {
return parent.outPath() +
"/" + name;
}
}
}
}
记得将变量assetPath的值该为你的android工程下的assets文件夹路径(绝对路径)。
3.运行AutoR文件,并刷新第一步中创建的包
点右键运行AutoR文件并刷新后,将会看到包下多了一个R文件。这个文件中就是自动生成的资源ID文件。 生成的文件如下格式:
package com.mytian.mypet.R;
/** 此文件为自动生成,请勿随意手动修改 */
public class R {
public static final String BG_PNG =
"bg.png";
public static final String GOBLINS_ATLAS =
"goblins.atlas";
public static final String GOBLINS_JSON =
"goblins.json";
public static final String GOBLINS_PNG =
"goblins.png";
public static final String SKIN1_SKIN =
"skin1.skin";
public static final String SKIN2_SKIN =
"skin2.skin";
public class fonts {
public static final String MINI_TTF =
"fonts/mini.ttf";
}
}
R文件会自动为每个目录创建一个内部类,保持层级关系同资源目录中的一致。
4.引用R文件中的资源ID来访问资源
例如:
FileHandle fh1 = Gdx.files.internal(R.fonts.MINI_TTF);
FileHandle fh2 = Gdx.files.internal(
"fonts/mini.ttf");
5.最后记得每次改动资源之后,都要重新运行运行AutoR文件,并刷新R文件
结语
相关资源:python入门教程(PDF版)