zoukankan      html  css  js  c++  java
  • 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 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做的一个类似愤怒小鸟的游戏。

  • 相关阅读:
    利用DTrace实时检测MySQl
    改进MySQL Order By Rand()的低效率
    RDS for MySQL查询缓存 (Query Cache) 的设置和使用
    RDS For MySQL 字符集相关说明
    RDS for MySQL 通过 mysqlbinlog 查看 binlog 乱码
    RDS for MySQL Mysqldump 常见问题和处理
    RDS for MySQL Online DDL 使用
    RDS MySQL 表上 Metadata lock 的产生和处理
    RDS for MySQL 如何使用 Percona Toolkit
    北京已成为投融资诈骗重灾区:存好骗子公司黑名单,谨防上当!
  • 原文地址:https://www.cnblogs.com/bunsman/p/2493703.html
Copyright © 2011-2022 走看看