cocos2dx3.2开发 RPG《Flighting》(九)必不可少的子弹
一、前言 上一节我们讲完了攻击,其实也只是攻击者一方一厢情愿地播放自己的攻击动画罢了,被攻击的那一方根本不知道发生了什么,攻击者和被攻击者还没有联系起来。 所以,我们就引入了子弹这个东东。
二、正文 一开始我在开发的时候想到用物理引擎,后来想了想还是算了,一是难控制,二是可能会遇到一些问题(例如两个人之间可能会发生碰撞。。) 所以还是将错就错,直接用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 邮箱地址:578690286@qq.com 如有问题或指教,欢迎与我交流,谢谢。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |