我正在构建游戏,基本上我要做的是将XML文件解析为以下两个目的:
然后,将所选场景的精灵加载到列表中并传递给渲染(在不同的线程中完成)。稍后将添加精灵的行为。
以下是我正在使用的代码:
public class SceneMngr extends Activity implements OnGestureListener{
MediaPlayer mediaplayer;
SoundPool soundpool;
WakeLock wakeLock;
List<Node> nodes = new ArrayList<Node>();
List<Node> sceneItems = new ArrayList<Node>();
int i,j,q;
AssetManager assMan = getAssets();
Map <String, Integer> soundPoolMap = new HashMap<String, Integer>();
Map <String, Bitmap> imageMap = new HashMap<String, Bitmap>();
Loader loader = new Loader();
private GestureDetector gDetector;
ArrayList<Sprite> sprites ;
FastRenderView renderView;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
PowerManager powerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "My Lock");
wakeLock.acquire();
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
mediaplayer = new MediaPlayer();
soundpool = new SoundPool(20, AudioManager.STREAM_MUSIC, 0);
renderView = new FastRenderView(this);
setContentView(renderView);
renderView.resume();
loadAssets();
loadScene("mainMenu");
}
public void loadAssets(){
nodes = loader.readAssets();
if (nodes.get(nodes.size()-1).getAttributes().getNamedItem("type").getNodeValue().equals("image") ){
try{
InputStream is = assMan.open(nodes.get(nodes.size()-1).getAttributes().getNamedItem("src").getNodeValue());
imageMap.put(nodes.get(nodes.size()-1).getAttributes().getNamedItem("name").getNodeValue(), BitmapFactory.decodeStream(is));
is.close();}
catch (Exception e) {
e.printStackTrace();
}
}
if (nodes.get(nodes.size()-1).getAttributes().getNamedItem("type").getNodeValue().equals("sound") ){
try{
AssetFileDescriptor descriptor = assMan.openFd(nodes.get(nodes.size()-1).getAttributes().getNamedItem("src").getNodeValue());
soundPoolMap.put(nodes.get(nodes.size()-1).getAttributes().getNamedItem("name").getNodeValue(), soundpool.load(descriptor, 1));
}
catch (Exception e) {
e.printStackTrace();
}
}
if (nodes.get(nodes.size()-1).getAttributes().getNamedItem("type").getNodeValue().equals("music") ){
try {
AssetFileDescriptor descriptor2 = assMan.openFd(nodes.get(nodes.size()-1).getAttributes().getNamedItem("src").getNodeValue());
mediaplayer.setDataSource(descriptor2.getFileDescriptor(),
descriptor2.getStartOffset(), descriptor2.getLength());
mediaplayer.prepare();
mediaplayer.setLooping(true);
mediaplayer.setVolume(0.1f, 0.1f);
mediaplayer.start();
} catch (IOException e) {
mediaplayer = null;
}
}
}
public void loadScene(String sceneId){
sceneItems=loader.readScene(sceneId);
String[] temp = new String[3];
sprites.clear(); //dispose previous scene: empty sprite list
//create a sprite for each node
for (i=0; i <sceneItems.size(); i++){
for (j=0; j < 2; j++){
temp[j] = sceneItems.get(i).getAttributes().item(j).getNodeValue();
}
sprites.add(new Sprite(temp[0], temp[1], temp[2]));
}
}
class FastRenderView extends SurfaceView implements Runnable{
Thread renderThread = null;
SurfaceHolder holder;
volatile boolean running = false;
@Override
public boolean onTouchEvent(MotionEvent me){
return gDetector.onTouchEvent(me);
}
public FastRenderView(Context context) {
super(context);
holder=getHolder();
}
public void resume() {
running = true;
renderThread = new Thread(this);
renderThread.start();
}
public void pause() {
running = false;
while(true) {
try {
renderThread.join();
break;
} catch (InterruptedException e) {
// retry
}
}
renderThread = null;
}
public void run() {
while(running) {
if(!holder.getSurface().isValid())
continue;
Canvas canvas = holder.lockCanvas();
drawSurfice(canvas);
holder.unlockCanvasAndPost(canvas);
}
}
private void drawSurfice(Canvas canvas){
for (q=0; q < sprites.size(); q++){
if (sprites.get(q).visibilitySwitch.equals("true")){
canvas.drawBitmap(imageMap.get(sprites.get(q).srcImg), sprites.get(q).src, sprites.get(q).dst, null);
}
}
}
}
public class Loader{
int h,k,t;
SoundPool soundpool;
AssetManager assMan = getAssets();
MediaPlayer mediaplayer;
List<Node> assetList = new ArrayList<Node>();
List<Node> spriteList = new ArrayList<Node>();
List<Node> sceneItems = new ArrayList<Node>();
Document doc;
Map <String, Integer> soundPoolMap = new HashMap<String, Integer>();
Map <String, Bitmap> imageMap = new HashMap<String, Bitmap>();
public Loader(){
}
//load items of targeted scene into a list
public List<Node> readScene(String sceneId){
for (h = 0; h < doc.getElementsByTagName("scene").getLength(); h++){
if (doc.getElementsByTagName("scene").item(h).getAttributes().getNamedItem("id").getNodeValue().equals(sceneId)){
for (t=0; t< doc.getElementsByTagName("scene").item(h).getChildNodes().getLength(); t++ )
if (doc.getElementsByTagName("scene").item(h).getChildNodes().item(t).getNodeType() != Node.TEXT_NODE)
sceneItems.add(doc.getElementsByTagName("scene").item(h).getChildNodes().item(t));
}
}
return sceneItems;
}
public List<Node> readAssets(){
//load asset file
try {
InputStream inStream = assMan.open("assetss.xml");
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
doc = builder.parse(inStream);
inStream.close();
}catch (Exception e) {
e.printStackTrace();
}
//create list of asset items
for ( k = 0; k < doc.getElementsByTagName("assets").item(0).getChildNodes().getLength(); k++ ){
if (doc.getElementsByTagName("assets").item(0).getChildNodes().item(k).getNodeType() != Node.TEXT_NODE){
assetList.add(doc.getElementsByTagName("assets").item(0).getChildNodes().item(k));}
}
return assetList;
}
}
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return true;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return true;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
}
public class Sprite {
public Bitmap img;
public String soundfx;
Rect src = new Rect();
Rect dst = new Rect();
String visibilitySwitch, srcImg;
List<Integer> posList = new ArrayList<Integer>();
public Sprite (String image, String position, String visibility){
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher(position);
while (m.find()) {
int n = Integer.parseInt(m.group());
posList.add(n);
}
src.set(posList.get(0), posList.get(1), posList.get(2), posList.get(3));
dst.set(posList.get(4), posList.get(5), posList.get(6), posList.get(7));
visibilitySwitch=visibility;
srcImg= image;
}
}
这是我正在使用的测试XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<xml>
<assets>
<sprite src="menuitems.png" name="menu" type="image"/>
<sprite src="buttons.png" name="buttons" type="image"/>
<sprite src="animals.png" name="animals" type="image"/>
<sprite src="music.mp3" name="music" type="sound"/>
<sprite src="click.ogg" name="clickSound" type="sound"/>
<sprite src="swipe.ogg" name="swipeSound" type="sound"/>
<sprite src="dog.mp3" name="dog" type="sound"/>
<sprite src="cow.mp3" name="cow" type="sound"/>
<sprite src="horse.mp3" name="horse" type="sound"/>
<sprite src="bunny.mp3" name="bunny" type="sound"/>
<sprite src="munubackground.png" name="menubackground" type="image"/>
</assets>
<scene id="mainMenu">
<sprite src="menuitems.png" position="0 0 192 42 100 100 292 142" visibility="true"/>
</scene>
<scene id="game">
<sprite src="background.jpg" position="0 0 0 0 0 0 200 200" visibility="true" name="background" />
<sprite src="menu.jpg" position="0 0 0 0 100 100 200 200" visibility="true" name="playButton" audio="click.ogg" onClick="playSound, nextScene"/>
<sprite src="menu.jpg" position="100 100 100 100 100 100 200 200" visibility="true" name="settingsButton" audio="click.ogg" onclick="playSound, nextScene"/>
<sprite src="menu.jpg" position="100 100 100 100 100 100 200 200" visibility="true" name="helpButton" audio="click.ogg" onclick="playSound, nextScene"/>
</scene>
</xml>
我从logcat收到以下错误:
04-23 05:24:15.198: D/AndroidRuntime(1919): Shutting down VM
04-23 05:24:15.198: W/dalvikvm(1919): threadid=1: thread exiting with uncaught exception (group=0xb3a4aba8)
04-23 05:24:15.208: E/AndroidRuntime(1919): FATAL EXCEPTION: main
04-23 05:24:15.208: E/AndroidRuntime(1919): Process: com.test.farm, PID: 1919
04-23 05:24:15.208: E/AndroidRuntime(1919): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.test.farm/com.test.farm.SceneMngr}: java.lang.NullPointerException
04-23 05:24:15.208: E/AndroidRuntime(1919): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2121)
04-23 05:24:15.208: E/AndroidRuntime(1919): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
04-23 05:24:15.208: E/AndroidRuntime(1919): at android.app.ActivityThread.access$800(ActivityThread.java:135)
04-23 05:24:15.208: E/AndroidRuntime(1919): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
04-23 05:24:15.208: E/AndroidRuntime(1919): at android.os.Handler.dispatchMessage(Handler.java:102)
04-23 05:24:15.208: E/AndroidRuntime(1919): at android.os.Looper.loop(Looper.java:136)
04-23 05:24:15.208: E/AndroidRuntime(1919): at android.app.ActivityThread.main(ActivityThread.java:5017)
04-23 05:24:15.208: E/AndroidRuntime(1919): at java.lang.reflect.Method.invokeNative(Native Method)
04-23 05:24:15.208: E/AndroidRuntime(1919): at java.lang.reflect.Method.invoke(Method.java:515)
04-23 05:24:15.208: E/AndroidRuntime(1919): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
04-23 05:24:15.208: E/AndroidRuntime(1919): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
04-23 05:24:15.208: E/AndroidRuntime(1919): at dalvik.system.NativeStart.main(Native Method)
04-23 05:24:15.208: E/AndroidRuntime(1919): Caused by: java.lang.NullPointerException
04-23 05:24:15.208: E/AndroidRuntime(1919): at android.content.ContextWrapper.getAssets(ContextWrapper.java:83)
04-23 05:24:15.208: E/AndroidRuntime(1919): at com.test.farm.SceneMngr.<init>(SceneMngr.java:42)
04-23 05:24:15.208: E/AndroidRuntime(1919): at java.lang.Class.newInstanceImpl(Native Method)
04-23 05:24:15.208: E/AndroidRuntime(1919): at java.lang.Class.newInstance(Class.java:1208)
04-23 05:24:15.208: E/AndroidRuntime(1919): at android.app.Instrumentation.newActivity(Instrumentation.java:1061)
04-23 05:24:15.208: E/AndroidRuntime(1919): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2112)
04-23 05:24:15.208: E/AndroidRuntime(1919): ... 11 more
和清单文件:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.farm"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-sdk android:minSdkVersion="3" android:targetSdkVersion="19"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity android:name=".SceneMngr"
android:label="SceneManager"
android:configChanges="keyboard|keyboardHidden|orientation"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
任何想法导致此错误的原因是什么?我已经在控制台中尝试了代码部分,它正在运行。
答案 0 :(得分:0)
在调用Context
之前,您无法引用onCreate()
,因此您应在AssetManager
中指定onCreate()
。
private AssetManager assMan;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
assMan = getAssets();
此外,您还有其他问题,WakeLock
未发布,根本不需要您的目的。相反,请使用keepScreenOn
的{{1}} attrubute。这不需要View
权限。
WAKE_LOCK
答案 1 :(得分:-1)
你应该在activity.oncreate()
中调用getAssets()