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

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

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

把旋转的方法写到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;

	//区域1
	if (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);
	}

	//区域2
	if (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);
	}

	//区域3
	if (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);
	}

	//区域4
	if (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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值