在andengine编程之sprite(三)中,我们介绍了一些sprite对位置的设置以及对触摸的监听。这次,我们要再来介绍介绍sprite对位置的设置,但这一次,我们要借助另一个方式——物理引擎。
PhysicsHandler是一个比较基本的物理类,它主要是对sprite设置移动速度,加速度,角速度等。
下面,我们先来看看它的一些方法:
速度:
public void setVelocityX(final float pVelocityX) 和public void setVelocityY(final float pVelocityY):分别对X方向和Y方向设置速度。
public void setVelocity(final float pVelocity) :X方向和Y方向设置同一数值的速度。
public void setVelocity(final float pVelocityX, final float pVelocityY):对X方向和Y方向设置速度。
加速度:
public void setAccelerationX(final float pAccelerationX)和public void setAccelerationY(final float pAccelerationY):分别对X方向和Y方向设置加速度。
public void setAcceleration(final float pAcceleration):X方向和Y方向设置同一数值的加速度。
public void setAcceleration(final float pAccelerationX, final float pAccelerationY):对X方向和Y方向设置加速度。
public void accelerate(final float pAccelerationX, final float pAccelerationY):对X方向和Y方向加速度数值做累加修正,例如加速度一直在提升,非匀加速状态。
角速度:
public void setAngularVelocity(final float pAngularVelocity):设置角速度。
重置,清零:
public void reset():将所有设置都设置为零,即重置。
接下来,我们用一张坦克的图片来实现一下精灵的移动:
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception { Scene mScene = new Scene(); final AnimatedSprite tank = new AnimatedSprite(400, 200, mSpriteTiledTextureRegion, getVertexBufferObjectManager()); // 设置背景 mScene.setBackground(background); mScene.attachChild(tank); // 注册精灵要实现触摸效果 mScene.registerTouchArea(tank); // 构建运动机制 final PhysicsHandler physicsHandler = new PhysicsHandler(tank); tank.registerUpdateHandler(physicsHandler); // 为场景注册触摸监听事件 mScene.setOnSceneTouchListener(new IOnSceneTouchListener() { public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) { // 求得角度根据两个坐标,这里取一下坦克中心点作为坦克的坐标 final float angleRad = MathUtils.atan2( tank.getY() + tank.getHeight() / 2 - pSceneTouchEvent.getY(), (tank.getX() + tank.getWidth() / 2) - pSceneTouchEvent.getX()); // 求出移动的速度,这里也是根据三角形的计算法则,已知角度和总速度,求出X方向速度和Y方向速度 // 100f:即为其总速度 float VelocityX = FloatMath.cos(angleRad) * 100f; float VelocityY = FloatMath.sin(angleRad) * 100f; switch (pSceneTouchEvent.getAction()) { // 这里,我们只取了按下抬起时的效果,方便我们观察 case TouchEvent.ACTION_DOWN: case TouchEvent.ACTION_MOVE: // 为其设置X方向速度和Y方向速度 physicsHandler.setVelocity(-VelocityX, -VelocityY); // 为图片设置旋转角度(+ 90:为了修正旋转方向) tank.setRotation(MathUtils.radToDeg(angleRad) + 90); break; case TouchEvent.ACTION_UP: // 松开按键后,将运动状态还原 physicsHandler.reset(); break; } return true; } }); pOnCreateSceneCallback.onCreateSceneFinished(mScene); }
然后根据角度和速度,可以分别求的X方向速度和Y方向速度:即代码中所写的FloatMath.cos(angleRad) * 100f和FloatMath.sin(angleRad) * 100f。
package com.testsprite; import org.andengine.engine.camera.Camera; import org.andengine.engine.handler.physics.PhysicsHandler; import org.andengine.engine.options.EngineOptions; import org.andengine.engine.options.EngineOptions.ScreenOrientation; import org.andengine.engine.options.resolutionpolicy.FillResolutionPolicy; import org.andengine.entity.scene.IOnSceneTouchListener; import org.andengine.entity.scene.Scene; import org.andengine.entity.scene.background.RepeatingSpriteBackground; import org.andengine.entity.sprite.AnimatedSprite; import org.andengine.input.touch.TouchEvent; 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.atlas.bitmap.source.AssetBitmapTextureAtlasSource; import org.andengine.opengl.texture.region.TiledTextureRegion; import org.andengine.ui.activity.BaseGameActivity; import org.andengine.util.math.MathUtils; import android.util.FloatMath; public class TestSprite extends BaseGameActivity { private static final int CAMERA_WIDTH = 800; private static final int CAMERA_HEIGHT = 480; private RepeatingSpriteBackground background; private TiledTextureRegion mSpriteTiledTextureRegion; public EngineOptions onCreateEngineOptions() { Camera mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT); EngineOptions mEngineOptions = new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new FillResolutionPolicy(), mCamera); return mEngineOptions; } public void onCreateResources( OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception { this.background = new RepeatingSpriteBackground(800, 480, getTextureManager(), AssetBitmapTextureAtlasSource.create( this.getAssets(), "background.png"), getVertexBufferObjectManager()); BitmapTextureAtlas mBitmapTextureAtlas = new BitmapTextureAtlas( getTextureManager(), 128, 256, TextureOptions.DEFAULT); mSpriteTiledTextureRegion = BitmapTextureAtlasTextureRegionFactory .createTiledFromAsset(mBitmapTextureAtlas, this, "tank.png", 0, 0, 1, 1); mBitmapTextureAtlas.load(); pOnCreateResourcesCallback.onCreateResourcesFinished(); } public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception { Scene mScene = new Scene(); final AnimatedSprite tank = new AnimatedSprite(400, 200, mSpriteTiledTextureRegion, getVertexBufferObjectManager()); // 设置背景 mScene.setBackground(background); mScene.attachChild(tank); // 注册精灵要实现触摸效果 mScene.registerTouchArea(tank); // 构建运动机制 final PhysicsHandler physicsHandler = new PhysicsHandler(tank); tank.registerUpdateHandler(physicsHandler); // 为场景注册触摸监听事件 mScene.setOnSceneTouchListener(new IOnSceneTouchListener() { public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) { // 求得角度根据两个坐标,这里取一下坦克中心点作为坦克的坐标 final float angleRad = MathUtils.atan2( tank.getY() + tank.getHeight() / 2 - pSceneTouchEvent.getY(), (tank.getX() + tank.getWidth() / 2) - pSceneTouchEvent.getX()); // 求出移动的速度,这里也是根据三角形的计算法则,已知角度和总速度,求出X方向速度和Y方向速度 // 100f:即为其总速度 float VelocityX = FloatMath.cos(angleRad) * 100f; float VelocityY = FloatMath.sin(angleRad) * 100f; switch (pSceneTouchEvent.getAction()) { // 这里,我们只取了按下抬起时的效果,方便我们观察 case TouchEvent.ACTION_DOWN: case TouchEvent.ACTION_MOVE: // 为其设置X方向速度和Y方向速度 physicsHandler.setVelocity(-VelocityX, -VelocityY); // 为图片设置旋转角度(+ 90:为了修正旋转方向) tank.setRotation(MathUtils.radToDeg(angleRad) + 90); break; case TouchEvent.ACTION_UP: // 松开按键后,将运动状态还原 physicsHandler.reset(); break; } return true; } }); pOnCreateSceneCallback.onCreateSceneFinished(mScene); } public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception { pOnPopulateSceneCallback.onPopulateSceneFinished(); } }