`
yezhiqiu-love
  • 浏览: 169837 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

AndEngine 分析之一-----Loading Resources In The Background With A Loading Screen

阅读更多
Loading Resources In The Background With A Loading Screen

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.

分享到:
评论

相关推荐

    AndEngine游戏-DeliveryBoy-源代码

    《AndEngine游戏-DeliveryBoy-源代码》是一个用于学习AndEngine游戏开发的示例项目,其主要内容涵盖了AndEngine的基本使用、游戏逻辑构建以及资源管理等多个方面。AndEngine是一款流行的开源Android游戏开发引擎,它...

    AndEngine_分析之三-----AsyncTask_BaseActivity备忘

    ### AndEngine分析之三——AsyncTask与BaseActivity深入解析 #### 一、AsyncTask概述 在AndEngine项目中,为了实现界面更新等操作时避免主线程阻塞的问题,使用了`AsyncTask`来处理后台任务。`AsyncTask`提供了一...

    AndEngine_分析之一----载入资源 这个是英文的

    在Android游戏开发中,AndEngine是一个非常流行的2D游戏引擎,它允许开发者创建高质量的图形和交互式体验。本文将探讨如何在AndEngine中实现后台加载资源,同时展示一个使用AsyncTask来处理加载过程的示例。 在...

    AndEngine_分析之二-----BaseGameActivity. 中文

    BaseGameActivity 是 AndEngine 框架中一个关键的组件,它是游戏的基础,负责管理游戏的引擎和SurfaceView。它继承自 BaseActivity,并实现了 IGameInterface 接口。 BaseGameActivity 的主要作用是: 1. 创建...

    AndEngine-GLES2-Example Eclipse Android 工程

    AndEngine 2013-2月 最新Example,直接导入Eclipse即可,API15, 环境 Android 4.0.3

    AndEngine游戏开发指南-初级篇.pdf

    AndEngine是一个开源的2D游戏开发框架,它基于libGDX框架开发,使用OpenGL ES(Open Graphics Library for Embedded Systems)进行图形绘制,并通过Java本地接口(JNI)调用底层的C++代码来实现高性能的游戏开发。...

    andengine-gles2.jar

    AndEngine 2013-3-12 最新Jar包,直接拉进项目libs即可,可查看源代码

    AndEngine-GLES2

    AndEngine-GLES2是一款专为Android平台设计的开源2D游戏引擎,它为开发者提供了高效且易用的工具,用于创建各种2D游戏。这款引擎以其简洁的API和丰富的功能而受到开发者的欢迎,尤其值得一提的是,曾经风靡全球的...

    andengine源码及demo

    AndEngine是一款专为Android平台设计的2D游戏开发框架,它提供了一套高效、易用的API,使得开发者能够快速构建各种2D游戏。AndEngine源码的分析和理解对于想要深入学习Android游戏开发的人来说至关重要。 1. **...

    andengine-physicseditor-extension.jar

    官方版本,亲测可用

    AndEngine范例-源码

    AndEngine是一款专为Android平台设计的游戏开发引擎,它简化了2D游戏的创建过程,让开发者无需深入理解底层图形库,就能快速构建出高质量的移动游戏。本资源提供了AndEngine的范例源码,这对于初学者和有经验的...

    AndEngine-GLES2源码

    AndEngine-GLES2是一款专为Android平台设计的游戏开发框架,基于OpenGL ES 2.0图形库,提供了一套高效、易用的API,使得开发者能够快速构建2D游戏。源码的获取对于深入理解AndEngine的工作原理以及进行自定义扩展至...

    Andengine-Android-Studio:用于游戏引擎的 Android Studio 模块,流行的标题和引擎

    Andengine-Android-Studio是将Andengine集成到Android Studio的模块,方便开发者在现代的Android开发环境中进行游戏开发。 Andengine的主要特点包括: 1. **轻量级**:Andengine的体积小巧,性能高效,对设备资源...

    AndEngine游戏开发示例

    AndEngine是一款专为Android平台设计的游戏开发框架,它简化了2D游戏的创建过程,让开发者无需深入理解底层图形库,就能快速构建出高质量的移动游戏。本示例旨在介绍如何利用AndEngine进行游戏开发,通过实例化引擎...

    andengine2.0开发的小游戏

    AndEngine是一款开源的2D游戏开发引擎,专为Android平台设计。它简化了在Android设备上构建高质量2D游戏的过程,提供了丰富的图形处理、物理引擎和动画功能。在这个"andengine2.0开发的小游戏"中,我们可以看到作者...

    AndEngine的官网下载的Demo

    AndEngine是一款针对Android平台开发2D游戏的开源引擎,它以简单易用和高效著称。这个Demo是AndEngine官方网站提供的示例集合,用于帮助开发者更好地理解和学习如何使用AndEngine来构建游戏。以下是对AndEngine及其...

    andEngine最新版的JAVA-DOC

    用andEngine最新的代码,然后用javadoc和easychm工具将它做成了chm格式的帮助文档,现在传到了上面,有需要的朋友可以下载

    AndEngine下载

    AndEngine是一款专为Android平台设计的2D游戏开发引擎,由Nathan Greno开发并维护。这个引擎以其轻量级、高效能和易用性而受到开发者们的青睐,特别是对于那些希望快速创建2D游戏或者没有太多图形编程经验的开发者来...

    andengine案例,jar包

    8. **易于上手**:AndEngine的设计目标之一就是易用性,它提供了清晰的API文档和活跃的社区支持,使开发者能更快地入门并开发出自己的游戏。 在使用AndEngine时,开发者需要注意以下几点: - **兼容性**:虽然...

    AndEngine的jar包

    AndEngine是一款专为Android平台设计的游戏开发框架,它允许开发者使用Java语言进行2D游戏的创建,无需深入了解OpenGL ES的底层细节。这个“AndEngine的jar包”是AndEngine的核心库,包含了AndEngine的所有功能模块...

Global site tag (gtag.js) - Google Analytics