[AndEngine学习教程] 第10节 box2D 物理碰撞系统

来源:互联网 发布:美股行情软件 编辑:程序博客网 时间:2024/05/21 09:28

1.要点

    顾着忙工作的事情,两周多没有写微博了,在上一节,基于AndEngine做了个碰撞检测的例子.这个例子对学习基本原理的作用还是有的,

但是用在游戏上就逊色点了,这节,主要基于Box2D系统来做碰撞检测.

   Box2D是一个用于模拟2D刚体物体的c++引擎,这里使用的是AndEngine的扩张插件,为了能够高效高速的使用它,底层的实现都是c++编写的,然后通过jni

调用实现的.所以虽然使用java编写代码,但是运行的也很流畅的.

 2.本节学习内容

     本节主要学习在AndEngine下引入Box2D插件.然后构建的基本物理实体碰撞.本例子主要实现4中外形的实体碰撞:

    矩形实体,圆形实体,三角形实体和正六边形实体;同过触摸屏幕可循环

动态地添加这几种实体.在一个模拟的重力环境下,根据g-sensor的数据来碰撞运动

3.工程配置准备

     在本例程的开始,已经讲解了如何配置AndEngine的开发环境.现在主要介绍如何使用Box2D扩张插件

    1.到官网下载Box2D插件,网址:https://github.com/nicolasgramlich/AndEnginePhysicsBox2DExtension

     2.解压后放到AndEngine同一个目录下,在eclipse下通过file->new->project->Android Project from Exist code,

       下一步找到box2d解压的文件夹

           

         点击finish.这是回到eclipse,回出现错误,因为没有包含AndEngine库进去,把鼠标放到box2d工程上,右键:

         build path->configurate build path.然后按照下图的方法,导入AndEngine的库

         

    接着把box2d工程下libs的andenginephysicsbox2dextension.jar拷贝到你的工程目录下的libs下面.这样字就完成了最基本可以使用的配置了


    如果想要在自己的工程中很好的使用eclipse中提供的自动完成功能,建议在自己的工程中进行如下设置:

   1.在工程中右键:build path->configurate build path.选中上边的libraries面板,然后点击add library,如下图所示:

   


接着next,点击user libraries->new->输入"Box2D"名称


Ok后点击add JARs..,一路点击OK finish就可以了.,最后到初始界面,把Box2D的顺序网上挪动到第二个,就是在AndEngine下面就可以了,这样方便编译.


4.代码编写

   1.折腾完基础的东西后,当然华丽丽的写代码啦,本例子主要用到5张图片,四个精灵和一张背景,内部成员变量如下设计

    

private static final int CAMERA_WIDTH = 800;private static final int CAMERA_HEIGHT = 480;private static final FixtureDef FIXTURE_DEF = PhysicsFactory.createFixtureDef(1, 0.5f, 0.5f);private TiledTextureRegion mBoxRegion;private TiledTextureRegion mCircleRegion;private TiledTextureRegion mTriangleRegion;private TiledTextureRegion mHexagonRegion;private SpriteBackground mBackground;private PhysicsWorld mPhysicsWorld;private int mSpriteCount = 0;
PhysicsWorld是这节内容的重点,是基于Box2D插件来的,具体的内容可以看源代码

2.接着初始化相应的资源

@Overridepublic EngineOptions onCreateEngineOptions() {// TODO Auto-generated method stubSmoothCamera mCamera = new SmoothCamera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT, 10, 10, 5);EngineOptions mEngineOptions = new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED,new RatioResolutionPolicy(CAMERA_WIDTH,CAMERA_HEIGHT),mCamera);return mEngineOptions;}@Overridepublic void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback)throws Exception {// TODO Auto-generated method stubfinal BitmapTextureAtlas mTexture = new BitmapTextureAtlas(getTextureManager(), 1024, 1024, TextureOptions.BILINEAR_PREMULTIPLYALPHA);;final TiledTextureRegion mBackgroundRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mTexture, this, "bg.png", 0, 0, 1, 1);mBackground = new SpriteBackground(new Sprite(0, 0,CAMERA_WIDTH ,CAMERA_HEIGHT , mBackgroundRegion, getVertexBufferObjectManager()));mBoxRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mTexture, this, "face_box_tiled.png", 0, 640, 2, 1);mCircleRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mTexture, this, "face_circle_tiled.png", 64, 640, 2, 1);mTriangleRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mTexture, this, "face_triangle_tiled.png", 128, 640, 2, 1);mHexagonRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mTexture, this, "face_hexagon_tiled.png", 192, 640, 2, 1);    mTexture.load();    pOnCreateResourcesCallback.onCreateResourcesFinished();}
3.创建场景,配置sensor和touch参数

                Scene mScene = new Scene();mScene.setBackground(mBackground);this.enableAccelerationSensor(this);mScene.setOnSceneTouchListener(this);

4.有了场景的框架后,我们就开始创建模式的物理世界了,这个世界是有范围的,

我们把它限制在的整个屏幕内:通过屏幕的四条边框进行限制;

this.mPhysicsWorld = new PhysicsWorld(new Vector2(0,SensorManager.GRAVITY_EARTH), false);final IAreaShape ground = new Rectangle(0, CAMERA_HEIGHT - 2, CAMERA_WIDTH, 2, getVertexBufferObjectManager());final IAreaShape roof = new Rectangle(0, 0, CAMERA_WIDTH, 2,getVertexBufferObjectManager());final IAreaShape left = new Rectangle(0,0,2,CAMERA_HEIGHT,getVertexBufferObjectManager());final IAreaShape right = new Rectangle(CAMERA_WIDTH-2,0,2,CAMERA_HEIGHT,getVertexBufferObjectManager());

5.在模拟的物理世界中创建精灵实体
final FixtureDef wallFixtureDef = PhysicsFactory.createFixtureDef(0, 0.5f, 0.5f);PhysicsFactory.createBoxBody(mPhysicsWorld, ground, BodyType.StaticBody, wallFixtureDef);PhysicsFactory.createBoxBody(mPhysicsWorld, roof, BodyType.StaticBody, wallFixtureDef);PhysicsFactory.createBoxBody(mPhysicsWorld, left, BodyType.StaticBody, wallFixtureDef);PhysicsFactory.createBoxBody(mPhysicsWorld, right, BodyType.StaticBody, wallFixtureDef);
在这里的Fixture,是用来描述实体的:比如密度,弹性,和摩擦.这些内容我们在物理学中都有了解的

public static FixtureDef createFixtureDef(final float pDensity, final float pElasticity, final float pFriction) {return PhysicsFactory.createFixtureDef(pDensity, pElasticity, pFriction, false);
BodyType选择的是StaticBody,因为这里要求的限制框不能随着重力,碰撞等进行移动的,如果要移动的,像我们的精灵一样的,就要使用BodyType.DynamicBody类型

的啦

6.把各种角色加载到场景中去:

mScene.attachChild(ground);mScene.attachChild(roof);mScene.attachChild(left);mScene.attachChild(right);mScene.registerUpdateHandler(this.mPhysicsWorld);pOnCreateSceneCallback.onCreateSceneFinished(mScene);

5.画龙点睛

    1.使用手机上的g-sensor,让物理世界按照实际的倾斜来模拟

   

@Overridepublic void onAccelerationAccuracyChanged(AccelerationData pAccelerationData) {// TODO Auto-generated method stub}@Overridepublic void onAccelerationChanged(AccelerationData pAccelerationData) {// TODO Auto-generated method stubthis.mPhysicsWorld.setGravity(new Vector2(pAccelerationData.getX(),pAccelerationData.getY()));}

  2.实现点击屏幕,就在该处产生一个精灵:

@Overridepublic boolean onSceneTouchEvent(Scene pScene, final TouchEvent pSceneTouchEvent) {// TODO Auto-generated method stubif(this.mPhysicsWorld != null){if(pSceneTouchEvent.getAction() == TouchEvent.ACTION_DOWN){this.runOnUpdateThread(new Runnable(){@Overridepublic void run() {// TODO Auto-generated method stubMyPhysics.this.addFace(pSceneTouchEvent.getX(), pSceneTouchEvent.getY());}});}return true;}return false;}

 3.实现addFace函数

private void addFace( final float pX, final float pY){final Scene scene = this.mEngine.getScene();this.mSpriteCount++;final AnimatedSprite face;final Body body;if(this.mSpriteCount % 4 == 0){//矩形face = new AnimatedSprite(pX, pY, mBoxRegion, getVertexBufferObjectManager());body = PhysicsFactory.createBoxBody(mPhysicsWorld, face, BodyType.DynamicBody, FIXTURE_DEF);face.animate(250);scene.attachChild(face);PhysicsConnector connector = new PhysicsConnector(face,body,true,true);this.mPhysicsWorld.registerPhysicsConnector(connector);}else if(this.mSpriteCount % 4 == 1){//圆形face =  new AnimatedSprite(pX,pY,mCircleRegion,getVertexBufferObjectManager() );body = PhysicsFactory.createCircleBody(mPhysicsWorld, face, BodyType.DynamicBody, FIXTURE_DEF);    face.animate(250);    scene.attachChild(face);    PhysicsConnector connector = new PhysicsConnector(face,body,true,true);    this.mPhysicsWorld.registerPhysicsConnector(connector);}else if(this.mSpriteCount % 4 == 2){//三角形face =  new AnimatedSprite(pX,pY,mTriangleRegion,getVertexBufferObjectManager() );final float halfWidth = face.getWidthScaled() * 0.5f / PIXEL_TO_METER_RATIO_DEFAULT;final float halfHeight = face.getHeightScaled() * 0.5f / PIXEL_TO_METER_RATIO_DEFAULT;ArrayList<Vector2> vectors = new ArrayList<Vector2>();vectors.add(new  Vector2(0, - halfHeight));vectors.add(new Vector2(-halfWidth,halfHeight));vectors.add(new Vector2(halfWidth, halfHeight));body = PhysicsFactory.createTrianglulatedBody(mPhysicsWorld, face,vectors,BodyType.DynamicBody, FIXTURE_DEF);    face.animate(250);    scene.attachChild(face);    PhysicsConnector connector = new PhysicsConnector(face,body,true,true);    this.mPhysicsWorld.registerPhysicsConnector(connector);}else if(this.mSpriteCount % 4 == 3){//六边形face =  new AnimatedSprite(pX,pY,mHexagonRegion,getVertexBufferObjectManager() );final float halfWidth = face.getWidthScaled() * 0.5f / PIXEL_TO_METER_RATIO_DEFAULT;final float halfHeight = face.getHeightScaled() * 0.5f / PIXEL_TO_METER_RATIO_DEFAULT;/* The top and bottom vertex of the hexagon are on the bottom and top of hexagon-sprite. */final float top = -halfHeight;final float bottom = halfHeight;final float centerX = 0;/* The left and right vertices of the heaxgon are not on the edge of the hexagon-sprite, so we need to inset them a little. */final float left = -halfWidth + 2.5f / PIXEL_TO_METER_RATIO_DEFAULT;final float right = halfWidth - 2.5f / PIXEL_TO_METER_RATIO_DEFAULT;final float higher = top + 8.25f / PIXEL_TO_METER_RATIO_DEFAULT;final float lower = bottom - 8.25f / PIXEL_TO_METER_RATIO_DEFAULT;final Vector2[] vertices = {new Vector2(centerX, top),new Vector2(right, higher),new Vector2(right, lower),new Vector2(centerX, bottom),new Vector2(left, lower),new Vector2(left, higher)};body = PhysicsFactory.createPolygonBody(mPhysicsWorld, face,vertices,BodyType.DynamicBody, FIXTURE_DEF);    face.animate(250);    scene.attachChild(face);    PhysicsConnector connector = new PhysicsConnector(face,body,true,true);    this.mPhysicsWorld.registerPhysicsConnector(connector);}}

6.运行游戏,看结果

本例子的源代码:http://download.csdn.net/detail/cen616899547/4773538
















原创粉丝点击