上例子之前先罗嗦两句,AndEngine是通过业务线程处理各种变化的,可能包含计算、存储、交互等等,当然最重要的还是改变实体的状态,在渲染的时候会看到实质的改变。举个例子,在业务线程中将TileSprite的显示瓦片顺序的改变,渲染线程显示出来便成为了动画。当然这种改变是需要我们控制的,实体通过注册IUpdateHandler,或者注册IModifier,这两种方式将我们的业务注册到业务线程。下面一段程序清楚的描述了业务线程的行为:
/** * 对实体的onUpdate方法的实际处理函数 * * @param pSecondsElapsed 间隔秒数 */ protected void onManagedUpdate(final float pSecondsElapsed) { //本身注册的实体修改器的onUpdate if(this.mEntityModifiers != null) { this.mEntityModifiers.onUpdate(pSecondsElapsed); } //本身注册IUpdateHandler对象的onUpdate if(this.mUpdateHandlers != null) { this.mUpdateHandlers.onUpdate(pSecondsElapsed); } //调用子实体的onUpdate方法 if((this.mChildren != null) && !this.mChildrenIgnoreUpdate) { final SmartList<IEntity> entities = this.mChildren; final int entityCount = entities.size(); for(int i = 0; i < entityCount; i++) { entities.get(i).onUpdate(pSecondsElapsed); } } }IModifier相当于IUpdateHandler的增强版,不能拥有onUpdate的业务更新方法,而且增加状态监听功能、自动注销功能和持续时间的设置。在这次的例子中首先登场的就是IUpdateHandler的实现。好可以上代码了:
package org.andengine.examples; import org.andengine.engine.camera.Camera; import org.andengine.engine.handler.physics.PhysicsHandler; import org.andengine.engine.options.EngineOptions; import org.andengine.engine.options.ScreenOrientation; import org.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy; import org.andengine.entity.scene.Scene; import org.andengine.entity.scene.background.Background; import org.andengine.entity.sprite.AnimatedSprite; import org.andengine.entity.util.FPSLogger; import org.andengine.opengl.texture.TextureOptions; import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas; import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory; import org.andengine.opengl.texture.region.TiledTextureRegion; import org.andengine.opengl.vbo.VertexBufferObjectManager; import org.andengine.ui.activity.SimpleBaseGameActivity; public class MovingBallExample extends SimpleBaseGameActivity { private static final int CAMERA_WIDTH = 720; private static final int CAMERA_HEIGHT = 480; private static final float DEMO_VELOCITY = 100.0f; private BitmapTextureAtlas mBitmapTextureAtlas; private TiledTextureRegion mFaceTextureRegion; @Override public EngineOptions onCreateEngineOptions() { final Camera camera = new Camera(0, 0, MovingBallExample.CAMERA_WIDTH, MovingBallExample.CAMERA_HEIGHT); return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(MovingBallExample.CAMERA_WIDTH, MovingBallExample.CAMERA_HEIGHT), camera); } @Override public void onCreateResources() { BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/"); this.mBitmapTextureAtlas = new BitmapTextureAtlas(this.getTextureManager(), 64, 32, TextureOptions.BILINEAR); this.mFaceTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(this.mBitmapTextureAtlas, this, "face_circle_tiled.png", 0, 0, 2, 1); this.mBitmapTextureAtlas.load(); } @Override public Scene onCreateScene() { this.mEngine.registerUpdateHandler(new FPSLogger()); final Scene scene = new Scene(); scene.setBackground(new Background(0.09804f, 0.6274f, 0.8784f)); final float centerX = (MovingBallExample.CAMERA_WIDTH - this.mFaceTextureRegion.getWidth()) / 2; final float centerY = (MovingBallExample.CAMERA_HEIGHT - this.mFaceTextureRegion.getHeight()) / 2; final Ball ball = new Ball(centerX, centerY, this.mFaceTextureRegion, this.getVertexBufferObjectManager()); scene.attachChild(ball); return scene; } /** * 球精灵的定义,完全没有必要继承于AnimatedSprite,Sprit足以。 * @author Administrator */ private static class Ball extends AnimatedSprite { private final PhysicsHandler mPhysicsHandler; public Ball(final float pX, final float pY, final TiledTextureRegion pTextureRegion, final VertexBufferObjectManager pVertexBufferObjectManager) { super(pX, pY, pTextureRegion, pVertexBufferObjectManager); //一个模拟物理运动的IUpdateHandler,设置速度和加速度完成实体的运动。(构造函数的参数就是需要运动实体) this.mPhysicsHandler = new PhysicsHandler(this); this.registerUpdateHandler(this.mPhysicsHandler); this.mPhysicsHandler.setVelocity(MovingBallExample.DEMO_VELOCITY, MovingBallExample.DEMO_VELOCITY); } @Override protected void onManagedUpdate(final float pSecondsElapsed) { //X轴越界判断,改变mPhysicsHandler的X速度 if(this.mX < 0) { this.mPhysicsHandler.setVelocityX(MovingBallExample.DEMO_VELOCITY); } else if(this.mX + this.getWidth() > MovingBallExample.CAMERA_WIDTH) { this.mPhysicsHandler.setVelocityX(-MovingBallExample.DEMO_VELOCITY); } //Y轴越界判断,改变mPhysicsHandler的Y速度 if(this.mY < 0) { this.mPhysicsHandler.setVelocityY(MovingBallExample.DEMO_VELOCITY); } else if(this.mY + this.getHeight() > MovingBallExample.CAMERA_HEIGHT) { this.mPhysicsHandler.setVelocityY(-MovingBallExample.DEMO_VELOCITY); } super.onManagedUpdate(pSecondsElapsed); } } }代码一上貌似就没有什么好说的了,注意onManagedUpdate方法是业务线程调用的管理方法,每次业务轮换到业务线程的时候首先调用实体的onUpdate,接着调用实体的onManagedUpdate。相当于实体本身也是一个IUpdateHandler,自身就可以根据条件发生变化,同时也可以通过注册在实体的IUpdateHandler来改变。在这个例子中mPhysicsHandler完成了实体的直线运动,而实体本身完成了接触屏幕边缘改变运动方向,如此如此。