【游客模式】——注册会员,加入11RIA 闪客社区吧!一起见证Flash的再次辉煌……
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
转载:9RIA游戏开发者社区(天地会)
作者:ladeng6666(拉登大叔)
作者博客:http://www.ladeng6666.com/blog/
【Box2D系列教程-导航帖】—拉登大叔出品(总贴)
今天我们来学习Box2D锁链效果。这个效果并不难,记得我们学过的Box2D 关节——”马达关节” b2RevoluteJoint吗?锁链效果其实就是用多个b2RevolueJoint连接多个刚体,很简单吧!
简单在用多个关节连接多个刚体,难也难在这里。我们还是先来看看效果吧。在下面的效果中我创建了两个锁链,一个是小桥,另一个是连接了一个圆形刚体的锁链。鼠标可以点击并拖动下面的刚体。
看过效果之后,我想你肯定也想到了,要用for循环来创建锁链。要用for循环就要有可以重复执行的过程,仔细想想这个过程并不难。
创建当前的刚体body,指定节点的位置anchor,创建节点为anchor的关节,链接当前刚体body和前一个刚体preBody。如下图所示。图中虚线框内是fox循环要重复执行的过程。anchor1用来连接preBody和Body。相信可能有人会跟我一样,犯下面的错误,把关节点设置为body的中心点。这样旋转后,会出现图中下面的效果。因为preBody和body都是围绕anchor1旋转的嘛,想想风扇效果?!
正确的做法是像下图一样,创建当前刚体时body时,让它偏移anchor1一点,偏移多少呢?最好是刚体的一半,这样节点就移到了刚体的边缘处了。旋转之后就会像图中下面的效果一样自然了。
另外设置刚体的宽度为两个节点之间的间距,这样刚体之间会紧密相连,效果就跟上的SWF示例一样了!
完整的代码和注释如下:
[Actionscript3] 纯文本查看 复制代码 package
{
import Box2D.Common.Math.b2Vec2;
import Box2D.Dynamics.b2Body;
import Box2D.Dynamics.b2World;
import Box2D.Dynamics.Joints.b2RevoluteJointDef;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
/**
* ...
* @author ladeng6666
*/
public class Bridge extends Sprite
{
private var world:b2World;
public function Bridge()
{
//初始化,创建世界,添加事件侦听等等
init();
//创建小桥锁链
createBridge();
//创建一个可以拖动的锁链
creaetLinkage();
//随机创建几个刚体
createBodies();
}
private function init():void
{
//初始化世界
world = LDEasyBox2D.createWorld();
addChild(LDEasyBox2D.createDebug(world));
LDEasyBox2D.stage = this;
LDEasyBox2D.createWrapWall(world,this);
//添加事件侦听
addEventListener(Event.ENTER_FRAME, loop);
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseEventHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseEventHandler);
}
//拖动刚体
private function mouseEventHandler(e:MouseEvent):void
{
if (e.type == MouseEvent.MOUSE_DOWN) {
var body:b2Body = LDEasyBox2D.getBodyAtMouse(world);
if (body != null) {
LDEasyBox2D.startDragBody(world, body);
}
}else if (e.type == MouseEvent.MOUSE_UP) {
LDEasyBox2D.stopDragBody(world);
}
}
//更新世界
private function loop(e:Event):void
{
LDEasyBox2D.updateWorld(world);
}
private function createBodies():void
{
//随机创建刚体
for (var i:int = 0; i < 10; i++) {
if (Math.random() > 0.5) {
LDEasyBox2D.createBox(world, Math.random() * 300 + 100, 100, Math.random() * 20 + 10, Math.random() * 20 + 10);
}else {
LDEasyBox2D.createCircle(world, Math.random() * 300 + 100, 100, Math.random() * 10 + 10);
}
}
}
private function creaetLinkage():void
{
//设置第一节刚体开始的位置
var initx:Number = 150;
var inity:Number = 50;
//两个节点之间的间距
var gapBetweenAnchor:Number = 30;
//定义节点
var anchor:b2Vec2=new b2Vec2();
//当前刚体
var body:b2Body;
//前一个刚体
var preBody:b2Body;
//设置前一个刚体是一个圆形刚体,这个刚体不在for循环范围内,
//但是要在for循环里引用,所以在这里预先定义好
preBody = LDEasyBox2D.createCircle(world, initx, inity, 15);
//定义关节
var revoluteJoint:b2RevoluteJointDef = new b2RevoluteJointDef();
for (var i:int = 0; i < 4; i++) {
//循环创建刚体,它们的x坐标都基于节点的位置向右偏移15个像素(也就是刚体的半宽)
body = LDEasyBox2D.createBox(world, initx + i * gapBetweenAnchor+15, inity, gapBetweenAnchor, 5);
//设置节点的坐标
anchor.Set((initx + i * gapBetweenAnchor) / 30, inity / 30);
//初始化关节
revoluteJoint.Initialize( preBody, body, anchor);
world.CreateJoint(revoluteJoint);
//设置preBody引用当前的刚体
preBody = body;
}
}
private function createBridge():void
{
//设置第一节刚体开始的位置
var initx:Number = 100;
var inity:Number = 250;
//两个节点之间的间距
var gapBetweenAnchor:Number = 50;
//定义节点
var anchor:b2Vec2=new b2Vec2();
//当前刚体
var body:b2Body;
//前一个刚体
var preBody:b2Body;
//在for循环之外预先定义第一个刚体,定义成GetGroundBody,固定锁链的起点
preBody = world.GetGroundBody();
//定义关节
var revoluteJoint:b2RevoluteJointDef = new b2RevoluteJointDef();
for (var i:int = 0; i < 6; i++) {
//循环创建刚体,它们的x坐标都基于节点的位置向右偏移15个像素(也就是刚体的半宽)
body = LDEasyBox2D.createBox(world, initx + i * gapBetweenAnchor+25, inity, gapBetweenAnchor, 10);
//设置节点的坐标
anchor.Set((initx + i * gapBetweenAnchor) / 30, inity / 30);
//初始化关节
revoluteJoint.Initialize( preBody, body, anchor);
world.CreateJoint(revoluteJoint);
//设置preBody引用当前的刚体
preBody = body;
}
//设置最后一个节点
anchor.Set((initx + i * 50) / 30, inity / 30);
//将最后一个节点链接到GetGroundBody,固定锁链的终点
revoluteJoint.Initialize( preBody, world.GetGroundBody(), anchor);
world.CreateJoint(revoluteJoint).GetAnchorB().x;
}
}
}
值得注意的是第121行和139行,将关节的起点和终点设置成了GetGroundBody()返回的刚体,用来固定住这两个位置,模拟小桥的效果。关于GetGroundBody()的用法请参考Box2D如何固定动态刚体
下载:
OK 2012-11-25 Box2D锁链效果.rar
(340.73 KB, 下载次数: 0)
|