cocos2dx 3D战斗类游戏制作:【二】——3D运动模式小准备

上章讲了构建一个游戏的数据库基础,基于数据库,我们已经可以实现按照指定的灯光、摄像机位置、3D模型文件、3D模型位置等等构建起一个场景和其中的精灵。

作为一个游戏,让这些场景中的精灵动起来是必须的,然后你就会发现一个有趣的现象——cocos的demo里面(cpp-test),3D精灵展示用的是平面相机(2D)而不是投影相机(3D)。

继而你会发现一个蛋疼的事实——cocos 2D即便到3.3RC0目前最新版本,也没有给你封装一个3D的移动方法。还是2D的moveTo,moveBy那些,呵呵,只有XY轴的运动

想象2D使用moveTo一样,把精灵在XYZ轴都动起来怎么办??

方法有很多,先说一个更改引擎的方法,给自己的引擎加一个MoveBy3D和MoveTo3D的方法。嘿嘿。

首先,打开“盘符:\cocos目录\cocos2d\cocos\2d”下的CCActionInterval.h,添加如下代码:

//dark添加开始***********************************************************************************************************
class CC_DLL MoveBy3D : public ActionInterval
{
public:
 /** creates the action */
 static MoveBy3D* create(float duration, const Vec3& deltaPosition);


 //
 // Overrides
 //
 virtual MoveBy3D* clone() const override;
 virtual MoveBy3D* reverse(void) const  override;
 virtual void startWithTarget(Node *target) override;
 virtual void update(float time) override;


CC_CONSTRUCTOR_ACCESS:
 MoveBy3D() {}
 virtual ~MoveBy3D() {}


 /** initializes the action */
 bool initWithDuration(float duration, const Vec3& deltaPosition);


protected:
 Vec3 _positionDelta;
 Vec3 _startPosition;
 Vec3 _previousPosition;


private:
 CC_DISALLOW_COPY_AND_ASSIGN(MoveBy3D);
};


/** Moves a Node object to the position x,y. x and y are absolute coordinates by modifying it's position attribute.
Several MoveTo3D actions can be concurrently called, and the resulting
movement will be the sum of individual movements.
@since v2.1beta2-custom
*/
class CC_DLL MoveTo3D : public MoveBy3D
{
public:
 /** creates the action */
 static MoveTo3D* create(float duration, const Vec3& position);


 //
 // Overrides
 //
 virtual MoveTo3D* clone() const override;
 virtual void startWithTarget(Node *target) override;


CC_CONSTRUCTOR_ACCESS:
 MoveTo3D() {}
 virtual ~MoveTo3D() {}


 /** initializes the action */
 bool initWithDuration(float duration, const Vec3& position);


protected:
 Vec3 _endPosition;


private:
 CC_DISALLOW_COPY_AND_ASSIGN(MoveTo3D);
};


//dark添加到此***********************************************************************************************************
```



其次,打开“盘符:\cocos目录\cocos2d\cocos\2d”下的CCActionInterval.cpp,添加如下代码:

//dark添加*************************************************************************************
// MoveBy3D
MoveBy3D* MoveBy3D::create(float duration, const Vec3& deltaPosition)
{
 MoveBy3D *ret = new (std::nothrow) MoveBy3D();
 ret->initWithDuration(duration, deltaPosition);
 ret->autorelease();


 return ret;
}


bool MoveBy3D::initWithDuration(float duration, const Vec3& deltaPosition)
{
 if (ActionInterval::initWithDuration(duration))
 {
 _positionDelta = deltaPosition;
 return true;
 }


 return false;
}


MoveBy3D* MoveBy3D::clone() const
{
 // no copy constructor
 auto a = new (std::nothrow) MoveBy3D();
 a->initWithDuration(_duration, _positionDelta);
 a->autorelease();
 return a;
}


void MoveBy3D::startWithTarget(Node *target)
{
 ActionInterval::startWithTarget(target);
 _previousPosition = _startPosition = target->getPosition3D();
}


MoveBy3D* MoveBy3D::reverse() const
{
 return MoveBy3D::create(_duration, Vec3(-_positionDelta.x, -_positionDelta.y, -_positionDelta.z));
}




void MoveBy3D::update(float t)
{
 if (_target)
 {
#if CC_ENABLE_STACKABLE_ACTIONS
 Vec3 currentPos = _target->getPosition3D();
 Vec3 diff = currentPos - _previousPosition;
 _startPosition = _startPosition + diff;
 Vec3 newPos = _startPosition + (_positionDelta * t);
 _target->setPosition3D(newPos);
 _previousPosition = newPos;
#else
 _target->setPosition3D(_startPosition + _positionDelta * t);
#endif // CC_ENABLE_STACKABLE_ACTIONS
 }
}
//
//MoveTo3D
//
MoveTo3D* MoveTo3D::create(float duration, const Vec3& position)
{
 MoveTo3D *ret = new (std::nothrow) MoveTo3D();
 ret->initWithDuration(duration, position);
 ret->autorelease();


 return ret;
}


bool MoveTo3D::initWithDuration(float duration, const Vec3& position)
{
 if (ActionInterval::initWithDuration(duration))
 {
 _endPosition = position;
 return true;
 }


 return false;
}


MoveTo3D* MoveTo3D::clone() const
{
 // no copy constructor
 auto a = new (std::nothrow) MoveTo3D();
 a->initWithDuration(_duration, _endPosition);
 a->autorelease();
 return a;
}


void MoveTo3D::startWithTarget(Node *target)
{
 MoveBy3D::startWithTarget(target);
 _positionDelta = _endPosition - target->getPosition3D();
}
//dark添加到此***********************************************************************************************************
```



好了,搞定。


现在你就可以在程序任意地方,直接象使用MoveTo方法一样,使用MoveTo3D方法。不过注意了,MoveTo是2D的,传入给它的参数是Vec2(x,y),而MoveTo3D,你应该给它传入Vec3(x,y,z)

当然了,把3D的运动方法加在2D目录的CCActionInterval,是有点怪怪的,最好是在cocos的3D目录下建立一个单独的3D方法类来做,不过那样涉及的事情比较多,我就懒得去介绍了,呵呵。


这一章,希望让您能感受到——啊,原来参与到Cocos引擎的开发升级就是这么简单啊:882: 


不知道看完文章,您有没有这个感受,呵呵,只支持2D运动的cocos变可以支持3D运动的cocos定制版,也就是给引擎加一点代码的事情。


说点题外话,呵呵,很多程序员,把学熟一个引擎作为几乎唯一的任务,很注重的是引擎原有封装好的东西可以怎么用。这没错,不过,有时,跳出框框,想想自己能在引擎的级别做点什么,而不是一味地学怎么用,不是更好么?


引擎对于程序员,其实就像鱼、葱、油、盐、姜。非要按菜谱来,没酱油没醋没料酒没糖,前面四道原料几乎没法做菜了。但是,如果只是考虑做一道好吃的菜,而不是一定要按菜谱怎么怎么样,那么鱼、葱、油、盐、姜可蒸可煎可炸,已经可以做若干种口味的鱼了啊。
1赞

蛋疼的事实——cocos 2D即便到3.3RC0目前最新版本,也没有给你封装一个3D的移动方法。还是2D的moveTo,moveBy那些,呵呵,只有XY轴的运动

想象2D使用moveTo一样,把精灵在XYZ轴都动起来怎么办??

MoveBy3D

:14: :14: :14: :14:

FantasyWarrior3D有这东西。

— Begin quote from ____

引用第2楼偶尔e网事于2014-12-01 10:47发表的 回 1楼(lion) 的帖子 :
:14: :14: :14: :14:

FantasyWarrior3D有这东西。 http://www.cocoachina.com/bbs/job.php?action=topost&tid=272524&pid=1186579

— End quote

FantasyWarrior3D是在update里面做的,呵呵,那个下一篇来说