Cocos2d-x中,实现类似捕鱼达人的炮台

来源:互联网 发布:橡皮章app软件 编辑:程序博客网 时间:2024/05/17 06:41

要实现一个炮台,可以先把子弹放一边,把炮台的事给搞定。

炮台需要做的就是当点击屏幕上某一点时,炮台会旋转,并且指向该点。

把旋转的方法写到onTouchBegan里面即可,代码如下:

bool HelloWorld::onTouchBegan(Touch* touch, Event* event){//获取点击的位置touchPoint = touch->getLocation();//获取大炮的位置Vec2 cannonPoint = cannon->getPosition();//利用反三角函数计算角度,结果是弧度angle = atan((touchPoint.x - cannonPoint.x) / (touchPoint.y - cannonPoint.y));//换算为角度,并且旋转大炮cannon->setRotation(angle * 180 / Pi);return true;}

需要注意的是atan函数的返回值是弧度值,而setRotation需要的参数是角度值,所以在调用时需要进行换算。

炮台可以旋转后,需要在每次点击时发出子弹,并且子弹的角度需要和炮台一致。

这里我是把整个可点击区域分成四块,如图:


因为这样可以比较容易确定子弹的最终位置。例如当点击区域1时,炮弹最终肯定为落在区域1的上边沿,当点击区域2时,炮弹肯定会落在区域2的右边沿。这样在计算最终位置的时候,总是为知道位置的x数值或y数值,然后进行三角函数的简单计算即可确定最终位置。代码如下:

void HelloWorld::addBullet(){Size visibleSize = Director::getInstance()->getVisibleSize();float realAngle = angle * 180 / Pi;SpriteFrameCache* frameCache = SpriteFrameCache::getInstance();frameCache->addSpriteFramesWithFile("bullet.plist", "bullet.png");//创建bullet精灵bullet = Sprite::createWithSpriteFrameName("bullet01.png");//根据炮台旋转角度,设置炮弹的位置Vec2 deltaPosition = Vec2((cannon->getContentSize().height / 2 + 10) * sin(angle), (cannon->getContentSize().height / 2 + 10) * cos(angle));bullet->setPosition(cannon->getPosition().x + deltaPosition.x, cannon->getPosition().y + deltaPosition.y);//根据角度旋转炮弹bullet->setRotation(realAngle);//计算分界角度,该角度即为各区域之间的分界角度float dividingAngle = atan((visibleSize.width / 2) / (visibleSize.height - cannon->getPosition().y)) * 180 / Pi;Vec2 destination;float velocity = 320;float length;float duration;//区域1if (realAngle > 0 && realAngle < dividingAngle){destination = Vec2((visibleSize.height - cannon->getPosition().y)*tan(angle)+visibleSize.width/2, visibleSize.height);length = (visibleSize.height - cannon->getPosition().y) / cos(angle);duration = length / velocity;auto actionMove = MoveTo::create(duration, destination);auto actionDone = CallFuncN::create(CC_CALLBACK_1(HelloWorld::bulletMoveFinished, this));auto sequence = Sequence::create(actionMove, actionDone, nullptr);bullet->runAction(sequence);}//区域2if (realAngle > 0 && realAngle > dividingAngle){destination = Vec2(visibleSize.width, visibleSize.width / 2 / tan(angle) + cannon->getPosition().y);length = (visibleSize.width / 2 / sin(angle));duration = length / velocity;auto actionMove = MoveTo::create(duration, destination);auto actionDone = CallFuncN::create(CC_CALLBACK_1(HelloWorld::bulletMoveFinished, this));auto sequence = Sequence::create(actionMove, actionDone, nullptr);bullet->runAction(sequence);}//区域3if (realAngle < 0 && realAngle > -dividingAngle){destination = Vec2((visibleSize.width/2-(visibleSize.height - cannon->getPosition().y)*tan(-angle)), visibleSize.height);length = (visibleSize.height - cannon->getPosition().y / cos(-angle));duration = length / velocity;auto actionMove = MoveTo::create(duration, destination);auto actionDone = CallFuncN::create(CC_CALLBACK_1(HelloWorld::bulletMoveFinished, this));auto sequence = Sequence::create(actionMove, actionDone, nullptr);bullet->runAction(sequence);}//区域4if (realAngle < 0 && realAngle < -dividingAngle){destination = Vec2(0, visibleSize.width / 2 / tan(-angle) + cannon->getPosition().y);length = (visibleSize.width / 2 / sin(-angle));duration = length / velocity;auto actionMove = MoveTo::create(duration, destination);auto actionDone = CallFuncN::create(CC_CALLBACK_1(HelloWorld::bulletMoveFinished, this));auto sequence = Sequence::create(actionMove, actionDone, nullptr);bullet->runAction(sequence);}addChild(bullet);}void HelloWorld::bulletMoveFinished(Node* pSender){bullet = (Sprite*)pSender;this->removeChild(bullet, true);}
当每个炮弹到达终点时,把炮弹删除。

其中需要注意的是在进行三角函数计算时要用弧度,但是旋转时要用角度。

然后在onTouchBegan中调用addBullet方法,这样一个基本的炮台就完成了,点击任意区域,炮台都会指向该点,并且向该点发射一颗炮弹。


其实我写完了也觉得这方法挺麻烦的,肯定还有更好的方法。等想到了再补充吧。

0 0
原创粉丝点击