Loading Resources In The Background With A Loading Screen
来源:互联网 发布:网络教育辅导题 编辑:程序博客网 时间:2024/05/24 07:12
Well, after searching for this for the last two days it seems that either no one has figured it out, or no one has shared such information.
So, here goes.
I read about people trying this with opening new threads and trying to put the loading on the update thread or the UI thread to no avail. I found the AsyncTask for android after remembering how we did it with XNA.
Making an AsyncTask is simple, here's the API from google: Here
For those who would like a little more instruction and some code, read on.
As far as how I implement my game as some background, I don't use different activities, I just use scenes. This is my first game and I only need 3 different scenes, I'll probably do activities in the future. (by no means is my way the best way I'm sure, this is for illustrative purposes)
I made my own subclass of scene:
import org.anddev.andengine.engine.Engine;import org.anddev.andengine.entity.scene.Scene;public abstract class GameScene extends Scene { protected Engine _engine; public GameScene(int pLayerCount, Engine baseEngine) { super(pLayerCount); _engine = baseEngine; } // =========================================================== // Inherited Methods // =========================================================== protected abstract void onLoadResources(); protected abstract void onLoadScene(); protected abstract void unloadScene(); protected abstract void onLoadComplete(); // =========================================================== // Methods // =========================================================== public void LoadResources(boolean loadSceneAutomatically){ this.onLoadResources(); if(loadSceneAutomatically){ this.onLoadScene(); } } public void LoadScene(){ this.onLoadScene(); }}
From here I've got a subclass of this for each of my three game scenes. I create the scene, tell it to load it's resources and then set the scene as the main scene.
If I provide true to LoadResources it will load the scene automatically. I would use this for anything that doesn't have a lot to load. My PlayScene on the other hand, has all of my game images to load.
Here's where the AsyncLoader comes in.
You have to create your own subclass of AsyncTask as stated in the API. From here you send to it the parameters. I made life simple by creating an interface IAsyncCallback to use as a parameter:
public interface IAsyncCallback { // =========================================================== // Methods // =========================================================== public abstract void workToDo(); public abstract void onComplete();}
Now, here's my subclass of AsyncTask:
import android.os.AsyncTask;public class AsyncTaskLoader extends AsyncTask<IAsyncCallback, Integer, Boolean> { // =========================================================== // Fields // =========================================================== IAsyncCallback[] _params; // =========================================================== // Inherited Methods // =========================================================== @Override protected Boolean doInBackground(IAsyncCallback... params) { this._params = params; int count = params.length; for(int i = 0; i < count; i++){ params[i].workToDo(); } return true; } @Override protected void onPostExecute(Boolean result) { int count = this._params.length; for(int i = 0; i < count; i++){ this._params[i].onComplete(); } }}
This simply calls the workToDo method on each of the parameters (no idea why you would want more than one in this case but that's how AsyncTask is built) and then calls onComplete when it's done.
From here you have to simply create an IAsyncCallback in your onLoadResources with all of your asset loading in the workToDo method, and onLoadScene in the onComplete. Then execute the AsyncTask:
@Override protected void onLoadResources(){ IAsyncCallback callback = new IAsyncCallback() { @Override public void workToDo() { TextureRegionFactory.setAssetBasePath("gfx/game/"); FontFactory.setAssetBasePath("font/"); PlayScene.this._backgroundTexture = new Texture(512, 1024, TextureOptions.BILINEAR_PREMULTIPLYALPHA); PlayScene.this._backgroundTextureRegion = TextureRegionFactory.createFromAsset(PlayScene.this._backgroundTexture, Game.Instance, "background0.png", 0, 0); PlayScene.this._backgroundTextureRegion2 = TextureRegionFactory.createFromAsset(PlayScene.this._backgroundTexture, Game.Instance, "background0.png", 0, 0); PlayScene.this._backgroundTextureRegion2.setFlippedVertical(true); PlayScene.this._faceTexture = new Texture(32,32,TextureOptions.BILINEAR_PREMULTIPLYALPHA); PlayScene.this._faceTextureRegion = TextureRegionFactory.createTiledFromAsset(PlayScene.this._faceTexture,Game.Instance,"face_box.png", 0,0,1,1); PlayScene.this._iffishTexture = new Texture(512,512,TextureOptions.BILINEAR_PREMULTIPLYALPHA); PlayScene.this._iffishTextureTile = TextureRegionFactory.createTiledFromAsset(PlayScene.this._iffishTexture, Game.Instance, "Iffisch.png", 0, 0, 5, 3); PlayScene.this._enemyTextures = new Texture(512,512,TextureOptions.BILINEAR_PREMULTIPLYALPHA); PlayScene.this._blowFishEnemyTextureTile = TextureRegionFactory.createTiledFromAsset(PlayScene.this._enemyTextures, Game.Instance, "blowey.png", 0, 0, 1, 1); PlayScene.this._faerieTexture = new Texture(64,64,TextureOptions.BILINEAR_PREMULTIPLYALPHA); PlayScene.this._faerieTextureRegion = TextureRegionFactory.createFromAsset(PlayScene.this._faerieTexture,Game.Instance,"faerie.png",0,0); PlayScene.this._inGameFontTexture = new Texture(512, 512, TextureOptions.BILINEAR_PREMULTIPLYALPHA); PlayScene.this._respawnFont = FontFactory.createFromAsset(PlayScene.this._inGameFontTexture, Game.Instance, "ANDYB.TTF", 32, true, Color.WHITE); PlayScene.this._hudFontTexture = new Texture(512, 512, TextureOptions.BILINEAR_PREMULTIPLYALPHA); PlayScene.this._hudFont = FontFactory.createFromAsset(PlayScene.this._hudFontTexture, Game.Instance, "ANDYB.TTF", 24, true, Color.BLACK); PlayScene.this._analogControlTexture = new Texture(512,256, TextureOptions.BILINEAR_PREMULTIPLYALPHA); PlayScene.this._analogBGTextureRegion = TextureRegionFactory.createFromAsset(PlayScene.this._analogControlTexture, Game.Instance, "analogControls.png", 0, 0); PlayScene.this._analogStickTextureRegion = TextureRegionFactory.createFromAsset(PlayScene.this._analogControlTexture, Game.Instance, "analogStick.png", 0, 75); PlayScene.this._scoreHudTextureRegion = TextureRegionFactory.createFromAsset(PlayScene.this._analogControlTexture, Game.Instance, "scoreHud.png", 49, 75); PlayScene.this._engine.getTextureManager().loadTextures(_enemyTextures, _backgroundTexture, _iffishTexture, _faceTexture, _inGameFontTexture, _faerieTexture, _analogControlTexture, _hudFontTexture); PlayScene.this._engine.getFontManager().loadFonts(_respawnFont, _hudFont); } @Override public void onComplete() { PlayScene.this.onLoadScene(); } }; new AsyncTaskLoader().execute(callback); }Then, just make sure you have setScene in your onLoadScene:
@Override protected void onLoadScene() { // set this as the main scene after loading this._engine.setScene(this);... your scene load stuff here..}
Just about done! Now you create a new GameScene (or PlayScene in this case) and pass false to the LoadResources.
This way it will create the scene, LoadResources will call onLoadResources which will execute the AsyncTask of loading the resources and then call onLoadScene which sets that scene as the main scene and loads up:
I do this from within another scene (I'm working on unloading it after the next one is loaded, so that you'll have to sort out yourself :) ) which creates a loading animation. It will play this animation until all of the next scene's resources are loaded and the new one sets itself as the main scene.
import org.anddev.andengine.engine.Engine;import org.anddev.andengine.engine.handler.IUpdateHandler;import org.anddev.andengine.engine.handler.timer.ITimerCallback;import org.anddev.andengine.engine.handler.timer.TimerHandler;import org.anddev.andengine.entity.scene.background.ColorBackground;import org.anddev.andengine.entity.sprite.AnimatedSprite;import org.anddev.andengine.opengl.texture.Texture;import org.anddev.andengine.opengl.texture.TextureOptions;import org.anddev.andengine.opengl.texture.region.TextureRegionFactory;import org.anddev.andengine.opengl.texture.region.TiledTextureRegion;public class LoadingScene extends GameScene { public LoadingScene(int pLayerCount, Engine baseEngine) { super(pLayerCount, baseEngine); } // =========================================================== // Fields // =========================================================== private Texture _loadingTexture; private TiledTextureRegion _loadingTextureRegion; // =========================================================== // Constants // =========================================================== // =========================================================== // Inherited Methods // =========================================================== @Override protected void onLoadResources() { TextureRegionFactory.setAssetBasePath("gfx/"); _loadingTexture = new Texture(512, 128, TextureOptions.BILINEAR_PREMULTIPLYALPHA); _loadingTextureRegion = TextureRegionFactory.createTiledFromAsset(_loadingTexture, Game.Instance, "loading.png", 0, 0, 2, 2); this._engine.getTextureManager().loadTexture(_loadingTexture); } @Override protected void onLoadScene() { this.setBackground(new ColorBackground(1,1,1)); AnimatedSprite loader = new AnimatedSprite(0, 0, _loadingTextureRegion); loader.setPosition((Game.CAMERA_WIDTH / 2) - (loader.getWidthScaled() / 2), (Game.CAMERA_HEIGHT / 2) - (loader.getHeightScaled() / 2)); loader.animate(300, true); this.getTopLayer().addEntity(loader); final PlayScene gameScene = new PlayScene(3,this._engine); gameScene.LoadResources(false); } @Override protected void unloadScene() {} @Override protected void onLoadComplete() {} // =========================================================== // Methods // ===========================================================}
Whew! Extremely loooong winded and pretty specific to my game but this should give a decent idea as to how this works :)
Any questions, comments or feedback is more than welcome. I'm also putting this up in the wiki.
原文地址
===============
最后吐槽下:csdn这排版比起原文的那个网站差远了,简直就是土鳖,还不求上进。
- Loading Resources In The Background With A Loading Screen
- 【AndEngine】 Loading Resources in background
- Loading Data in the Background 之Running a Query with a CursorLoader
- Loading Data in the Background 之Handling the Results
- Loading a TensorFlow graph with the C++ API
- Loading Resources Conditionally
- (error) LOADING Redis is loading the dataset in memory问题解决
- (error) LOADING Redis is loading the dataset in memory问题解决
- Loading a true type font with GDI+
- Loading a 3D scene with libGDX
- The Proccess of Loading and Executing a Specific Program in Linux Kernel
- Unity Loading Resources at Runtime
- 【Loading Resources】iOS Supports Device-Specific Resources
- Loading.....
- loading...
- Loading
- loading
- loading
- Java微信公众平台开发模式+自定义按钮源码
- 数据库日期处理
- Windows下R的编辑器(eclipse)
- jquery鼠标事件
- Android自定义组合控件之自定义属性
- Loading Resources In The Background With A Loading Screen
- 这有什么不好
- Java线程比较
- 查询块的几种简单使用
- 如何强制访问c++私有成员
- android中textview字数过长解决方法
- Cocos2d-x 添加字体库
- Linux Shell 进制错误 - value too great for base
- slim错误"failed to execute login command"