[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张图片,四个精灵和一张背景,内部成员变量如下设计
- private staticfinalint CAMERA_WIDTH =800;
- private staticfinalint CAMERA_HEIGHT =480;
- private staticfinal 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.接着初始化相应的资源
- @Override
- public EngineOptions onCreateEngineOptions() {
- // TODO Auto-generated method stub
- SmoothCamera 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;
- }
- @Override
- public void onCreateResources(
- OnCreateResourcesCallback pOnCreateResourcesCallback)
- throws Exception {
- // TODO Auto-generated method stub
- final 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(finalfloat pDensity,finalfloat pElasticity,finalfloat 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,让物理世界按照实际的倾斜来模拟
- @Override
- public void onAccelerationAccuracyChanged(AccelerationData pAccelerationData) {
- // TODO Auto-generated method stub
- }
- @Override
- public void onAccelerationChanged(AccelerationData pAccelerationData) {
- // TODO Auto-generated method stub
- this.mPhysicsWorld.setGravity(new Vector2(pAccelerationData.getX(),pAccelerationData.getY()));
- }
2.实现点击屏幕,就在该处产生一个精灵:
- @Override
- public boolean onSceneTouchEvent(Scene pScene,final TouchEvent pSceneTouchEvent) {
- // TODO Auto-generated method stub
- if(this.mPhysicsWorld !=null){
- if(pSceneTouchEvent.getAction() == TouchEvent.ACTION_DOWN){
- this.runOnUpdateThread(new Runnable(){
- @Override
- public void run() {
- // TODO Auto-generated method stub
- MyPhysics.this.addFace(pSceneTouchEvent.getX(), pSceneTouchEvent.getY());
- }
- });
- }
- return true;
- }
- return false;
- }
3.实现addFace函数
- private void addFace(finalfloat pX,finalfloat 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
- [AndEngine学习教程] 第10节 box2D 物理碰撞系统
- [AndEngine学习教程] 第10节 box2D 物理碰撞系统
- [AndEngine学习教程] 第9节 CollisionDetection 实体碰撞检测
- [AndEngine学习教程] 第9节 CollisionDetection 实体碰撞检测
- Andengine 学习系列5-使用物理系统BOX2D
- (转)Andengine 学习系列5-使用物理系统BOX2D
- (转)[AndEngine学习教程] 第9节 CollisionDetection 实体碰撞检测
- [AndEngine学习教程] 第8节 ParticleSystem 粒子系统
- [AndEngine学习教程] 第8节 ParticleSystem 粒子系统
- [AndEngine学习教程] 第1节 搭建开发环境
- [AndEngine学习教程] 第3节 使用Modifier修改动画
- [AndEngine学习教程] 第4节 制作人物动画
- [AndEngine学习教程] 第6节 模拟手柄控制器
- [AndEngine学习教程] 第1节 搭建开发环境
- [AndEngine学习教程] 第1节 搭建开发环境
- [AndEngine学习教程] 第3节 使用Modifier修改动画
- [AndEngine学习教程] 第4节 制作人物动画
- [AndEngine学习教程] 第6节 模拟手柄控制器
- PHP书写规范 PHP Coding Standard
- Android 分布式编译
- Python中动态导入模块-pybatis的准备阶段(七)
- 励志博文:从1.5k到18k, 一个程序员的5年成长之路
- drawSelectorOnTop的作用
- [AndEngine学习教程] 第10节 box2D 物理碰撞系统
- What is a Class A audio amplifier?
- lamp
- 使用jsp自定义标签库实现数据列表显示模拟cms4j中的标签库效果
- gcc 安装详解
- sgip错误代码
- Flash字体嵌入方法总结—(1)基础篇
- android源码编译
- js重定向---实现页面跳转的几种方式