文章目录
[]都说程序员都是一群懒人,额(>_<)!!!,确实有那么点吧,我也不例外,为了方便代码的编写,同时为了测试的方便,最关键的以后可以直接创建而不用再为每一个刚体添加索引,并且视图和逻辑实现了比较完美的分离,这节我们要做的就是创建一个debugview,为我们后期制作更加复杂的demo奠定基础(也有点偷偷懒的意思)。<>
一、基本思路和原理基本原理:
1、Box2d的世界采用链表的方式为每一个在当前世界中的物体保存了引用,通过这个链表我们可以访问到每个Body.
2、每一个Body都有一个SetUserData(Object)的方法可以保存一个具有对用户有用的数据类。比如:我们可以为一个矩形保存宽和高,为圆保存半径。
3、我们可以通过每一个Body的mShapeList.m_Type获取这个Body的形状,我们可以使用枚举类ShapeType为m_Type指定形状。
实现思路:
1、从世界中取出第一个Body,由于其是使用链表实现的,所以我们可以通过body获取到下一个Body。我们可以用一个for或一个while来遍历这个链表,可以通过body.m_next获取下一个body。这里需要注意的是需要判断当前body是否为null。
2、通过Body.mShapeList.m_Type获取将要绘制的形状,当然当前我们只有矩形和圆形我们可以只使用PLOYGON_SHAPE、CIRCLE_SHAPE来标志一个矩形和圆。
3、通过getUserData获取到我们保存在Body中的游戏数据,我们可以在这个游戏数据中存储绘制的必要信息,从而确定body在游戏中的相关数据。我们可以把矩形还是圆的信息保存在这个游戏数据类中。
二、DebugView实现1、我们需要为圆和矩形指定数据类CircleBodyInfo、BarBodyInfo
package org.incoding.mini.box2d_android.util; public class CircleBodyInfo { public float radius = 0; } package org.incoding.mini.box2d_android.util; public class BarBodyInfo { public float width = 0; public float height = 0; }2、为创建的物体指定形状以及为该物体保存信息,这个我们在BodyUtil中实现。具体实现可以参看代码,这里不再赘述。
polygondef.type = ShapeType.POLYGON_SHAPE; BarBodyInfo info = new BarBodyInfo(); info.width = bar_width; info.height = bar_height; bar.setUserData(info);3、我们通过遍历所有的物体节点来绘制物体。注意:所有的绘制都是在子线程中的,有线程同步的问题。这里我们在遍历绘制时对世界加了锁。
synchronized (world) { Body body = world.getBodyList(); while (body != null) { drawBodys(canvas, body); if(body.m_next != null) { body = body.m_next; } else { body = null; } } }4、我们根据物体的形状确定确定绘制的是矩形还是圆,然后采用各自的方法绘制。注:当前我们只针对矩形和圆形。
/* 当前我们就绘制矩形和圆,所以我们先只考虑矩形和圆 * */ void drawBodys(Canvas canvas,Body body) { // 绘制矩形 if(body.m_shapeList != null && body.m_shapeList.m_type == ShapeType.POLYGON_SHAPE) { drawBar(canvas, body); } // 绘制圆形 if(body.m_shapeList != null && body.m_shapeList.m_type == ShapeType.CIRCLE_SHAPE) { drawBall(canvas, body); } } /* * 绘制矩形 * */ void drawBar(Canvas canvas, Body bar) { canvas.save(); // 获取物体的宽和高 float width = ((BarBodyInfo)bar.getUserData()).width; float height = ((BarBodyInfo)bar.getUserData()).height; canvas.drawRect(bar.getPosition().x * RATE - width / 2 , bar.getPosition().y * RATE - height / 2, bar.getPosition().x * RATE + width / 2, bar.getPosition().y * RATE + height / 2, groundPaint); // 绘制遮罩 if(bar.isSleeping()) { canvas.drawRect(bar.getPosition().x * RATE - width / 2, bar.getPosition().y * RATE - height / 2, bar.getPosition().x * RATE + width / 2, bar.getPosition().y * RATE + height / 2, diePaint); } canvas.restore(); } /* * 绘制小球 * @param canvas 要绘制的画板 * */ void drawBall(Canvas canvas, Body ball) { canvas.save(); // 获取物体的半径 float radius = ((CircleBodyInfo)ball.getUserData()).radius; canvas.drawCircle(ball.getPosition().x * RATE, ball.getPosition().y * RATE, radius, ballPaint); // 绘制遮罩 if(ball.isSleeping()) { canvas.drawCircle(ball.getPosition().x * RATE, ball.getPosition().y * RATE, radius, diePaint); } canvas.restore(); }5、我们将DebugView设置为抽象类,并在添加一个addBody(World, RATE)方法,该方法的回调放在setupRc()中。这样子View中我们就可以通过该方法来添加刚体。
三、DebugView测试这里给出了DebugView的测试,以后测试就相当的方便了。
package org.incoding.mini.box2d_android.lession03; import org.incoding.mini.box2d_android.util.BodyUtil; import org.jbox2d.dynamics.World; import android.content.Context; import android.view.MotionEvent; public class TestDebugView extends DebugView { World world; float RATE; public TestDebugView(Context context, float width, float height) { super(context, width, height); } @Override void addBody(World world,float RATE) { // 创建地板 float ground_width = width; float ground_height = 10; // 创建地板 BodyUtil.createBar( world, 0, 0.5f, 0f, ground_width, ground_height, 0, 0, height - ground_height, RATE); this.world = world; this.RATE = RATE; } @Override public boolean onTouchEvent(MotionEvent event) { if(event.getAction() == MotionEvent.ACTION_DOWN) { BodyUtil.createBall(world, 7.0f, 0.6f, 0.4f, 5f, 0, (float)(width * Math.random()), 40, RATE); } return super.onTouchEvent(event); } }可能在最新的代码中已经看不到这些代码了,但是最新代码的雏形就是这么的简陋,嘿嘿。 不得不说,程序员真的有点懒...