android游戏引擎andengine学习系列六:Physics物理碰撞效果理解

 

看到exmaples中的例子:CollisionDetectionExample,看到效果图如下:

android游戏引擎andengine学习系列六:Physics物理碰撞效果理解_第1张图片

 

其实这个例子跟我们前面的绘制虚拟游戏摇杆很像,不同的就是中间有两个sprite,判断碰撞的关键语句如下:

scene.registerUpdateHandler(new IUpdateHandler() {	 //场景注册一个UpdateHandler,每次update都运行一次                               	@Override
			public void reset() { }

			@Override
			public void onUpdate(final float pSecondsElapsed) {
				if(centerRectangle.collidesWith(face)) {
					centerRectangle.setColor(1, 0, 0);	//如果两个sprite相碰,则方块sprite变为红色
				} else {
					centerRectangle.setColor(0, 1, 0);   //如果没有相碰,则变为蓝色
				}
			}
		});


另外mCamera.isRectangularShapeVisible(face)判断face是否超出摄像机的视界。

 

 

Physics中的例子都是模仿现实世界中的重力还有碰壁的反弹等物理效果,看下代表性的例子:PhysicsExample

效果如下:

android游戏引擎andengine学习系列六:Physics物理碰撞效果理解_第2张图片

 

实现了IAccelerometerListener重力加速度、IOnSceneTouchListener触屏事件等接口

实现物理效果的步骤如下:

1、创建物理世界

this.mPhysicsWorld = new PhysicsWorld(new Vector2(0, SensorManager.GRAVITY_EARTH), false);

 

2、创建墙壁并加载到scene中

final Shape ground = new Rectangle(0, CAMERA_HEIGHT - 2, CAMERA_WIDTH, 2);
		final Shape roof = new Rectangle(0, 0, CAMERA_WIDTH, 2);
		final Shape left = new Rectangle(0, 0, 2, CAMERA_HEIGHT);
		final Shape right = new Rectangle(CAMERA_WIDTH - 2, 0, 2, CAMERA_HEIGHT);

		final FixtureDef wallFixtureDef = PhysicsFactory.createFixtureDef(0, 0.5f, 0.5f);	//参数分别为密度,弹性,摩擦。
		PhysicsFactory.createBoxBody(this.mPhysicsWorld, ground, BodyType.StaticBody, wallFixtureDef);
		PhysicsFactory.createBoxBody(this.mPhysicsWorld, roof, BodyType.StaticBody, wallFixtureDef);
		PhysicsFactory.createBoxBody(this.mPhysicsWorld, left, BodyType.StaticBody, wallFixtureDef);
		PhysicsFactory.createBoxBody(this.mPhysicsWorld, right, BodyType.StaticBody, wallFixtureDef);

		scene.getBottomLayer().addEntity(ground);
		scene.getBottomLayer().addEntity(roof);
		scene.getBottomLayer().addEntity(left);
		scene.getBottomLayer().addEntity(right);


3、PhysicsWorld实例用scene.registerUpdateHandler注册到场景

scene.registerUpdateHandler(this.mPhysicsWorld);


4、当上面的物理世界创建好了以后,在外部实现IOnSceneTouchListener接口的方法,一触屏便生出一个sprite。

public boolean onSceneTouchEvent(final Scene pScene, final TouchEvent pSceneTouchEvent) {
		if(this.mPhysicsWorld != null) {
			if(pSceneTouchEvent.getAction() == TouchEvent.ACTION_DOWN) {
				this.runOnUpdateThread(new Runnable() {
					@Override
					public void run() {
						PhysicsExample.this.addFace(pSceneTouchEvent.getX(), pSceneTouchEvent.getY());	//备注1
					}
				});
				return true;
			}
		}
		return false;
	}


以上几步完成之后便可以完成整个的物理世界的碰撞效果了。

 

备注1:该例子中有四种不同的sprite碰撞墙壁,关键语句如下:

if(this.mFaceCount % 4 == 0) {
			face = new AnimatedSprite(pX, pY, this.mBoxFaceTextureRegion);
			body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, face, BodyType.DynamicBody, FIXTURE_DEF);
		} else if (this.mFaceCount % 4 == 1) {
			face = new AnimatedSprite(pX, pY, this.mCircleFaceTextureRegion);
			body = PhysicsFactory.createCircleBody(this.mPhysicsWorld, face, BodyType.DynamicBody, FIXTURE_DEF);
		} else if (this.mFaceCount % 4 == 2) {
			face = new AnimatedSprite(pX, pY, this.mTriangleFaceTextureRegion);
			body = PhysicsExample.createTriangleBody(this.mPhysicsWorld, face, BodyType.DynamicBody, FIXTURE_DEF);
		} else {
			face = new AnimatedSprite(pX, pY, this.mHexagonFaceTextureRegion);
			body = PhysicsExample.createHexagonBody(this.mPhysicsWorld, face, BodyType.DynamicBody, FIXTURE_DEF);
		}

		face.animate(200);
		face.setUpdatePhysics(false);

		scene.getTopLayer().addEntity(face);


关于第一种和第二种没什么多说的,和上面创建墙壁的差不多的语法。第三种和第四种创建三角形和六边形的有点复杂,需要计算,看如下原理:
android游戏引擎andengine学习系列六:Physics物理碰撞效果理解_第3张图片先看三角形的精灵的画法,可以先根据三角形sprite得到该sprite的宽和高,当然这里是把他的宽高去一般,为了方便计算,于是可以得到坐标:

      A(0,-H),  B(-W,H),  C(W,H),

这里是根据android的坐标系统来定的。得到了坐标值,于是可以确定Vector2类,关键便是的到这里的vertor2.

再来看看正六边形的原理:

android游戏引擎andengine学习系列六:Physics物理碰撞效果理解_第4张图片同样的我们可以得到W和H,根据数学知识得到BG的长度为:0.5*H,至于具体如何算,可以请教中学的数学老师,于是我们可以得到坐标:

    A(0,-H),  B(W,-0.5H),  C(W,0.5H),  D(0,H),  E(-W,0,.5H),  F(-W,-0.5H);

好了,我们坐标都得到了,可以定义我们的Vertor2的数组:

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)
		};	//这里面的点的顺序是从顶点,然后按顺时针,也就是我们上面的ABCDEF顺序

三角形也是一样的,有了vertices,我们便可以得到物理世界的不一样形状的sprite

return PhysicsFactory.createPolygonBody(pPhysicsWorld, pShape, vertices, pBodyType, pFixtureDef);


具体的创造六边形的方法:

private static Body createHexagonBody(final PhysicsWorld pPhysicsWorld, final Shape pShape, final BodyType pBodyType, final FixtureDef pFixtureDef) {
		/* Remember that the vertices are relative to the center-coordinates of the Shape. */
		final float halfWidth = pShape.getWidthScaled() * 0.5f / PIXEL_TO_METER_RATIO_DEFAULT;
		final float halfHeight = pShape.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)
		};

		return PhysicsFactory.createPolygonBody(pPhysicsWorld, pShape, vertices, pBodyType, pFixtureDef);
	}


这里面有一点开始我怎么也想不通,就是定义坐标的时候,左右为什么要加减2.5,上下为什么要加减8.25,后来看了图片才知道,纹理png图上的图案并没有全部填满整个纹理png图,上下左右都有一些边距,如下:

android游戏引擎andengine学习系列六:Physics物理碰撞效果理解_第5张图片

改图是被我放大的效果,为了方便大家看得更清楚,看到这里便一下子明白了上面那个问题,至于具体的数字为什么是那么多,肯定是跟像素有关系,有兴趣的同学可以找到这个图片,然后把它放大后慢慢的去数,就会明白啦!

你可能感兴趣的:(游戏,android,vector,null,float,引擎)