奖励小功能

首先当敌人被击毁时根据随机数判断是否出现一个奖励。以下代码简单,就不做多解释

void Enemy::doHurt() {
	float percentage = this->_hp / this->_sourceHp;
	if(Config::sharedConfig()->getIsOpenSlot()) {
		this->_topSlot->setScaleY(percentage);
	}
	if(this->_hp <= 0) {
		...
<span style="white-space:pre">		</span>
		float appearRate = CCRANDOM_0_1();
		Award* award = NULL;
		if(appearRate < 0.2f) {
			if(GameLayer::shareGameLayer()->getIsAppearShader() == false && this->_id != 3 && 
				Config::sharedConfig()->getIsTsuihikidanMode() == false) {
					GameLayer::shareGameLayer()->setIsAppearShader(true);
					award = Award::getOrCreate(SHADER);
			}
		}else {
			appearRate = CCRANDOM_0_1();
			if(0.2f > appearRate && appearRate < 0.45f) {
				if(GameLayer::shareGameLayer()->getIsAppearShield() == false && this->_id != 3) {
					GameLayer::shareGameLayer()->setIsAppearShield(true);
					award = Award::getOrCreate(PROTECTED_BODY);
				}
			} 
		}
		if(award && award != NULL) {
			award->setVisible(true);
			award->setPosition(this->getPosition());
			award->startAction();
			award->scheduleUpdate();
		}

	}
}
奖励现在只做了三个,分别是:护盾、增加恢复值、敌人血量减半。用三个枚举值记录:

typedef enum {
	PROTECTED_BODY,
	ADD_RESUME_VALUE,
	SHADER
}AWARD_TYPE;
最终出现的奖励效果是由三个精灵组成:


其中,小光圈绕着圆形的环做圆周运动,中间的主体精灵做翻转动作,当碰到屏幕的任何一边后会根据其碰撞的角度做90度的反弹,当碰到主角后触发奖励功能。定义完了显示效果后便是实现它。

class Award : public CCNode
{
public:
	Award();//构造
	bool init();//初始化
	virtual void execute() = 0;//奖励的实现功能
	void startAction();//开始动作
	void doAction();//执行动作
	void endAction();//结束动作
	CCRect collideRect();//碰撞判断矩形
	static void preSet();//重置
	static Award* getOrCreate(AWARD_TYPE awardType);//根据不同的奖励类别获取或创建不同的奖励
	CC_SYNTHESIZE_READONLY(AWARD_TYPE, _awardType, AwardType);//奖励类别
	
	CC_SYNTHESIZE_READONLY(float, _speed, Speed);//速度
	CC_SYNTHESIZE(int, _direction, Direction);//方向
	CC_SYNTHESIZE(bool, _active, Active);//激活


	void update(float dt);//更新
protected:
	CCSprite* _circle;//圆环
	CCSprite* _body;//奖励主体
	CCSprite* _halo;//小光圈
private:
	bool _leftCollision;//是否碰到左边的屏幕
	bool _rightCollision;//是否碰到右边的屏幕
	bool _topCollision;//是否碰到上边的屏幕
	bool _bottomCollision;//是否碰到下边的屏幕

};
其中奖励的基类中有个虚函数execute,这个函数是真正的实现奖励的功能的真正触发点,由各自的子类实现各自的奖励功能(这里采用状态机的实现方式,而不用变量_awardType去做switch或if的判断,这样可以让程序的可维护性和代码的可读性更高)。除了触发功能点外其余的动作都交由这个基类来实现(毕竟对于子类来说他们就是实现的功能不一样而已,其余的像碰壁检测等动作都是一样的)。

实现类:

Award::Award() {//初始化成员变量
	_leftCollision = false;
	_rightCollision = false;
	_topCollision = false;
	_bottomCollision = false;

	_circle = NULL;
	_body = NULL;
	_halo = NULL;
}
bool Award::init() {//初始化圆环和小光圈(主体由子类去完成)
	_circle = CCSprite::createWithSpriteFrameName("circle.png");
	_halo = CCSprite::createWithSpriteFrameName("halo.png");
	this->addChild(_circle);
	this->addChild(_halo);
	_halo->setPosition(ccp(_circle->getContentSize().width / 2, 0));

	return true;
}
void Award::preSet() {
	for(unsigned int i = 0; i < 3; i++) {//分别预创建三个奖励
		ProtectedBodyAward::create();
		AddResumeAward::create();
		ShaderAward::create();
	}
}
void Award::startAction() {//开始动作
	if(_body) {
		//主体精灵做翻转动作,可以由引擎自带的CCOrbitCamera类来实现
		CCActionInterval* orbit = CCOrbitCamera::create(1, 1, 0, 0, 180, 180, 0);
		_body->runAction(CCRepeatForever::create(CCSequence::create(orbit, orbit->reverse(), NULL)));
	}
	//小光圈做圆周运动,有自定义的CircleAction类来实现
	_halo->runAction(CCRepeatForever::create(CircleAction::create(10, _circle->getPosition(), _circle->getContentSize().width / 2)));
}
void Award::endAction() {//结束动作
	this->stopAllActions();
}
void Award::doAction() {//当主角碰到奖励时触发该方法
	this->setActive(false);//设置不激活
	this->unscheduleUpdate();//停止调度更新
	this->endAction();//停止所有动作
	this->execute(); //触发奖励功能
	this->setVisible(false);//设置不可见
}
void Award::update(float dt) {
	CCPoint p = this->getPosition();
	CCSize size = _circle->getContentSize();
	CCSize winSize = CCDirector::sharedDirector()->getWinSize();
	if(this->_direction < 1) {
		this->_direction = (int)(CCRANDOM_0_1() * 360.0f);
	}
	//碰壁检测
	if(p.x - size.width / 2 <= 10 || p.y - size.height / 2 <= 10 || p.x + size.width / 2 >= ScreenWidth - 10 || p.y + size.height / 2 >= ScreenHeight - 10) {
		if(p.x - size.width / 2 <= 10 && !_leftCollision) {//碰到左壁
			if(this->_direction > 180) {
				this->_direction = this->_direction + 90;
			}else {
				this->_direction = this->_direction - 90;
			}
			_leftCollision = true;
			_rightCollision = false;
			_topCollision = false;
			_bottomCollision = false;
		}else if(p.y - size.height / 2 <= 10 && !_bottomCollision) {//碰到下壁
			if(this->_direction > 270) {
				this->_direction = this->_direction + 90;
			}else {
				this->_direction = this->_direction - 90;
			}
			_leftCollision = false;
			_rightCollision = false;
			_topCollision = false;
			_bottomCollision = true;
		}else if(p.x + size.width / 2 >= winSize.width - 10 && !_rightCollision) {//碰到右壁
			if(this->_direction < 180) {
				this->_direction = this->_direction + 90;
			}else {
				this->_direction = this->_direction - 90;
			}
			_leftCollision = false;
			_rightCollision = true;
			_topCollision = false;
			_bottomCollision = false;
		}else if(p.y + size.height / 2 >= ScreenHeight - 10 && !_topCollision){//碰到上壁
			if(this->_direction < 90) {
				this->_direction = this->_direction - 90;
			}else {
				this->_direction = this->_direction + 90;
			}
			_leftCollision = false;
			_rightCollision = false;
			_topCollision = true;
			_bottomCollision = false;
		}
		//计算最终的反弹角度
		if(this->_direction > 360) {
			this->_direction = this->_direction % 360;
		}else if(this->_direction < 0) {
			this->_direction = 360 + this->_direction;
		}
		float r = CC_DEGREES_TO_RADIANS(this->_direction);
		float c = cosf(r);
		float s = sinf(r);

		p = this->getPosition();
		this->setPosition(ccp(p.x + this->_speed * dt * c, p.y + this->_speed * dt *  s));
	}else {
		float r = CC_DEGREES_TO_RADIANS(this->_direction);
		float c = cosf(r);
		float s = sinf(r);
		this->setPosition(ccp(p.x + this->_speed * dt * c, p.y + this->_speed * dt *  s));
	}
}
Award* Award::getOrCreate(AWARD_TYPE awardType) {
	CCArray* array = Container::sharedContainer()->getAwards();
	CCObject* iterator;
	Award* award = NULL;
	CCARRAY_FOREACH(array, iterator) {
		award = (Award*)(iterator);
		if(award && award->getAwardType() == awardType && award->getActive() == false) {
			award->setActive(true);
			//设置初始化角度
			int direction = (int)(CCRANDOM_0_1() * 360);
			if(direction < 90) {
				direction = direction + 90;
			}else if(direction > 270) {
				direction = direction - 90;
			}
			award->setDirection(direction);
			return award;
		}
	}
	if(awardType == PROTECTED_BODY) {
		award = ProtectedBodyAward::create();
	}else if(awardType == ADD_RESUME_VALUE) {
		award = AddResumeAward::create();
	}else if(awardType == SHADER) {
		award = ShaderAward::create();
	}
	return award;
}
CCRect Award::collideRect() {//构造碰撞体
	CCPoint p = this->getPosition();
	CCSize size = _circle->getContentSize();
	return CCRectMake(p.x - size.width / 2, p.y - size.height / 2, size.width, size.height);
}


实现了基类后便要实现三个不同奖励功能的子类:

1)护盾:

class ProtectedBodyAward : public Award {
public:
	static ProtectedBodyAward* create();
	bool init();
	void execute();
};
ProtectedBodyAward* ProtectedBodyAward::create() {
	ProtectedBodyAward* protectedBodyAward = new ProtectedBodyAward();
	protectedBodyAward->init();
	Container::sharedContainer()->getAwards()->addObject(protectedBodyAward);
	protectedBodyAward->release();
	protectedBodyAward->setVisible(false);
	GameLayer::shareGameLayer()->addChild(protectedBodyAward);
	return protectedBodyAward;
}
bool ProtectedBodyAward::init() {
	bool result = false;
	if(Award::init()) {
		this->_active = true;
		this->_awardType = PROTECTED_BODY;//奖励类别
		this->_speed = 150;
		int direction = (int)(CCRANDOM_0_1() * 360);
		if(direction < 90) {
			direction = direction + 90;
		}else if(direction > 270) {
			direction = direction - 90;
		}
		this->_direction = direction;
		_body = CCSprite::createWithSpriteFrameName(shield_png);//主体精灵
		this->addChild(_body);
	}
	return result;
}
void ProtectedBodyAward::execute() {
	GameLayer::shareGameLayer()->getShip()->getProtectBody()->protectStart();//触发护盾
}
其余的两个都是一样的,都是在execute中实现不同的功能,随后在跟主角碰撞时触发下doAction方法即可。

//奖励判断
	CCArray* awards = Container::sharedContainer()->getAwards();
	Award* award = NULL;
	for (unsigned int j = 0; j < awards->count(); j++) {
		award = (Award*)awards->objectAtIndex(j);
		if(award->getActive()) {
			if(this->_ship->boundingBox().intersectsRect(award->collideRect())) {
				if(this->_isAppearShield && award->getAwardType() == PROTECTED_BODY) {
					if(this->_ship->getIsProtected() == false && this->_ship->getProtectBody()->getActive() == false) {
						award->doAction();
					}
				}else if(this->_isAppearShader && award->getAwardType() == SHADER) {
					award->doAction();
					this->scheduleOnce(schedule_selector(GameLayer::endShader), STATIC_DATA_FLOAT("shader_time"));
				}else if(award->getAwardType() == ADD_RESUME_VALUE){
					award->doAction();
				}
			}
		}
	}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值