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

来源:互联网 发布:gxsec软件 编辑:程序博客网 时间:2024/05/16 07:56

转自:http://blog.csdn.net/cen616899547/article/details/8190603

 

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张图片,四个精灵和一张背景,内部成员变量如下设计

[java] view plaincopyprint?
  1. private staticfinalint CAMERA_WIDTH =800;
  2. private staticfinalint CAMERA_HEIGHT =480;
  3. private staticfinal FixtureDef FIXTURE_DEF = PhysicsFactory.createFixtureDef(1,0.5f,0.5f);
  4. private TiledTextureRegion mBoxRegion;
  5. private TiledTextureRegion mCircleRegion;
  6. private TiledTextureRegion mTriangleRegion;
  7. private TiledTextureRegion mHexagonRegion;
  8. private SpriteBackground mBackground;
  9. private PhysicsWorld mPhysicsWorld;
  10. private int mSpriteCount =0;

PhysicsWorld是这节内容的重点,是基于Box2D插件来的,具体的内容可以看源代码

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

[java] view plaincopyprint?
  1. @Override
  2. public EngineOptions onCreateEngineOptions() {
  3. // TODO Auto-generated method stub
  4. SmoothCamera mCamera = new SmoothCamera(0,0, CAMERA_WIDTH, CAMERA_HEIGHT,10,10,5);
  5. EngineOptions mEngineOptions = new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED,new RatioResolutionPolicy(CAMERA_WIDTH,CAMERA_HEIGHT),mCamera);
  6. return mEngineOptions;
  7. }
  8. @Override
  9. public void onCreateResources(
  10. OnCreateResourcesCallback pOnCreateResourcesCallback)
  11. throws Exception {
  12. // TODO Auto-generated method stub
  13. final BitmapTextureAtlas mTexture =new BitmapTextureAtlas(getTextureManager(),1024,1024, TextureOptions.BILINEAR_PREMULTIPLYALPHA);;
  14. final TiledTextureRegion mBackgroundRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mTexture,this,"bg.png",0,0,1,1);
  15. mBackground = new SpriteBackground(new Sprite(0,0,CAMERA_WIDTH ,CAMERA_HEIGHT , mBackgroundRegion, getVertexBufferObjectManager()));
  16. mBoxRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mTexture,this,"face_box_tiled.png",0,640,2,1);
  17. mCircleRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mTexture,this,"face_circle_tiled.png",64,640,2,1);
  18. mTriangleRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mTexture,this,"face_triangle_tiled.png",128,640,2,1);
  19. mHexagonRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mTexture,this,"face_hexagon_tiled.png",192,640,2,1);
  20. mTexture.load();
  21. pOnCreateResourcesCallback.onCreateResourcesFinished();
  22. }

3.创建场景,配置sensor和touch参数

[java] view plaincopyprint?
  1. Scene mScene = new Scene();
  2. mScene.setBackground(mBackground);
  3. this.enableAccelerationSensor(this);
  4. mScene.setOnSceneTouchListener(this);


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

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

[java] view plaincopyprint?
  1. this.mPhysicsWorld = new PhysicsWorld(new Vector2(0,SensorManager.GRAVITY_EARTH),false);
  2. final IAreaShape ground = new Rectangle(0, CAMERA_HEIGHT -2, CAMERA_WIDTH,2, getVertexBufferObjectManager());
  3. final IAreaShape roof =new Rectangle(0,0, CAMERA_WIDTH,2,getVertexBufferObjectManager());
  4. final IAreaShape left = new Rectangle(0,0,2,CAMERA_HEIGHT,getVertexBufferObjectManager());
  5. final IAreaShape right =new Rectangle(CAMERA_WIDTH-2,0,2,CAMERA_HEIGHT,getVertexBufferObjectManager());


5.在模拟的物理世界中创建精灵实体

[java] view plaincopyprint?
  1. final FixtureDef wallFixtureDef = PhysicsFactory.createFixtureDef(0,0.5f,0.5f);
  2. PhysicsFactory.createBoxBody(mPhysicsWorld, ground, BodyType.StaticBody, wallFixtureDef);
  3. PhysicsFactory.createBoxBody(mPhysicsWorld, roof, BodyType.StaticBody, wallFixtureDef);
  4. PhysicsFactory.createBoxBody(mPhysicsWorld, left, BodyType.StaticBody, wallFixtureDef);
  5. PhysicsFactory.createBoxBody(mPhysicsWorld, right, BodyType.StaticBody, wallFixtureDef);

在这里的Fixture,是用来描述实体的:比如密度,弹性,和摩擦.这些内容我们在物理学中都有了解的

[java] view plaincopyprint?
  1. public static FixtureDef createFixtureDef(finalfloat pDensity,finalfloat pElasticity,finalfloat pFriction) {
  2. return PhysicsFactory.createFixtureDef(pDensity, pElasticity, pFriction,false);

BodyType选择的是StaticBody,因为这里要求的限制框不能随着重力,碰撞等进行移动的,如果要移动的,像我们的精灵一样的,就要使用BodyType.DynamicBody类型

的啦

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

[java] view plaincopyprint?
  1. mScene.attachChild(ground);
  2. mScene.attachChild(roof);
  3. mScene.attachChild(left);
  4. mScene.attachChild(right);
  5. mScene.registerUpdateHandler(this.mPhysicsWorld);
  6. pOnCreateSceneCallback.onCreateSceneFinished(mScene);


 

5.画龙点睛

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

[java] view plaincopyprint?
  1. @Override
  2. public void onAccelerationAccuracyChanged(AccelerationData pAccelerationData) {
  3. // TODO Auto-generated method stub
  4. }
  5. @Override
  6. public void onAccelerationChanged(AccelerationData pAccelerationData) {
  7. // TODO Auto-generated method stub
  8. this.mPhysicsWorld.setGravity(new Vector2(pAccelerationData.getX(),pAccelerationData.getY()));
  9. }


 

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

[java] view plaincopyprint?
  1. @Override
  2. public boolean onSceneTouchEvent(Scene pScene,final TouchEvent pSceneTouchEvent) {
  3. // TODO Auto-generated method stub
  4. if(this.mPhysicsWorld !=null){
  5. if(pSceneTouchEvent.getAction() == TouchEvent.ACTION_DOWN){
  6. this.runOnUpdateThread(new Runnable(){
  7. @Override
  8. public void run() {
  9. // TODO Auto-generated method stub
  10. MyPhysics.this.addFace(pSceneTouchEvent.getX(), pSceneTouchEvent.getY());
  11. }
  12. });
  13. }
  14. return true;
  15. }
  16. return false;
  17. }


 

3.实现addFace函数

[java] view plaincopyprint?
  1. private void addFace(finalfloat pX,finalfloat pY){
  2. final Scene scene = this.mEngine.getScene();
  3. this.mSpriteCount++;
  4. final AnimatedSprite face;
  5. final Body body;
  6. if(this.mSpriteCount %4 ==0){//矩形
  7. face = new AnimatedSprite(pX, pY, mBoxRegion, getVertexBufferObjectManager());
  8. body = PhysicsFactory.createBoxBody(mPhysicsWorld, face, BodyType.DynamicBody, FIXTURE_DEF);
  9. face.animate(250);
  10. scene.attachChild(face);
  11. PhysicsConnector connector = new PhysicsConnector(face,body,true,true);
  12. this.mPhysicsWorld.registerPhysicsConnector(connector);
  13. }
  14. else if(this.mSpriteCount %4 ==1){//圆形
  15. face = new AnimatedSprite(pX,pY,mCircleRegion,getVertexBufferObjectManager() );
  16. body = PhysicsFactory.createCircleBody(mPhysicsWorld, face, BodyType.DynamicBody, FIXTURE_DEF);
  17. face.animate(250);
  18. scene.attachChild(face);
  19. PhysicsConnector connector = new PhysicsConnector(face,body,true,true);
  20. this.mPhysicsWorld.registerPhysicsConnector(connector);
  21. }
  22. else if(this.mSpriteCount %4 ==2){//三角形
  23. face = new AnimatedSprite(pX,pY,mTriangleRegion,getVertexBufferObjectManager() );
  24. final float halfWidth = face.getWidthScaled() *0.5f / PIXEL_TO_METER_RATIO_DEFAULT;
  25. final float halfHeight = face.getHeightScaled() *0.5f / PIXEL_TO_METER_RATIO_DEFAULT;
  26. ArrayList<Vector2> vectors = new ArrayList<Vector2>();
  27. vectors.add(new Vector2(0, - halfHeight));
  28. vectors.add(new Vector2(-halfWidth,halfHeight));
  29. vectors.add(new Vector2(halfWidth, halfHeight));
  30. body = PhysicsFactory.createTrianglulatedBody(mPhysicsWorld, face,vectors,BodyType.DynamicBody, FIXTURE_DEF);
  31. face.animate(250);
  32. scene.attachChild(face);
  33. PhysicsConnector connector = new PhysicsConnector(face,body,true,true);
  34. this.mPhysicsWorld.registerPhysicsConnector(connector);
  35. }
  36. else if(this.mSpriteCount %4 ==3){//六边形
  37. face = new AnimatedSprite(pX,pY,mHexagonRegion,getVertexBufferObjectManager() );
  38. final float halfWidth = face.getWidthScaled() *0.5f / PIXEL_TO_METER_RATIO_DEFAULT;
  39. final float halfHeight = face.getHeightScaled() *0.5f / PIXEL_TO_METER_RATIO_DEFAULT;
  40. /* The top and bottom vertex of the hexagon are on the bottom and top of hexagon-sprite. */
  41. final float top = -halfHeight;
  42. final float bottom = halfHeight;
  43. final float centerX =0;
  44. /* 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. */
  45. final float left = -halfWidth +2.5f / PIXEL_TO_METER_RATIO_DEFAULT;
  46. final float right = halfWidth -2.5f / PIXEL_TO_METER_RATIO_DEFAULT;
  47. final float higher = top +8.25f / PIXEL_TO_METER_RATIO_DEFAULT;
  48. final float lower = bottom -8.25f / PIXEL_TO_METER_RATIO_DEFAULT;
  49. final Vector2[] vertices = {
  50. new Vector2(centerX, top),
  51. new Vector2(right, higher),
  52. new Vector2(right, lower),
  53. new Vector2(centerX, bottom),
  54. new Vector2(left, lower),
  55. new Vector2(left, higher)
  56. };
  57. body = PhysicsFactory.createPolygonBody(mPhysicsWorld, face,vertices,BodyType.DynamicBody, FIXTURE_DEF);
  58. face.animate(250);
  59. scene.attachChild(face);
  60. PhysicsConnector connector = new PhysicsConnector(face,body,true,true);
  61. this.mPhysicsWorld.registerPhysicsConnector(connector);
  62. }
  63. }


 

6.运行游戏,看结果

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





 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 让荷兰猪咬了怎么办 仓鼠的脚被棉花怎么办 仓鼠的脚变黑了怎么办 夏天小仓鼠生了怎么办 把仓鼠摔出血了怎么办 仓鼠摔成骨折了怎么办 孩子被仓鼠咬了怎么办 仓鼠不咬磨牙石怎么办 仓鼠妈妈跑了宝宝怎么办 买的仓鼠繁殖了怎么办 仓鼠没有鼠粮了怎么办 仓鼠被踩吐血了怎么办? 买的蓝莓太酸怎么办 荷兰猪夏天掉毛怎么办 被猫抓伤肿了怎么办 荷兰猪鼻子破了怎么办 荷兰猪吃了包菜怎么办 龙猫不爱吃主粮怎么办 荷兰猪躲起来了怎么办 荷兰猪一直叫是怎么办 龙猫不吃粗的主粮怎么办 转龙猫中暑症状+龙猫中暑怎么办 火车上空调太冷怎么办 格力空调太冷怎么办 未满月龙猫宝宝怎么办 房间小空调太冷怎么办 奶猫半夜不睡觉怎么办 龙猫不喜欢吃草粒怎么办 龙猫一直在发抖怎么办 龙猫牙齿掉了怎么办 龙猫晚上很吵怎么办 小狗把手咬破了怎么办 夏天仓鼠太热了怎么办 仓鼠玩转轮会摔怎么办 如何发截图不会发现吐怎么办 嘴巴烂了药过敏怎么办 非法校车被扣了怎么办 手指削掉一块肉怎么办 在广州误走brt道怎么办 平安eq测试没过怎么办 物业在小区私自建房怎么办