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());
	}
}
这里也只是一个逻辑的更新。本节截图。

植物大战僵尸》是一款著名的塔防游戏,由PopCap Games开发并于2009年发布。游戏灵感来源于百度的一个匿名帖子,以僵尸来袭为背景,玩家需要利用各种植物来阻止僵尸入侵自己的庭院。 在游戏中,玩家扮演植物收集者,面对不断进攻的僵尸。玩家需要通过种植不同的植物来建立防线,阻止僵尸的前进。每个植物都有不同的特殊技能和攻击方式,如射手植物可以发射豌豆攻击僵尸,坚果植物可以阻挡僵尸前进的道路,向日葵植物可以帮助玩家获取更多太阳能量等。玩家需要根据僵尸的种类和速度,选择合适的植物来组成最佳的防线。 游戏中有多个关卡,每个关卡都有不同的地图和僵尸。随着游戏的进行,僵尸的种类和数量逐渐增加,玩家需要不断升级植物,以应对更强大的敌人。此外,游戏还提供了一些道具和特殊植物,如炸弹植物和冰冻植物,来帮助玩家更有效地对抗僵尸。 《植物大战僵尸》以其简单易懂的操作和各种可爱有趣的植物形象赢得了很多玩家的喜爱。游戏不仅提供了休闲娱乐的体验,还可以训练玩家的策略思维和反应能力。 总之,《植物大战僵尸》是一款经典的塔防游戏,以其独特的主题、可爱的植物形象和刺激的游戏体验吸引了无数的玩家。无论是植物收集者还是僵尸爱好者,都能在这个游戏中找到乐趣。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值