不会开机的男孩

Box2d 04 多边形刚体和鼠标连接器

| Comments

我们在真正做一些物体的时候,有一些情况不是标准的圆形,矩形。这时我们需要创建多边形的刚体。这里推荐一个工具VertexHelper来帮我们生成刚体的定义。

今天的东西似乎有一点太少了,再瞅瞅另一种连接器,b2MouseJoint——鼠标连接器。 在使用鼠标连接器之前,我们需要找到我们选择的是那一个物体。

  • 获取手势的位置,也就是坐标向量
  • 创建一个小的物体,小到只是一个点,然后通过这个物体在物理世界中查找包含这个物体的刚体

鼠标连接器的使用步骤 当检测到碰撞时,创建连接器

b2MouseJointDef mouseJointDef;
mouseJointDef.bodyA = groundBody; //通常连接地面
mouseJointDef.bodyB = body;       //需要移动的刚体
mouseJointDef.target = locationWorld; //当前位置
mouseJointDef.maxForce = 1000 * body->GetMass(); //移动的最大力,这个决定移动的灵敏度
//mouseJointDef.collideConnected = true; //这个场景不需要

self.mouseJoint = (b2MouseJoint *) world->CreateJoint(&mouseJointDef);
//body->SetAwake(true);         //很多地方指定了这个,但是我实际测试,这个场景也不需要

在手势移动的时候重新设置

world->DestroyJoint(self.mouseJoint);
self.mouseJoint = NULL;

在手势取消和结束时销毁

world->DestroyJoint(_mouseJoint);

demo

Box2d 03 b2Joint 连接器

| Comments

在真实世界中,一个物体很难孤立的存在,比如一个我们的自行车,2个轮子除了可以自由滚动以外,还必须保证2个轮子之间的距离不变,而保证这个距离不变的就是自行车的大梁。我们的胳膊,需要保证在一定范围的情况下围绕一个点旋转等等。Box2D中 连接器就是用来保证刚体和刚体之间的某种关系而出现的。

我们先认识b2DistanceJoint——距离连接器。

image

这是一个自行车的模型bodyA bodyB 就是之前熟悉的圆形刚体,中间的红线是我们的距离连接,anchorA,anchorB 则是连接器连接2个刚体的位置。非常的直观。

b2DistanceJointDef jointDef;
jointDef.Initialize(ballA, ballB, ballA->GetPosition(), ballB->GetPosition());

b2DistanceJoint *join = (b2DistanceJoint *)world->CreateJoint(&jointDef);
CGFloat distance = 30.0 / PTM_RATIO;
join->SetLength(distance);

非常的直观,制定连接的位置和距离,就创建完毕了。下面是一个demo,每当触摸屏幕的时候给自行车一个向右的冲量。

demo代码

Box2D 02 刚体

| Comments

刚体的属性有3种。

  • staticBody
  • kinematicBody
  • dynamicBody

    staticzero mass, zero velocity, may be manually moved

    kinematic: zero mass, non-zero velocity set by user, moved by solver

    dynamic: positive mass, non-zero velocity determined by forces, moved by solver

简单说就是static 的刚体没有质量,没有速度。 kinematic 的刚体没有质量,但是可以设置速度。 dynamic 的刚体就是之前我们写的小球。有质量有速度。

static 的常常用于游戏中的墙,这种不会移动的,而且不会受到力的作用改变他的位置,速度等。 kinematic 的常常用于游戏中的跳板这些,他们会移动,但是同样不会受到力的作用改变原来的运动轨迹。 dynamic 通常是我们的玩家,敌人。他们会移动,而且会受到力的作用,旋转,碰撞,加速等。

刚写好了几个demo,用来做这几种类型的区分,

demo代码

Box2D 01 基本概念

| Comments

首先几个概念需要了解一下。

world 就是engin需要模拟的世界,他有一个大家都很熟悉的重力

body(刚体) 刚体的定义大家在物理中都熟悉了,在box2D世界中,刚体定义了物体一些重要的属性,比如质点位置,旋转角度,角速度,线性阻尼,等

shape(形状)这里定义我们的物体的形状是圆的,方的还是多边形等

fixture(材质?这个好难翻译中文)光是上面的东西,我们不能够完成物理世界的碰撞,fixture定义了几个重要的属性,包括摩擦系数,恢复系数,密度

回想当初学习的物理知识也就这么多了,当然后面还会介绍其他新的东西。有个形状,和密度我们可以计算质量,有了位置,速度,角速度,足够我们计算高中学到的简单碰撞了,在有恢复系数和线性阻尼,我们也能更好的模拟更真实的物理情景,而这也是大学物理的部分了。

好多的背景知识,让我们再看看如何在程序里面做一个真实的世界出来。

b2Vec2 gravity;
gravity.Set(0.0f, -10.0f);
world = new b2World(gravity);

box2D的坐标是和笛卡尔坐标系一样的,向量 (0, -10) 表示我们真实世界的重力,大约为10米每秒

创建我们的第一个物体,一个圆球。 这里Box2D采用了工厂模式来创建一个我们需要的物体。我们首先描述一个需求,然后通过一个工厂来生产我们需要的产品。

b2BodyDef bodyDef;//
bodyDef.type = b2_dynamicBody; //这里定义为动态刚体
bodyDef.position.Set(pt.x/PTM_RATIO, pt.y/PTM_RATIO);
body = world->CreateBody(&bodyDef);

b2CircleShape bodyShape;
bodyShape.m_radius = 26.0 / PTM_RATIO; //定义球的半径

b2FixtureDef fixtureDef;
fixtureDef.shape = &bodyShape;
fixtureDef.density = 0.1f;  //密度
fixtureDef.friction = 0.1f; //摩擦力
fixtureDef.restitution = 0.9f; //恢复系数
body->CreateFixture(&fixtureDef);

还急得之前的概念么?在定义好body,shape,创建好fixture之后。这些信息已经足够模拟真实运动了。因为是真实的世界,独立各个平台,box2D的单位是米,而不是程序图形图像的单位像素,PTM_RATIO这个宏用于转换单位。

当然,这些物理数据还不能让我们在程序中看到,为了美观,增加一点小东西,希望大家了解cocos2d。这里创建一个CCPhysicsSprite

CCPhysicsSprite *sprite = [CCPhysicsSprite spriteWithFile:@"ball.png"];
[self addChild:sprite];

[sprite setPTMRatio:PTM_RATIO];
[sprite setB2Body:body];

//CCPhysicsSprite 的操作一定要在设置PTMRatio 和 body之后
[sprite setPosition: ccp(pt.x, pt.y)];

这时我们就可以看到一个小球自由落体,然后淡出世界,不过似乎有一种淡淡的忧伤,太无趣了这个世界。

让我们为这个世界创建一个边界,让小球不要运动超过屏幕。

// Define the ground body.
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0, 0); // bottom-left corner

// Call the body factory which allocates memory for the ground body
// from a pool and creates the ground box shape (also from a pool).
// The body is also added to the world.
b2Body* groundBody = world->CreateBody(&groundBodyDef);

// Define the ground box shape.
b2EdgeShape groundBox;      

// bottom

groundBox.Set(b2Vec2(0,0), b2Vec2(s.width/PTM_RATIO,0));
groundBody->CreateFixture(&groundBox,0);

// top
groundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO));
groundBody->CreateFixture(&groundBox,0);

// left
groundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(0,0));
groundBody->CreateFixture(&groundBox,0);

// right
groundBox.Set(b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,0));
groundBody->CreateFixture(&groundBox,0);

这里没有指定其他属性,默认创建的刚体是静态的,不会移动的。而这正是我们想要的。

这时小球会自由落体然后反弹,这时可以调整restitution,如果对这些不是很熟悉的话。但是总体感觉还是有一点无聊,让我们再来一点新东西。

b2Vec2 force = b2Vec2(-30, 30);
body->ApplyLinearImpulse(force, body->GetPosition());

body是我们其中的一个小球。ApplyLinearImpulse的意思就是对body施加一个冲量。

demo地址

运动小结

| Comments

有很多人觉得我能用1年的时间减肥30斤,并保持下来很牛,也许是有一点点的不容易吧。我这里纪录一下自己的心得。

动力

改变很难,减肥的确是一件非常难的事情,需要极大的意志力和时间的投入。我最开始的动力,可能说出来挺丢人,是因为自己喜欢的一个女孩,表白失败。然后顿时觉得浑身充满负能量没有地方发泄。再加上那会工作压力不大。然后便开始减肥。办了1年的会员,我告诉所有人,我要把肚子上的赘肉练下去,把胳膊上的肌肉练出来。几乎所有人都告诉我,这是不可能的,可能我脾气倔吧,我就越要把这件事情做好。

第一个月减了20斤

开始的第一个月是大家最容易坚持下来的,那会浑身都是负能量,我每天游泳1.5到2km,周末会游的远一点。运动了整整一个月,减了20斤。这个对于当时170斤的我来说,这个运动量已经是身体负荷的极限了,要知道铁人三项其中的游泳项目也就是1.5km。这会计算都有一点害怕,那会我一周累计起来要游泳1W米。。。

另外时间上的成本也很高,那会体力不好,基本上要游泳1个半小时多,加上洗澡的时间和收拾东西的时间,即便游泳池就在楼下这么近的位置,每天都需要花费至少2个小时。所以,可见我当时是有多么的闲。: (

接下来的10个月

我的经验是当运动到1个月的时候,是身体最疲劳的时候,懒惰情绪抬头,同时身体的疲劳积累越来越多,1个月就是这样的一个拐点。

1个月后,我不得不调整我的计划,我没有办法再坚持每天游泳的运动量了,我减少了1半,一个星期保证至少去3次,一般4次,每次1.5km,1个小时。体重没有变化,一直在保持,这里有一点很重要,中间因为一些假期休息导致反弹了至少3次,每次至少5斤。

有一些有趣的事情,比如情人节那天,大家都出去约妹子了,孤单的我一个人去游了3km,回来整个人就瘦了7斤。当时自己觉得那些运动节目弱爆了,一个星期减个7斤还要好意思觉得效果不错。当然,副作用非常明显,第二天我就起不了床,连续2天都没有去游泳。: D

在我运动了大概6-7个月的时候,我开始做腹部的训练。之前也曾经做过很多,但都没有能够坚持下来,而这次我准备来真的。一开始我只能做30个,用了一个月的时间到每天180个。和我之前说的一样,1个月是一个门槛,

然后又发生了一件事情,可以说是我人生的又一个拐点吧,和一个女孩分手,大量的负能量转换为了健身的动力,又坚持了4个月,而且加大游泳的运动量,于是我又减了5斤。

最近5个月

慢慢快1年了,我减了25斤,并保持了下来。这让我的精神状态得到了超级大的改观,我开始意识到运动给我带来的好处不仅仅是排解负能量。由于投入了大量的时间并形成习惯之后,我觉得我需要做一点变化,来提高我的健身效率。然后我找了健身教练来帮助我制定运动计划。

这个可以说是一个魔鬼计划吧,我先锻炼的是腹部,从一些比较入门的动作,当然这些动作已经比我之前做的动作要难好多了,而且数量也增加,每次做的动作都在200个以上,一周至少3次。一般4次。一个月后,达到了520个。然后随着每次运动量增加,我减少到了每周3次,其中1周2次私教课,我自己练一次,间隔游泳1.5km。也就是每天至少花1个小时健身。

1个月后果然是最难熬的腹部下去了一大块,腰围小了1寸,其实好多时候我都想把运动量减少到一周2次腹肌,其他时间游泳,因为练腹肌实在是太苦逼了,撕裂的疼。

我其实挺不好意思的,因为在我快要坚持不下去的时候,又遇到一个妹子,可能是我还没有从之前的那个人走出来,对妹子挺冷淡的,当我准备进入状态的时候,妹子觉得不合适走了。然后我就又获得了不少负能量,然后又坚持了一个月,每周3-4次,一次520个腹部动作。

然后还是吃素,尽量不吃肉,我需要改善我的体质,否则我坚持不下来这么大的运动量。 这2个月,我又减了5斤。非常不容易的5斤。非常开心,这时候所有人见到我都不得不相信我做到了1年前我说的,我要把肚子上的肉移动到胳膊上面。而且我的确是瘦了好多。

然后我开始纪录我的健身时间和计划。到现在正好3个月。上个月我开始更科学的健身,腹部训练我降到了一周2次,每次300个动作(我更换了新的动作,这300个比之前的520个难多了)。增加了胳膊,肩膀,腿部,背部,肩膀的训练。每天基本上身体挨个部位轮流练,坚持不下去了就去游个1.5km。最近开始做yoga。

这3个月,每个月都锻炼25天以上,每次不少于45分钟,

健身的误区有很多,比如很多妹子都不敢练器械,因为害怕练出肌肉,作为一个坚持做腹肌5个月的家伙来看,练出肌肉绝对没有想象的那么容易,抛开休息,饮食不说,只说运动量,我之前500多个的时候只是热身,如果想要有6块,运动量至少得增加1倍每天差不多1000个,当然,最好换动作,要不太浪费时间。

回头看,我能坚持下来,“妹子”的原因虽然上不了台面,但是的确是真真正正的导火索,感谢她们,让我养成了这样一个好习惯。

写到这里,我又看了一边我的运动时间表。很有意思的,有一周,我几乎从早上忙到晚上12点,每天大概15个小时工作,而我那周,居然健身375分钟.所以忙,只是借口而已。

希望我可以再坚持1年。