开发者

How to retain the state of a activity that has a GLSurfaceView

My problem is our game can switch into menu and setting mode instantly but it will need 4-6 seconds to load texture, init GL render mode eventually I just used 6 simple textures to create 6 sprites in game.

Please help me answer two questions: 1. How can I preload our assets in android os to start our game quicker? 2. In order to use a trick to create instance switch between activity, how can I retain my activity with GLSurfaceView state?

I order to help you understanding my situation, please read the following code:

The game using 3 activities as you can see in following configuration:

 <application android:label="@string/app_name"
  android:icon="@drawable/icon" android:allowBackup="true">
  <activity android:name=".Menu" android:screenOrientation="portrait" 
  android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
  android:launchMode="singleTop">
   <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
   </intent-filter>

  </activity>
  <activity android:name=".ReTouch" android:screenOrientation="portrait" />

  <activity android:name=".Preference" android:screenOrientation="portrait" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" />

 </application>

My .ReTouch class is a class that extended from RokonActivity (I am using rokon engine for my game), this engine will create a GLSurefaceView to render my game in OpenGL ES You can get RokonAcitivity's source code here: http://code.google.com/p/rokon/source/browse/tags/release/1.1.1/src/com/stickycoding/Rokon/RokonActivity.java

 public class ReTouch extends RokonActivity {
 public static final int REPLAY_DELAY_INTERVAL = 1000;
 private ReTouchGameBoard reTouchGame;

and .Menu, .Preference are two normal standard activity in an android application.

I am using this method to start and switch between activities:

  playButton.setOnClickListener(new OnClickListener() {

   public void onClick(View v) {
    soundPool.play(soundId, 1, 1, 1, 0, 1);
开发者_运维问答    startActivity(new Intent(Menu.this, ReTouch.class));
   }
  });
  settingButton.setOnClickListener(new OnClickListener() {

   public void onClick(View v) {
    soundPool.play(soundId, 1, 1, 1, 0, 1);
    startActivity(new Intent(Menu.this, Preference.class));
   }
  });
  quitButton.setOnClickListener(new OnClickListener() {

   public void onClick(View v) {
    soundPool.play(soundId, 1, 1, 1, 0, 1);
    finish();
   }
  });


I avoided this problem rather than solve it for my game:

I use a 'FrameLayout' as the main layout, with the 'GLSurfaceView' as the first layout inside it (i.e. at the bottom of the stack), the 'menu' viewgroup next, and an opaque 'loading' screen top of it (set to match_parent to fill the screen):

<FrameLayout 
    android:id="@+id/graphics_frameLayout1" 
    android:layout_width="fill_parent" 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_height="fill_parent">
    <android.opengl.GLSurfaceView 
        android:id="@+id/graphics_glsurfaceview1" 
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent">
    </android.opengl.GLSurfaceView>
    <LinearLayout
        android:id="@+id/menu_linearLayout1"
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent"
        android:visiblility="gone"
        android:background="#000000">// opaque background
        // menus etc be here
    </LinearLayout>
    <LinearLayout       
        android:layout_height="fill_parent" 
        android:id="@+id/loading_linearLayout1" 
        android:layout_width="fill_parent" 
        android:orientation="vertical"
        android:background="#000000">// opaque background
        <ProgressBar 
            style="?android:attr/progressBarStyleLarge" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:id="@+id/loading_progressBar1">
        </ProgressBar>
        <TextView 
            android:layout_width="wrap_content" 
            android:id="@+id/loading_textView1" 
            android:layout_height="wrap_content" 
            android:text="Loading...">
        </TextView>
    </LinearLayout>
</FrameLayout>

When the loading has finished, I set the loading viewgroup to invisible or gone, and the menu viewgroup to visible. Once the user has selected the option to start the game, I start the game logic thread and make the menu gone again

I have a hierarchy of activities (ReTouchMenuActivity extends ReTouchActivity, then in a new file, ReTouchActivity extends RokonActivity) so that I don't end up with the whole game in a single, unmanageable file

I load other assets in separate threads (for example, vertex data for 3D models) and then load in the vertices, texture coords etc just prior to drawing arrays (i.e. gl.glVertexPointer(3, GL10.GL_FLOAT, 0, meshVertices);

The real problem is that you have to load the textures in the GL Thread, which can block the UI thread (though without crashing it) leading to no responsiveness to user input when loading large textures. My own game using the above on a ZTE Blade running android 2.1 can take up to two seconds to load some large textures (1mb+) and even the circular progress bar stops spinning during this time.

I noticed you finish() the activity when the user clicks the quit button, but when the user leaves the app without clicking the quit button (say when they get an incoming call or select something from the notifications bar), the activity/app still runs in the background. You have to re-load textures when they bring the activity/app back to the top of the stack (i.e. the user re-opens it). If you don't re-load textures in such a scenario, the user will just get a load of blank instead of textures

If you try saving as a variable the GL handle/object that android passes to your Renderer class' onDraw method, for use by a texture-loading thread for example, then it goes out of context after the onDraw method returns and texture loading fails.

I assume is because android wipes all the graphics data / openGL state, when the user leaves the app, in case other apps want to use it. Therefore I assume you can't do precisely what you're aiming to do (preload textures in android os or whatever). Though if someone else knows better, I'd be interested in hearing.

Edit:

This question has some good answers about speeding up actual load time for textures

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜