cocos2dx 植物大战僵尸 24 坚果和大坚果

前些天实现了撑杆僵尸,对于撑杆僵尸来说,只有大坚果是无法跳过去的,所以本节实现坚果和大坚果,对于这两种植物,实现起来是不难的,因为只是一般的植物,然后会有两个损伤点,损伤点1:int(MAX HP*2/3) 损伤点2:int(MAX HP*1/3)(摘自百度词条pvz)。接着看看实现吧。

class WallNut : public Plant
{
protected:
	enum class State
	{
		None,
		Normal,
		Cracked1,
		Cracked2,
	};
protected:
	int m_nAllHp;
	State m_state;
public:
	WallNut();
	~WallNut();
	static WallNut*create(const string&plantName);
	bool init(const string&plantName);

	void setAllHitPoint(const int&hp);
	virtual void updateHook(float dt);
	virtual void onHurt();
protected:
	virtual void changeState(State state);
主要的就是onHurt函数和changeState()

void WallNut::onHurt()
{
	Plant::onHurt();

	auto curHP = this->getHitPoint();

	auto cracked = 3;
	if (curHP != 0)
	{
		cracked = m_nAllHp/curHP;
	}
	State state = State::None;

	if (cracked == 1)
	{
		state = State::Normal;
	}
	else if (cracked == 2)
	{
		state = State::Cracked1;
	}
	else if (cracked == 3)
	{
		state = State::Cracked2;
	}
	this->changeState(state);
}
需要注意的是,当前血量可能会为0,所以需要特地判断以下。

void WallNut::changeState(State state)
{
	if (m_state == State::None || m_state == state)
		return;
	m_state = state;

	string animationName;
	auto plantName = this->getPlantName();
	Animation*animation = nullptr;

	if (state == State::Normal)
	{
		animationName = plantName;
	}
	else if (state == State::Cracked1)
	{
		animationName = StringUtils::format("%s_cracked1",plantName.c_str());
	}
	else if (state == State::Cracked2)
	{
		animationName = StringUtils::format("%s_cracked2",plantName.c_str());
	}

	if (!animationName.empty())
	{
		animation = AnimationCache::getInstance()->getAnimation(animationName);
		auto animate = Animate::create(animation);
		animate->setTag(ANIMATION_TAG);
		//停止原先动画
		this->getSprite()->stopActionByTag(ANIMATION_TAG);

		this->getSprite()->runAction(animate);
	}
}
改变状态还是类似于以前的代码,仅仅进行动画的改变。接下来就是大坚果了。

class TallNut : public WallNut
{
public:
	TallNut();
	~TallNut();
	static TallNut*create(const string&plantName);
	bool init(const string&plantName);
};
bool TallNut::init(const string&plantName)
{
	this->setPlantName(plantName);
	//设置正常动画
	auto animationName = plantName;
	auto animation = AnimationCache::getInstance()->getAnimation(animationName);
	//设置贴图
	auto firstFrame = animation->getFrames().front()->getSpriteFrame();
	m_pSprite = Sprite::createWithSpriteFrame(firstFrame);
	
	auto size = m_pSprite->getContentSize();
	//设置位置
	m_pSprite->setPosition(size.width/2.f,size.height/2.f);
	//设置锚点
	m_pSprite->setAnchorPoint(Point(0.5f,0.65f));

	this->setContentSize(size);
	this->addChild(m_pSprite);
	//设置运行动画
	Animate*animate = Animate::create(animation);
	animate->setTag(ANIMATION_TAG);
	this->getSprite()->runAction(animate);
	//设置当前状态
	m_state = State::Normal;

	return true;
}
大坚果继承自坚果,除了init函数,其他函数全部不需要更新,坚果的changeState的实现中根据当前的植物名称和当前状态确定动画名称,我们所需要做的就是确保他们的格式相同即可。然后就是撑杆僵尸的更新了,撑杆僵尸在跳起会检测当前的目标的植物是否是大坚果,如果是,则越过失败。

void PoleVaultingZombie::jump2()
{
	this->changeState(State::Jump2);
	//失去撑杆
	m_bLosePole = true;
	//是否能跳过去 TODO
	//直接设置位置
	auto pos = this->getPosition();
	auto size = this->getContentSize();
	auto rect = this->getCollisionBoundingBox();

	//获取当前的植物是否是高坚果
	auto topPlant = m_pDelegate->getTopPlant(m_pAim);
	//跳过失败
	if (PlantLayer::isTallNut(topPlant))
	{
		this->setPosition(pos - Point(40.f,0.f));
	}
	else
	{
		this->setPosition(pos - Point(120.f,0.f));
	}
	//清除当前目标
	this->clearAim();
}
这个40和120是根据动画有关的,以后还会进行调整的。然后就是僵尸基类添加一个新的函数。

//是否参与与子弹的碰撞,不包括Boom 默认为true
virtual bool isActiveForBullet()const;
撑杆僵尸在跳起时,暂时不参与与子弹(Boom除外)的碰撞,所以需要进行一个标识。接着就是撑杆僵尸的更新

void PoleVaultingZombie::jump()
{
	this->changeState(State::Jump);
	//不对子弹起碰撞
	m_bIsActiveForBullet = false;
}
bool PoleVaultingZombie::isActiveForBullet()const
{
	return m_bIsActiveForBullet;
}
然后就是BulletLayer的更新了。

void BulletLayer::checkCollisionBetweenZombieAndBullet(Bullet*bullet)
{
	auto row = bullet->getRow();

	auto zombies = m_pDelegate->getZombiesOfRow(row);
	auto r = bullet->getCollisionBoundingBox();

	for (auto it = zombies.begin();it != zombies.end();it++)
	{
		auto zombie = *it;

		if (bullet->isDying())
			break;

		auto rect = zombie->getCollisionBoundingBox();
		//僵尸收到伤害
		if (r.intersectsRect(rect))
		{
			this->handleCollision(bullet,zombie);
		}
	}
	//子弹碰撞结束
	bullet->contactEnd();
}
然后添加一个handleCollision函数了。

void BulletLayer::handleCollision(Bullet*bullet,ZombieBase*zombie)
{
	auto attactType = bullet->getAttackType();
	bool isTrack = Bullet::isTrackBullet(attactType);
	bool bIsHurt = false;
	//当前子弹是Boom 则无法避免
	if (bullet->getAttackType() == AttackType::Boom)
	{
		bIsHurt = true;
	}//僵尸是和子弹能发生碰撞
	else if (zombie->isActiveForBullet())
	{
		//是追踪性子弹 并且碰撞的是目标僵尸
		if (isTrack && zombie == bullet->getAimZombie())
			bIsHurt = true;
		//不是追踪子弹
		else if (!isTrack)
			bIsHurt = true;
	}
	if (bIsHurt)
	{
		bullet->hurt();
		//僵尸受伤
		zombie->hurt(bullet->getDamage(),bullet->getAttackType());
	}
}
这里也只是一个逻辑的更新。本节截图。
cocos2dx 植物大战僵尸 24 坚果和大坚果_第1张图片

你可能感兴趣的:(cocos2dx)