The Chipmunk SpaceManager(Chipmunk物理引擎管理类)

在学习闲逛中,发现了cocos2d-iphone 官方网站中一篇介绍Chipmunk物理引擎并工具化的教程。在网上搜了下,并无中文翻译,并且Chipmunk物理引擎的相关资料也非常少,于是产生了翻译此篇blog的想法。

原文相关:

The Chipmunk SpaceManager

Published by mobilebros on March 15, 2010 in chipmunk and cocos2d. 20 Comments

Tags: chipmunk, cocos2d, spacemanager, tutorial.

Tweet

 

Cocos2d-iphone and Chipmunk

之前当我 (作者:MobileBros)刚开始使用Cocos2d-iphone, 我也是刚接触Chipmunk; 那个时候Chipmunk也是唯一和Cocos2d相结合的物理引擎, 我也并不清楚应该完成些什么。 很快地我为了用好Chipmunk 引擎而写了许多可重用的代码,并且这些代码都是用C写好的,让我现在已经仔细考虑两种语言(译者:我感觉作者要说的意思应该是两个库)!听起来很熟悉是吗?

 

Chipmunk:

Chipmunk引擎里的概念非常简单。首先有一个chipmunk的 “space”(空间,对应box2d中的wrold), 之后你需要往这个空间中添加shapes/bodies/constraints (形状、刚体、约束), 然后再让空间去管理模拟一段具体范围的时间(的物理效果)。这就完了!最后一步,执行所有的魔法般物理效果的是刚体。

 

Cocos2d Integration – Basic Approach(Cocos2d整合-基本方法):


Cocos2d 能做好很多事情,比如显示sprites(精灵)、 particles(粒子), 响应actions(动作)、touches(触摸), 等等非常多的东西。而Chipmunk非常擅长模拟刚体物理。一般“粘合” (“glueing”) 两个库到一起的方法是关联运行中的chipmunk刚体与Cocos2d节点并告诉Cocos2d去update Cocos2d nodes(更新Cocos2d的节点,设置位置,旋转);非常规范的 模型-视图(model-view)方法。在chipmunk系统中修改约束条件,碰撞行为会产生不同的反应;这是你需要自定义的游戏逻辑。

 

SpaceManager要做的就是去介入粘合(两个系统)并自动化大部分过程。

 

What is SpaceManager?

 

Chipmunk-SpaceManager 项目有两个非常显著的组成部分。有一个(core)核心类“SpaceManager”,和一些与Cocos2d-iphone关联的(helper)帮助类。这些CCNode子类的帮助类用来表现(Chipmunk中的)形状 和 约束。事实上,许多人没有意识到这是互不依赖的两个部分。

 

Core(核心类):

核心类 SpaceManager 的目的是提供一个封装好的我们发现经常(至少)需要用到一遍又一遍的基本功能。这些功能包括:

  • 做出基础的形状 (矩形,圆,多边形)
  • 移动形状 (特别是在碰撞机制下)
  • 推进 chipmunk space的时间
  • 可忽略静态与动态形状不同的API
  • 用我们的 “model(模型)”去更新视图 (Chipmunk –> Cocos2d)
  • 用controller/view(控件/视图)去更新模型 (Cocos2d –> Chipmunk)
  • 与chipmunk系统不冲突 (你可以结合使用spacemanager调用chipmunk原有方法)
  • 创建包含墙的窗口 (听起来又点傻,但是它枯燥乏味)(译者:对不起,感觉没翻译对。不知道要表达什么)

 

我们的目标并不是一丝不动地封装已有的类和功能(实际上slembcke已经发布了用obj-c封装的套件)。相对的,我们想要管理常见的任务/模式。

 

Cocos2d Helpers(帮助类):

 “helper”类的目的是提供一个简单的结合shape/constraint(形状/约束)与CCNode类型匹配的解决方案。这样做,我们可以完成许多其他常见的任务,包括:在node删除后,自动从chipmunk中清除shape/body(形状/刚体);同样,我们也可以在node上通过CCAction的,甚至直接调用setPosition和setRotation控制形状的位置和旋转。

cpShapeNode和cpConstraintNode有点特别,它们会非常正确地绘制对应的shape/constraint.比如你刚用spring constraint(圆形约束)创建了一个cpConstraintNode, 通过添加这个node类型到一个CCLayer或者其他的CCNode, 它将正确地画出一个与spring constraint(圆形约束)相关联的刚体 (使用OpenGL绘制一条zig-zag line(曲线))。

一个称为cpCCNode的基类, 提供任何希望来源于这个基类的子类实现。它提供:

  • shape 属性: 与之关联的形状(译注:cpShape结构体)
  • integrationDt: 如果不为0,任何调用setPosition(不是来自 chipmunk,即改变position) 将引起依此数据计算更新形状的速度(译注:cpFloat数据类型)
  • spaceManager: 一个对拥有本身的spaceManager的引用(译注:SpaceManager类,设置spaceManager管理自动删除对应的shape)
  • autoFreeShape: 清除shape, 需要设置spaceManager属性
  • applyImpulse: 给形状对应的刚体一次冲击(力)
  • applyForce: 给形状对应的刚体一个连续的力
  • • resetForces: 重置任何施加在刚体上的连续力为0

 

Give me an Example!

现在假设你想要把Chipmunk整合到你子类化的一个CCLayer中。这个layer去呈现你的space或者任何添加进去与形状、约束关联的CCNodes.

首先,先让我们创建一个space,然后再添加一个包容它的rect(使这个空间内的shape不会超出屏幕)。

smgr = [[SpaceManager alloc] init]; //SpaceManager* smgr declared in header file

[smgr addWindowContainmentWithFriction:0.8 elasticity:0.7 inset:cpvzero];

 

这段代码看起来并不多,但是chipmunk已经被初始化,使用默认的值和重力创建了一个cpSpace.然后我们添加一个包含窗口(containment rect),有一个具体的回复力/弹力和摩擦系数,一个你想要的具体化的空间。

 

Our First Shape:

很好地完成了第一步,但是接下来让我们添加一个球进去。这个例子让我们使用cpShapeNode(一个“helper”类)来实现,因为它只用OpenGL的最基本的原生方法绘制自己。

cpShape *ball = [smgr addCircleAt:cpv(240,160) mass:5.0 radius:15];
ballNode = [cpShapeNode nodeWithShape:ball]; //cpShapeNode *ballNode declared in header file
ballNode.color = ccBLUE;

ballNode.autoFreeShape = YES;
ballNode.spaceManager = smgr;

[self addChild:ballNode];

我们仅仅只需要SpaceManager去创建一个圆形的shape(形状),然后放置在屏幕的中央(iPhone),设置质量为5,半径为15。它会返回一个指向cpShape类实例的指针,然后我们可以用这个指针去与cpShapeNode关联匹配(颜色设为蓝色,然后添加到我们的CCLayer中)。这里值得注意的是,我们告诉ballNode去自动释放它的shape(当ballNode被released后), 我们的SpaceManager实例也是(会去自动处理释放)。这样你就不用担心之后的内存清除工作了。

 

Crank it up(摇动它):


从现在开始,事情开始变地有趣起来了。尽管现在你已经把代码正确地运行起来了,但是你可能想知道为什么这个蓝色的小球只是停在屏幕的中间。哦,对了!我们需要告诉chipmunk开始模拟我们的space啦。

[smgr start:1.0/60.0];

哇喔!我们成功了,一个蓝色的小球从屏幕的中间开始掉下,并在屏幕的底部上下弹跳几次。好吧,这还不算是很有趣的事。

 

Touches:

也许我们可以让它在触摸方法中做些其他的事。不要忘记把你的layer设置为一个touch delegate…

-(BOOL) ccTouchBegan:(UITouch*)touch withEvent:(UIEvent*)event
{
   CGPoint pt = [self convertTouchToNodeSpace:touch];
   [ballNode applyImpulse:ccpMult(ccpSub(pt, ballNode.position), 3)];
   return YES;
}

这样会通过你的点击的方向给这个小球一个摇动,离球越远晃动越强。现在,如果你只有一个目地,去点击 ⋯⋯你已经创建了一个游戏了!

 

A Game Idea…



价值$1,000,000的游戏创意:一个球和一个目标;瞄准目标,点击发射球 。点击越少使球击中目标,得分越多!

好了。让我们开始设置一个目标,也许一个漂亮的红色方块是不错的选择?

cpShape *target = [smgr addRectAt:cpv(440,160) mass:STATIC_MASS width:20 height:20 rotation:0];
 
targetNode = [cpShapeNode nodeWithShape:target];       //cpShapeNode *targetNode declared in header file
targetNode.color = ccRED;
 
targetNode.autoFreeShape = YES;
targetNode.spaceManager = smgr;
 
[self addChild:targetNode];

这里没有什么特别的变化,除了:STATIC_MASS,这是什么东东? 这个在chipmunk术语中的意思就是质量无限大(STATIC_MASS == INFINITY),前者看起来更确切一点。在chipmunk的世界中有“active”的shapes,也有“static” 的shapes. “static” 的shapes永远不支持移动,在chipmunk世界中看来它们是固定的。还有什么属性比这个更合适我们的矩形目标呢?给SpaceManager传递STATIC_MASS的质量,构建这样一个目标是必须的工作。其他的东西看起来与我们上面创建那个小球一样的。

Collision Callbacks:

我们现在有一个球,一个触摸逻辑,还有一个目标。现在我们需要的是知道什么时候目标被击中了。首先,我们需要去定义一个方法去处理这个。

-(BOOL) handleCollision:(CollisionMoment)moment arbiter:(cpArbiter*)arb space:(cpSpace*)space
{
   if (moment == COLLISION_BEGIN)
   {
      CCLabel *label = [CCLabel labelWithString:@"You Win!" fontName:@"Helvetica" fontSize:32];
      label.position = ccp(240,160);
      label.color = ccBLACK;
      [self addChild:label];
}
 
//other moments: COLLISION_PRESOLVE, COLLISION_POSTSOLVE, COLLISION_SEPARATE
 
return YES;
}

如果你熟悉chipmunk的回调函数,你会注意到这个方法有些类似,但是你现在同时传递了一个CollisionMoment变量。这是一个枚举(enum)类型的参数告诉你处于碰撞的哪个阶段。现在我们只需要关心对象什么时候第一次被触碰。

 

现在不要忘了⋯⋯我们需要注册这个回调函数到我们的SpaceManager实例:

ballNode.shape->collision_type = 1;
targetNode.shape->collision_type = 2;
 
[smgr addCollisionCallbackBetweenType:1
                            otherType:2
                               target:self
                             selector:@selector(handleCollision:arbiter:space:)];

就是这样!如果我们去监测点击了多少此,同时显示到我们的游戏中,那么就大功告成了。如果有对这个例子感兴趣的话,这是完整的源代码:

SpaceManager Example(本博备份:SpaceManager-Example.zip)

当然,SpaceManager能做的事比我们现在讨论的要更多,比如:调度shapes的删除,分割shapes,转变shapes的active和static属性,持续探测碰撞,等等。这个在这里找到这个项目的网页:

http://code.google.com/p/chipmunk-spacemanager/

还有更深入的例子和源代码。

 

翻译完:接下来我会翻译一个用SpaceManager做的一个类似愤怒小鸟的游戏。

posted @ 2012-05-10 09:17  馒不头  阅读(831)  评论(0编辑  收藏  举报