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

邮箱地址:[email protected]

如有问题或指教,欢迎与我交流,谢谢。

时间: 2024-10-19 13:02:03

cocos2dx3.2开发 RPG《Flighting》(九)必不可少的子弹的相关文章

cocos2dx3.2开发 RPG《Flighting》(十五)最后的总结说明,以及源码分享

一.前言 这次的Flighting系列教程一口气写了2天,到这里就要结束了.接下来我说明补充一下一些前面没有提到,但是我觉得有必要讲一下的. 二.正文 1.怪物的出场 前面已经说了一个个的XXXMessageUtil,其实StateMessageUtil是比较特别的.首先我们先看看StateMessage的Excel表(关卡) 前面的字段大家可以参透参透,我主要讲一讲monster字段 monster字段表示这个关卡的怪物对队列,用"|"隔开 class StageMessage{ p

cocos2dx3.2开发 RPG《Flighting》(一)基本介绍

前言: 上次写了一个消灭星星,很多人都回复了我,并且提出了宝贵的意见,先感谢大家啦~上几个月我发现了一个很好玩的游戏--<BattleHeart>,心里面想着,这么好的游戏要是可以联机跟好朋友一起玩(就像CS那样)那就爽歪歪了,于是就动手开始模仿这款游戏,并且为其加入网络模块.可惜,因为对多人网络游戏开发并不熟悉,虽然最后还是开发出来了,但是效果却差强人意.不过在开发过程中学到了很多新的知识和网络游戏用到的技术(例如boost::asio搭建服务器,网络游戏同步等),也算是一个不错的经历了.

cocos2dx3.2开发 RPG《Flighting》(三)从Excel表中加载需要的数据

一.前言 在一个游戏里面,需要用到的数据一般都是由游戏策划提供的(这里的策划还是由我自己担任啦哈哈).什么是需要用到的数据?例如我创建一个角色A,A有他自己的攻击力,防御力,速度等,再创建一个角色B,B也有自己的攻击力,防御力,速度等.每个角色都有一些基础属性,但是对应不同的角色,属性的值有可能不同.我们不可能在代码里面把这些数据写死.最好的办法是从一个文件(通常是Excel表格)中读入数据,这样就方便管理和修改. 二.正文 1.Excel <Flighting>游戏里面用到了4个Excel表

cocos2dx3.2开发 RPG《Flighting》(十)为角色加上血量条

一.前言 先说明一下,Role类其实是有很多属性的 protected: /*与战斗相关的数据*/ int m_id; //id Role* m_attackTarget; Role** m_attackTargetPtr;//攻击目标 Point m_desPoint;//目标位置 ROLE_STAT en_stat; //当前状态 FlightLayer* m_layer; //父控件 int m_speed; //移动速度 int m_initSpeed; int m_attackDist

cocos2dx3.2开发 RPG《Flighting》(七)回到战斗场景,更新角色的叠放次序

一.前言 至此,我们的战斗场景关于角色移动已经讲得七七八八了.不过还是有一些问题需要注意注意. 二.正文 在第五节里面我们讲了FlightLayer里面有一个很重要的容器m_rolesArray,并且说道其初始化是由以下两个函数负责的. void FlightLayer::initTeam(const HeroMessage& h1,const HeroMessage& h2,const HeroMessage& h3){ Hero* hero1 = Hero::create(h1

cocos2dx3.2开发 RPG《Flighting》(八)开始战斗

一.前言 前面我们已经基本学会了怎么让角色走起路来而且也做了很多的优化.下面是时候开始战斗了.不过还是不要急,我们先暂时不引入英雄和怪物这两个类(毕竟只要是Role就可以打架,哪怕是英雄打英雄) 二.正文 先大致说一下整个思路: 1.选择角色并且可以拉出一条导航线出来(之前已经做了) 2.判断导航线的终点,如果终点刚好是在一个Role的身上,那么..嘻嘻就打他了. 3.角色移动到目标身边 4.角色播放攻击动画 5.被打的人播放被打的动画 1.2两步之前已经基本做了,这里只需要做一点点修改. vo

QT开发(十九)——QT内存泄漏问题

QT开发(十九)--QT内存泄漏问题 一.QT对象间的父子关系 QT最基础和核心的类是:QObject,QObject内部有一个list,会保存children,还有一个指针保存parent,当自己析构时,会自己从parent列表中删除并且析构所有的children. QT对象之间可以存在父子关系,每一个对象都可以保存它所有子对象的指针,每一个对象都有一个指向其父对象的指针. 当指定QT对象的父对象时,父对象会在子对象链表中加入该对象的指针,该对象会保存指向其父对象的指针. 当QT对象被销毁时,

微信公众平台开发教程(九)微信公众平台通用开发框架

微信公众平台开发教程(九)微信公众平台通用开发框架 一.思考 开发了几个微信项目,一直在思考:如何将微信相关的处理与业务系统联系在一起?如何做到彼此分离,且易于扩展?能否开发一套独立的微信服务框架,支持各种业务应用? 二.现有常用的服务框架 支持多种业务应用,我们通过分层的方式来实现.将复杂的系统进行分层,将一些功能或者特有的逻辑进行封装,封装为不同的基础服务或中间件.业务层无需关心底层具体实现,只需进行简单调用.组装,即可支撑强大的业务应用.这样保证了层级独立,也使得系统易于维护和扩展.在一个

Senparc.Weixin.MP SDK 微信公众平台开发教程(九):自定义菜单接口说明

上一篇<Senparc.Weixin.MP SDK 微信公众平台开发教程(八):通用接口说明>介绍了如何通过通用接口获取AccessToken,有了AccessToken,我们就可以来操作自定义菜单,以及其他的高级接口,这一篇单讲自定义菜单. 一.自定义菜单规则 自定义菜单分为一级菜单和二级菜单. 一级菜单数量为1-3个,即打开公众账号直接可以看到排列在最下方的最多3个按钮.一级菜单的文字最多不能超过16字节(相当于8个汉字). 二级菜单从属于一级菜单,数量为1-5个.二级菜单的文字不最多不能