一、前言
上一节我们讲完了攻击,其实也只是攻击者一方一厢情愿地播放自己的攻击动画罢了,被攻击的那一方根本不知道发生了什么,攻击者和被攻击者还没有联系起来。
所以,我们就引入了子弹这个东东。
二、正文
一开始我在开发的时候想到用物理引擎,后来想了想还是算了,一是难控制,二是可能会遇到一些问题(例如两个人之间可能会发生碰撞。。)
所以还是将错就错,直接用update函数解决问题吧。
子弹,顾名思义,就是子弹啊。
class Role; class Bullet : public Node{ public: static Bullet* createWithTarget(Role* sender,Role** target); bool initWithTarget(Role* sender,Role** target); void setDamage(int damage); ~Bullet(); private: Sprite* m_bullet; Role* m_target; Role** m_targetPtr; virtual void update(float dt); int m_damage; int m_speed; Role* m_sender; };
从头文件里面就可以知道,子弹的实现很简单。
主要还是看create和update函数
Bullet* Bullet::createWithTarget(Role* sender,Role** targetPtr){ Bullet* ret = new Bullet(); if(ret && ret->initWithTarget(sender,targetPtr)){ ret->autorelease(); return ret; } CC_SAFE_DELETE(ret); return nullptr; } bool Bullet::initWithTarget(Role* sender,Role** targetPtr){ m_damage = 0; m_bullet = Sprite::create("Bullet/" + sender->getBulletImg()); setDamage(sender->getAtk()); setPosition(sender->getPosition() + Point(0,sender->getContentSize().height/2)); this->addChild(m_bullet); m_speed = sender->getBulletSpeed(); m_targetPtr = targetPtr; m_sender = sender; this->scheduleUpdate(); return true; }
create函数就是这样,注意的是子弹的图片是根据每个不同的角色而定的。(近战角色没有子弹,我们可以把素材用一张透明的小块代替)
其实Role类里面还有很多属性的。这里大家通过命名应该知道怎么一回事。
create函数设置好子弹的攻击者和被攻击者之后。update负责处理
void Bullet::update(float dt){ m_target = *m_targetPtr; if(!m_target){ this->removeFromParentAndCleanup(true); return; } if(!m_target->getBoundingBox().containsPoint(this->getPosition())){ float distance = ccpDistance(getPosition(),m_target->getPosition()+Vec2(0,m_target->getContentSize().height)); float t = distance / m_speed; float speed_x = (m_target->getPositionX() - getPositionX()) / t; float speed_y = (m_target->getPositionY()+ m_target->getContentSize().height/2 - getPositionY()) / t; setPositionX(getPositionX() + speed_x); setPositionY(getPositionY() + speed_y); }else{ CCLOG("BULLET->ARR"); m_target->injured(m_effect,m_damage); this->removeFromParentAndCleanup(true); } }
如果目标死了,就清楚子弹
如果子弹没有达到目标的区域,就一直更新xy,跟Role的是差不多的
如果到达了,触发目标的injured函数,并且清除自己(子弹)
好了,介绍完子弹,我们看一下一个角色怎么发送子弹
还记得Role类的onBondAnimationFinish函数是干嘛用的吧?不清楚的可以看上一节。
void Role::onBondAnimationFinish(Armature* arm,MovementEventType type,const std::string& name){ if(type == COMPLETE){ if(name == "attack"){ CCLOG("ATTACK COMPLETE"); //恢复速度 m_speed = m_initSpeed; m_arm->getAnimation()->setSpeedScale(1.0f); this->stand(); } } if(type == START){ if(name == "attack"){ CCLOG("SEND BULLET"); sendBullet(); } } }
这里我们只是在攻击动画播放前,调用sendBullet函数
void Role::sendBullet(){ if(m_attackTarget && m_layer){ m_layer->addBullet(this,m_attackTargetPtr); } }
而sendBullet函数也只是让m_layer(其实就是FlightLayer)调用addBullet函数
void FlightLayer::addBullet(Role* sender,Role_Ptr targetPtr){ Bullet* bullet = Bullet::createWithTarget(sender,targetPtr); this->addChild(bullet); }
好了,这里我们能够自动移动到目标的子弹已经做出来了。
剩下的就是被击打的那一方,的injured函数了,在injured函数里面我们可以添加受伤效果(上一节没讲的),还有进行血量值的计算。这些都很自由。这里给出我的injured函数供大家参考
void Role::injured(int effect,int damage){ runSkillEffect(effect); if(damage < 0){ m_hp -= damage; }else{ int real_damage = (damage-m_defence > 0)?damage - m_defence : 1; m_hp-= real_damage; } if(m_hp > m_initHp){ m_hp = m_initHp; } if(m_hp <= 0){ die(); return; } if(en_stat == ROLE_MOVE){ return; } MoveBy* toR = MoveBy::create(0.2f,Vec2(10,0)); MoveBy* toL = MoveBy::create(0.2f,Vec2(-10,0)); Sequence* seq; if(m_armFaceTo){ seq = Sequence::create(toR,toL,NULL); }else{ seq = Sequence::create(toL,toR,NULL); } m_arm->runAction(seq); }
effect这个参数是播放特效的,可以忽略。
本节到此结束。
我的csdn地址:http://blog.csdn.net/hezijian22
邮箱地址:[email protected]
如有问题或指教,欢迎与我交流,谢谢。