cocos2dx 植物大战僵尸 17 路障僵尸

本文介绍了一个基于《植物大战僵尸》游戏中路障僵尸的设计方案。通过继承Zombie基类并结合装饰者模式,实现了路障僵尸的独特行为,包括路障掉落动画及伤害吸收机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原版植物大战僵尸的路障是饰品,能阻挡一部分伤害,在路障掉落前路障僵尸是不会受伤的。

如下为个人头脑风暴。

路障僵尸使用装饰者的话,需要继承自ZombieBase,由于图片原因,所以内部需要有一个普通僵尸。对木桶僵尸,内部处理的逻辑为站立,行走,攻击,当路障死亡后更新交给Zombie即可。路障在活着时负责对伤害的吸收,在路障死亡时,会有一个路障掉落动画。同时路障僵尸的贴图消失,显示内部僵尸的贴图。但是用装饰者无法实现磁力菇,因为磁力菇需要判断僵尸是否有饰品,如果有还需要判断饰品是否为铁质饰品。故新建饰品类为Garnishry,不过这样一来路障僵尸就需要继承自普通僵尸,因为植物大战僵尸使用的是骨骼动画,能很容易地实现路障等饰品随僵尸运动的效果,而帧动画要实现就很困难了。
目前思路1 路障僵尸的路障可以增加防御力,比如豌豆攻击20,则吸收10即可。这样和原著稍微不同,好处是动画会连贯,(需要在死亡时头和饰品全部掉落.显得不那么突兀)
思路2 尽量跟进原版,缺点是动画处理肯定不流畅,优点就是和原版接近。
个人偏向于思路1的,毕竟帧动画限制。不过还是需要实现路障僵尸类,毕竟贴图不同
以上就是我决定添加饰品类和路障僵尸的部分思路
先看看路障的实现吧。
//-------------------------路障Conehead----------------------------
class Conehead : public Garnishry
{
	SDL_SYNTHESIZE(int,m_nDefense,Defense);//防御值
public:
	Conehead();
	~Conehead();
	CREATE_FUNC(Conehead);
	bool init();
	virtual int absorbDamage(int baseDamage,AttackType attackType);
};
bool Conehead::init()
{
	//设置血量 不小于0即可
	this->setHitPoint(1);
	this->setType(Type::Common);
	this->setDefense(13);

	return true;
}

int Conehead::absorbDamage(int baseDamage,AttackType attackType)
{
	//吸收部分伤害,如果伤害值小于0,强制少1
	auto damage = baseDamage - this->getDefense();

	if (damage < 0)
	{
		damage = 1;
	}

	return damage;
}
路障专用于路障僵尸,每次都会吸收13点伤害。路障僵尸继承于Zombie
/*由于资源和帧动画限制,只能继承自Zombie*/
class ConeheadZombie : public Zombie
{
public:
	ConeheadZombie();
	~ConeheadZombie();
	static ConeheadZombie*create(const string&zombieName);
	bool init(const string&zombieName);
protected:
	virtual void changeState(State state);
	virtual void showZombieHead();
};
由于是继承自Zombie,路障僵尸实现就简单多了
void ConeheadZombie::changeState(State state)
{
	//状态没有发生改变,直接退出
	if (m_state == state)
		return ;

	m_state = state;
	string animationName;

	if (m_state == State::Walk)
	{
		animationName = StringUtils::format("%sWalk",m_zombieName.c_str());
	}
	else if (m_state == State::Attack)
	{
		animationName = StringUtils::format("%sAttack",m_zombieName.c_str());
	}
	else if (m_state == State::WalkDead)
	{
		animationName = "ZombieLostHead";

		this->showZombieHead();
	}
	else if (m_state == State::AttackDead)
	{
		animationName = "ZombieLostHeadAttack";
		
		this->showZombieHead();
	}
	//停止原先的动画
	this->getSprite()->stopActionByTag(ANIMATION_TAG);

	auto animation = AnimationCache::getInstance()->getAnimation(animationName);
	auto animate = Animate::create(animation);
	animate->setTag(ANIMATION_TAG);

	this->getSprite()->runAction(animate);
}
改变状态时改变对应的动画,在Zombie::update()中进行调用。
void ConeheadZombie::showZombieHead()
{
	//调整位置
	Point bornPos = this->getPosition();
	Size size = this->getContentSize();

	bornPos.x += size.width/4.f;

	m_pDelegate->showZombieHead(bornPos);
	//显示路障掉落动作
	Point pos = this->getPosition();
	pos.x += size.width/4;
	pos.y -= size.height/2;

	m_pDelegate->showConeAction(pos);
}
这里比普通僵尸多了的就是路障掉落动作了,在特效层实现。
void EffectLayer::showConeAction(const Point&pos,Layer*layer,int tag)
{
	//获取路障精灵名称
	auto spriteName = "Zombie_cone3.png";
	float duration = 0.8f;
	float rotation = 20.f;

	Sprite*sprite = Sprite::createWithSpriteFrameName(spriteName);
	sprite->setPosition(pos);
	sprite->setRotation(rotation);

	layer->addChild(sprite,tag);
	//运行动作
	JumpBy*jump = JumpBy::create(duration,Point(40.f,140.f),-10.f,1);
	RotateBy*rotate = RotateBy::create(duration,40.f);
	RemoveSelf*remove = RemoveSelf::create();

	auto spawn = Spawn::createWithTwoActions(jump,rotate);
	auto seq = Sequence::createWithTwoActions(spawn,remove);

	sprite->runAction(seq);
}
然后在cards.plist添加路障僵尸卡片即可
    <!--路障僵尸-->
    <key>ConeheadZombie</key>
    <dict>
      <key>desc</key>
      <string></string>
      <key>worth</key>
      <integer>75</integer>
      <key>CD</key>
      <real>7.5</real>
      <key>ready time</key>
      <real>0</real>
      <key>active</key>
      <string>all</string>
      <key>needful terrain</key>
      <array>
        <string>Lawn</string>
      </array>
    </dict>
然后在ZombieFactory中实现对应的创建方法
ConeheadZombie*ZombieFactory::createConeheadZombie(const string&zombieName)
{
	auto zombie = ConeheadZombie::create(zombieName);
	//设置基础属性
	zombie->setDead(false);
	zombie->setHitPoint(200);
	zombie->setBaseSpeed(0.15f);
	zombie->setColdDownTime(1.f);
	zombie->setDamage(100);
	zombie->setCriticalPoint(70.f);
	//设置装饰品
	zombie->setGarnishry(Conehead::create());
	//添加血条
	HpBar*hpBar = HpBar::create("hpBar1.png","hpBarBG.png",200.f);
	//设置血条位置
	auto rect = zombie->getSprite()->getSpriteFrameRect();
	Size size = zombie->getContentSize();
	Size barSize = hpBar->getContentSize();
	
	Point pos;
	pos.x = rect.origin.x + rect.size.width/2;
	pos.y = rect.size.height/2 - size.height/2 - barSize.height/2;

	hpBar->setPosition(pos);

	zombie->bindHpBar(hpBar);

	return zombie;
}
然后在ZombieLayer中的makeZombie中调用这个函数
	else if (zombieName == CONEHEADZOMBIE_NAME)
	{
		zombie = m_pZombieFactory->createConeheadZombie(zombieName);
		zombie->setZombieDir(ZombieDir::Left);
		moveBehavior = new LineMoveBehavior();
	}
本节截图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值