cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第十步---发射子弹&怪物受伤---全部源代码和资源完结下载
好吧,到这一步,整个游戏基本上弄完啦。因为自己的水平也就这样.....重写的过程中非常多细节处理的不好。
游戏中非常多地方都留下了可扩充的代码。但是时间方面有点不够。
。。并且也没美工
本次笔记内容:
1、思路&代码&效果展示
2、完结代码&资源下载
一:思路&代码
后面的内容基本上是木头书上的内容,没什么太大改动
和之前非常多地方一样。把子弹单独抽离出来,然后绑定在英雄身上,那么英雄就能够带着子弹进行攻击
这样也方便之后的扩展.....毕竟这个游戏非常多地方都是主要的。可是也留给可扩展的设计
那么,首先弄一个子弹的基类,也是为了之后扩展,比方英雄升级之后子弹也变了---可是本游戏没有完毕那么多
#define SPEED_DEFAULT 10 class BulletBase : public Entity{ public: BulletBase();~BulletBase(); //绑定目标 void lockAim(Entity* entity); //获取目标 Entity* getAim(); void setUsed(bool isUsed); bool isUsed(); //子弹是否攻击到敌人 bool isArrive(); protected: //在攻击目标是调用,子类实现 virtual void onLockAim(Entity* aim)=0; bool _isArrive; bool _isUsed; Entity* _aim; CC_SYNTHESIZE(int,_atkValue,AtkValue); //攻击力 CC_SYNTHESIZE(int,_speed,Speed); //速度 };实现
BulletBase::BulletBase(){ _isUsed = false; _aim = NULL; _speed = SPEED_DEFAULT; _atkValue = 1; } BulletBase::~BulletBase(){ CC_SAFE_RELEASE(_aim); } void BulletBase::setUsed(bool isUsed){ _isUsed = isUsed; setVisible(isUsed); } bool BulletBase::isUsed(){ return _isUsed; } void BulletBase::lockAim(Entity* entity){ if(entity != NULL){ CC_SAFE_RETAIN(entity); CC_SAFE_RELEASE(_aim); _aim = entity; onLockAim(_aim); } } Entity* BulletBase::getAim(){ return _aim; } bool BulletBase::isArrive(){ return _isArrive; }那么这里就实现一个正常情况的子弹
class BulletNormal : public BulletBase{ public: BulletNormal(); ~BulletNormal(); CREATE_FUNC(BulletNormal); virtual bool init(); protected: virtual void onLockAim(Entity* entity); private: void moveEnd(); };实现也比較简单
#define SPEED_NORMAL 5 BulletNormal::BulletNormal(){ _speed = SPEED_NORMAL; } BulletNormal::~BulletNormal(){ } bool BulletNormal::init(){ Sprite* sprite = Sprite::create("sprite/bullet/bulletNor.png"); bindSprite(sprite); return true; } void BulletNormal::onLockAim(Entity* aim){ _isArrive = false; //这里是一个动作的移动 auto moveTo = MoveTo::create(0.5f,aim->getPosition()); //动作完毕之后的回调函数 auto callFunc = CallFunc::create(this,callfunc_selector(BulletNormal::moveEnd)); auto action = Sequence::create(moveTo,callFunc,NULL); this->runAction(action); } void BulletNormal::moveEnd(){ _isArrive = true; }那么子弹仅仅是简单的一个精灵。从英雄移动到锁定的目标。那么这里仅仅是一些单独的子弹。我们应该是弄一个子弹管理器,然后绑定在英雄身上
#define BULLET_NUM 10 #define BULLET_TIME 0.07f class BulletManager : public Node{ public: BulletManager(); ~BulletManager(); static BulletManager* create(); bool init(); //virtual void onExit(); //**10**从全部子弹中,娶一个没有在用的 BulletBase* getAnyUnUsedBullet(); private: Vector<BulletBase*> _bulletList; //这里保留parent,是为了把子弹节点cocos的树中。才干被显示出来 void createBullets(Node* parent); //update函数 void bulletLogicCheck(float dt); };子弹管理器也有一个简单的update函数。那么就是让子弹从英雄的位置,移动到怪物
然后打中之后就隐藏,接着打出第二颗子弹
BulletManager::BulletManager(){ } BulletManager::~BulletManager(){ } BulletManager* BulletManager::create(){ BulletManager* bulletMgr = new BulletManager(); if(bulletMgr && bulletMgr->init()){ bulletMgr->autorelease(); } else{ CC_SAFE_DELETE(bulletMgr); } return bulletMgr; } bool BulletManager::init(){ Node* parent = Director::getInstance()->getRunningScene(); createBullets(parent); this->schedule(schedule_selector(BulletManager::bulletLogicCheck),BULLET_TIME); return true; } void BulletManager::createBullets(Node* parent){ for(int i = 0; i < BULLET_NUM; i ++){ BulletBase* bullet = BulletNormal::create(); bullet->setUsed(false); _bulletList.pushBack(bullet); parent->addChild(bullet,10); } } void BulletManager::bulletLogicCheck(float dt){ for(auto bullet : _bulletList){ //正在使用的这个子弹 if(bullet != NULL && bullet->isUsed()){ //get其锁定的目标,后面让其受伤 Entity* aim = bullet->getAim(); if(aim != NULL){ if(bullet->isArrive()){ aim->hurtMe(bullet->getAtkValue()); //打中敌人,就隐藏 bullet->setUsed(false); } } } } } BulletBase* BulletManager::getAnyUnUsedBullet(){ for(auto bullet : _bulletList){ if(bullet != NULL && bullet->isUsed() == false){ bullet->setUsed(true); return bullet; } } return NULL; }那么就给英雄加入一个子弹管理器
//**10** _bulletMgr = BulletManager::create(); this->addChild(_bulletMgr);同一时候,英雄须要发射子弹,而不是 打印 atk 的文字
void Hero::atk(){ CCLOG("Atk!!"); BulletBase* bullet = _bulletMgr->getAnyUnUsedBullet(); if(bullet != NULL){ bullet->setPosition(getPosition()); bullet->setAtkValue(getCurAtk()); bullet->lockAim(_atkMonster); } _isAtkCoolDown = true; //攻击间隔时间后。冷却时间到 this->scheduleOnce(schedule_selector(Hero::atkCollDownEnd),getAtkSpeed()/1000.0f); }英雄在攻击,可是怪物还没受伤,不会死。你也看不到它在受伤.....
于是乎看看修饰怪物受伤的血量条,和子弹绑定在英雄身上一样的设计
class WidgetHPSlot : public Node{ public: WidgetHPSlot(); ~WidgetHPSlot(); static WidgetHPSlot* create(Entity* entity); bool init(Entity* entity); ControlSlider* getSlider(); private: Entity* _entity; //**控件 ControlSlider* _slider; }; ----------------.cpp WidgetHPSlot::WidgetHPSlot(){ _entity = NULL; _slider = NULL; } WidgetHPSlot::~WidgetHPSlot(){ CC_SAFE_RELEASE(_entity); CC_SAFE_RELEASE(_slider); } WidgetHPSlot* WidgetHPSlot::create(Entity* entity){ WidgetHPSlot* hpSlot = new WidgetHPSlot(); if(hpSlot && hpSlot->init(entity)){ hpSlot->autorelease(); } else{ CC_SAFE_DELETE(hpSlot); } return hpSlot; } bool WidgetHPSlot::init(Entity* entity){ CC_SAFE_RETAIN(entity); _entity = entity; _slider = ControlSlider::create( "widget/sliderBg.png", "widget/sliderValue.png", "widget/sliderThumb.png"); _slider->setTouchEnabled(false); this->addChild(_slider); return true; } ControlSlider* WidgetHPSlot::getSlider(){ return _slider; }然后monster加入成员,而且,重写基类的函数。这些函数是分别在 死亡、绑定、受伤的时候附加调用的,给你自己加入扩展其它作用的
void Monster::onDead(){ this->removeAllChildrenWithCleanup(true); } void Monster::onBindSprite(){ if(_hpSlot == NULL){ Point pos = getPosition(); _hpSlot = WidgetHPSlot::create(this); _hpSlot->setPosition(pos.x,pos.y+getSprite()->getContentSize().height/2); _hpSlot->getSlider()->setMaximumValue(getHP()); _hpSlot->getSlider()->setMinimumValue(0); _hpSlot->getSlider()->setValue(getHP()); this->addChild(_hpSlot); } } void Monster::onHurt(int hurtValue){ if(_hpSlot != NULL){ int curValue = _hpSlot->getSlider()->getValue(); curValue -= hurtValue; if(curValue < 0){ curValue = 0; } _hpSlot->getSlider()->setValue(curValue); } }这里要注意把前面的init 函数中的 绑定精灵放到。set属性后面,不然,bingSprite就把onBindSprite函数中的血量
条赋值为1啦。。。。。
。
效果例如以下:
怪物被消灭之后就没啦.....
二:
---------------------------------------
---------------------------------------
好吧,也仅仅能做到这里啦..........什么游戏胜利、失败什么的...都没完好啦。
。。。
勿喷
好吧。个人愚昧观点。欢迎指正与讨论