[Cocos2d塔防游戏开发]Cocos2dx-3.X完成塔防游戏《王国保卫战》--地图(二)

news/2025/2/13 20:12:03/

接上文,添加地图,在地图层直接添加即可,我是将AnchorPoint设置在(0,0),方便计算坐标

mapSprite = Sprite::createWithSpriteFrameName(String::createWithFormat("Stage_%d.png",level+1)->getCString());
mapSprite->setAnchorPoint(Point(0,0));
mapSprite->setPosition(Point(0,0));
addChild(mapSprite);

本章节主要介绍两个固定技能和商店技能的实现


首先是两个固定技能,以陨石为例

首先添加按键图片精灵

stoneSprite = Sprite::createWithSpriteFrameName("power_portrait_fireball_0001.png");
stoneSprite->setAnchorPoint(Point(0,0));
stoneSprite->setPosition(Point(10,-20));
stoneSprite->setName("inactive");
//判断倒计时是否完毕
completeStone = false;
addChild(stoneSprite,1);     

然后是倒计时遮盖层,采用的是ProgressTimer实现,放在按键图片精灵上面

stoneTimer = ProgressTimer::create(Sprite::createWithSpriteFrameName("power_loading.png"));
stoneTimer->setAnchorPoint(Point(0,0));
//顺时针转动
stoneTimer->setReverseDirection(true);
stoneTimer->setPosition(Point(10,-20));
stoneTimer->setPercentage(100);//显示原形的百分比
this->addChild(stoneTimer,1);


添加定时器,更新ProgressTimer状态

void PlayerStateMenu::updateStoneProgress(float Dt){  stoneTimer->setPercentage(stoneTimer->getPercentage() - Dt*2);//更新进度2if (stoneTimer->getPercentage()==0) {this->unschedule(schedule_selector(PlayerStateMenu::updateStoneProgress));//取消定时器completeStone = true;}return;
}

在你想要开始的时候schedule它比如第一波敌人出现之后


添加触摸响应

auto stoneListener = EventListenerTouchOneByOne::create();
stoneListener->onTouchBegan = [&](Touch* touch, Event* event){auto target = static_cast<Sprite*>(event->getCurrentTarget());Point locationInNode = target->convertTouchToNodeSpace(touch);Size size = target->getContentSize();Rect rect = Rect(0, 0, size.width, size.height);//若第一次点击点击if(rect.containsPoint(locationInNode)){//若冷却结束if(completeStone == true){//移出其他技能触摸监听mTouchLayer->removeAllListener();if(stoneSprite->getName() == "inactive"){//设置为点击状态stoneSprite->setSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("power_portrait_fireball_0002.png"));//改变状态TAGstoneSprite->setName("active");//改变其他2个按键状态/********///触摸层设置陨石技能监听mTouchLayer->setFireBallTouchShield();//第二次点击,即取消}else{mTouchLayer->removeFireBallTouchShield();stoneSprite->setSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("power_portrait_fireball_0001.png"));stoneSprite->setName("inactive");<span style="white-space:pre">	</span>}
<span style="white-space:pre">		</span>}return true;}return false;  
};
stoneListener->onTouchEnded = [&](Touch* touch, Event* event){
};
//触摸吞噬
stoneListener->setSwallowTouches(true);
_eventDispatcher->addEventListenerWithSceneGraphPriority(stoneListener,stoneSprite);

当倒计时结束的时候,将completeStone置为true,只有此时点击按键才会触发。

点击技能,在触摸层添加一个EventListenerTouchOneByOne,覆盖整个触摸层,此时点击地图时,会执行这个触摸事件

下面来看看触摸层


class TouchLayer :public Layer
{
public:virtual bool init();CREATE_FUNC(TouchLayer);EventListenerTouchOneByOne* touchlistener;EventListenerTouchOneByOne* FiereBalllistener;void setFireBallTouchShield();void removeFireBallTouchShield();bool onFireBallTouchBegan(Touch* touch, Event* event);void onFireBallTouchEnded(Touch* touch, Event* event);bool isFlag;bool onTouchBegan(Touch* touch, Event* event);void onTouchEnded(Touch* touch, Event* event);void onTouchMoved(Touch* touch, Event* event);Size winSize;bool isMoved;void removeAllListener();
};
这里我只截取了和陨石有关以及移动地图的部分


在BaseMap里添加触摸监听层

void BaseMap::initTouchLayer()
{mTouchLayer = TouchLayer::create();mTouchLayer->setContentSize(mapSprite->getContentSize());mTouchLayer->setAnchorPoint(Point(0,0));mTouchLayer->setPosition(Point(0,0));addChild(mTouchLayer,99);
}

添加地图移动时间触摸

touchlistener = EventListenerTouchOneByOne::create();
touchlistener->onTouchBegan = CC_CALLBACK_2(TouchLayer::onTouchBegan, this);
touchlistener->onTouchEnded = CC_CALLBACK_2(TouchLayer::onTouchEnded, this);
touchlistener->onTouchMoved = CC_CALLBACK_2(TouchLayer::onTouchMoved, this);
touchlistener->setSwallowTouches(true);
_eventDispatcher->addEventListenerWithFixedPriority(touchlistener,-1);
_eventDispatcher->addEventListenerWithSceneGraphPriority(touchlistener,this);


这里设置将FiexPriority设置为-1为了确保触摸事件先与技能等其他触摸时间触发

void TouchLayer::onTouchEnded(Touch* touch, Event* event)
{
<span style="white-space:pre">	</span>touchlistener->setSwallowTouches(isMoved);isMoved = false;
}void TouchLayer::onTouchMoved(Touch* touch, Event* event)
{// 计算滑动过程中的滑动增量auto diff = touch->getDelta(); //手指移动修正,因为手指触摸不像鼠标触摸那么固定if(abs(diff.x) >5|| abs(diff.y) >5){isMoved = true;}// 得到当前bgSprite的位置auto currentPos = this->getParent()->getPosition();// 得到滑动后bgSprite应该所在的位置auto pos = currentPos + diff;//边界控制,约束pos的位置pos.x = MIN(pos.x, 0);pos.x = MAX(pos.x, -1200 + winSize.width);pos.y = MIN(pos.y, 0);pos.y = MAX(pos.y, -1000 + winSize.height);// 重设地图层位置this->getParent()->setPosition(pos);
}

当手指在触摸层上移动的时候,isMoved会为true,这是setSwallowTouches(isMoved)会将其他触摸事件吞噬
这样是为了确保移动的时候经过或者移动结束的时候碰巧在某触摸点时,不会触发其他触摸事件(比如说移动完手指正好在某个防御塔上,这样就不会弹出防御塔升级层)
另外当移动的时候也不会触发技能事件监听,可以移动完再选择技能释放地点


void TouchLayer::setFireBallTouchShield()
{//调用此方法创建陨石技能触摸时间FiereBalllistener = EventListenerTouchOneByOne::create();FiereBalllistener->onTouchBegan = CC_CALLBACK_2(TouchLayer::onFireBallTouchBegan, this);FiereBalllistener->onTouchEnded = CC_CALLBACK_2(TouchLayer::onFireBallTouchEnded, this);FiereBalllistener->setSwallowTouches(true);//设置比移动触摸事件高即可_eventDispatcher->addEventListenerWithFixedPriority(FiereBalllistener,1);_eventDispatcher->addEventListenerWithSceneGraphPriority(FiereBalllistener,this);
}void TouchLayer::removeFireBallTouchShield()
{//使用技能完毕去除此监听时间if(FiereBalllistener!=NULL)_eventDispatcher->removeEventListener(FiereBalllistener);
}bool TouchLayer::onFireBallTouchBegan(Touch* touch, Event* event)
{//直接返回TRUE,拦截其他时间return true;
}void TouchLayer::onFireBallTouchEnded(Touch* touch, Event* event)
{//播放音效SoundManager::playFireballUnleash();//创建3个陨石auto fireBall1 = FireBall::create();addChild(fireBall1);fireBall1->shoot(static_cast<TouchLayer*>(event->getCurrentTarget())->convertTouchToNodeSpace(touch)+Point(-30,300));auto fireBall2 = FireBall::create();addChild(fireBall2);fireBall2->shoot(static_cast<TouchLayer*>(event->getCurrentTarget())->convertTouchToNodeSpace(touch)+Point(0,350));auto fireBall3 = FireBall::create();addChild(fireBall3);fireBall3->shoot(static_cast<TouchLayer*>(event->getCurrentTarget())->convertTouchToNodeSpace(touch)+Point(30,280));//陨石坠落之后获取父类的玩家状态层,调用startStone,重新开始计时并且重置ProgressTimer遮盖层static_cast<BaseMap*>(this->getParent())->playerState->startStone();//移除此监听事件removeFireBallTouchShield();
}

我实现整个技能监听加上触摸移动差不多就是这样

商店技能,召唤士兵等其他技能也是同样的思路,只是使用的技能不同罢了~其他的例如冰冻敌人、召唤士兵等将在对应的模块中一一介绍


今天先暂时写到这样,还有苦逼的实习等着我去找







http://www.ppmy.cn/news/624532.html

相关文章

[Cocos2d塔防游戏开发]Cocos2dx-3.X完成塔防游戏《王国保卫战》--子弹类(一)

该章节主要介绍防御塔的子弹 有了防御塔没有子弹类是不能攻击敌人的&#xff0c;所以接着来讨论子弹&#xff0c;新建一个子弹基类Bullet.h class Bullet : public Sprite { public:Bullet();~Bullet();virtual bool init();CREATE_FUNC(Bullet);protected:CC_SYNTHESIZE(int,…

好玩的Java塔防游戏,比较火的塔防手游!塔防游戏排行榜推荐

十年之前&#xff0c;我在同学的诺基亚上玩过一款非常好玩的JAVA塔防手游&#xff0c;具体的名字虽然忘了&#xff0c;但当时连续通宵好几个晚上对其喜爱的热情至今也无法忘记。回到现在&#xff0c;手游也从之前的单机到现在的多人联网&#xff0c;玩法上更是增加了许多&#…

[Cocos2d塔防游戏开发]Cocos2dx-3.X完成塔防游戏《王国保卫战》--其他

最后一章&#xff0c;讲一下其他零碎的地方。 防御塔方面&#xff0c;还有炮塔的两个高级塔&#xff0c;例如地震塔&#xff0c;机器人塔。地震塔就是周围敌人全部减少血量&#xff0c;机器人塔就是一个士兵类&#xff0c;炮塔升级成士兵类&#xff0c;实现方式和士兵类似。 法…

打外星生物的塔防java_塔防游戏有很多,这一款防外星人的游戏,你玩过没

拥有各自风格特色的多种防御塔&#xff0c;游戏包括精美界面设置。玩的时候他音效有种搞怪的感觉。好多种防御塔捍卫萝卜&#xff0c;不同防御塔有不同的威力和功能&#xff0c;可以收集道具&#xff0c;还可以以养外星人达到更多的成果。就我而言&#xff0c;这个游戏就给我带…

04 塔防底板布局 (和儿子一起编游戏-塔防系列 )

4.1 基本概念 从简单的来讲&#xff0c;塔防的底板由供坏蛋行走的路线&#xff0c;供安放炮塔的底座&#xff0c;起始点和终止点组成&#xff0c;成品的效果是这样的&#xff1a; 要做成上面说的底板&#xff0c;就要涉及到Unity3D Prefab&#xff0c;这是一个预制件概念&…

《王国之泪》掉帧严重怎么破?超频Switch教程来了,稳定30帧运行

萧箫 发自 凹非寺量子位 | 公众号 QbitAI 《塞尔达传说王国之泪》简直爆火&#xff0c;相比之下Switch有点“带不动”它了。 这不&#xff0c;就在游戏发售后&#xff0c;不少玩家发现它最大的问题是掉帧严重&#xff0c;尤其是使用“究极手”在海拉鲁搞事时&#xff0c;能直接…

[Cocos2d塔防游戏开发]Cocos2dx-3.X完成塔防游戏《王国保卫战》--游戏开始界面

修改AppDelegate中内容&#xff0c;将setDesignResolutionSize中改为 <span style"font-size:14px;">(960, 640, ResolutionPolicy::FIXED_HEIGHT)</span> 保持传入的设计分辨率高度不变&#xff0c;根据屏幕分辨率修正设计分辨率的宽度 通过&#xff1a…

塔防类游戏关卡分析

转自&#xff1a;http://blog.csdn.net/u014779452/article/details/48471669 隐约还记得最开始接触的塔防游戏是在《魔兽争霸3》里的一个塔防地图&#xff0c;一个田字型的地图&#xff0c;四周一波一波的来怪物&#xff0c;而玩家需要在路边建塔消灭进攻的怪物&#xff0c;阻…