cocos2dx 植物大战僵尸 4 太阳

游戏中的场景有的会产生阳光,所以需要在每一个关卡设置一个标识,来确定是否产生阳光,在tmx中添加以下属性


之后在LevelLayer中获取该属性
void LevelLayer::loadProperties()
{
	auto &properties = m_pTiledMap->getProperties();

	for (auto property : properties)
	{
		if (property.first == "produce sun")
		{
			m_bProduceSun = property.second.asBool();
		}
	}
}
然后就是在合适的时间产生阳光
void LevelLayer::update(float dt)
{
	if (!m_bProduceSun)
		return ;
	m_elapsed += dt;
	//产生阳光
	if (m_elapsed >= 16.f)
	{
		m_elapsed -= 16.f;

		Size visibleSize = Director::getInstance()->getVisibleSize();
		Point bornPos = Point(visibleSize.width/2,0);
		float duration = 6.f;
		MoveBy*move = MoveBy::create(duration,Point(0,500.f));

		m_pDelegate->makeSun(25,move,bornPos);
	}
}
目前设置每16秒出现一次太阳,这个间隔时间也可以放到tmx中的。

另外实现了PanelLayet,目前保存了 阳光背景 阳光计数板和一个铲子背景(铲子以后实现),可以用外部文件,也可以使用代码生成(如果使用cocostudio,需要和cocos2dx版本对应),另外,如果使用外部文件的话,还需要获取这些控件,作扩展使用,另一个就是点击阳光后会有有一个移动到阳光计数器板的动作,也是需要获取阳光计数板的位置的

接着就是Product 和ProductLayer的实现
Product就是产品,这里包括 金币 阳光(还有以后扩展的花园模式的道具),都是Product,这些除了贴图不同,还有一个区别就是效果不同(效果在GameScene中判断),所以仅仅实现Product类就行了,然后使用enum来标识不同种类,再在GameScene中判断

生成太阳的方法如下
void ProductLayer::makeSun(int number,FiniteTimeAction*action,const Point&bornPos)
{
	//生成太阳
	Product*sun = Product::create();
	//设置各种属性
	sun->setNumber(number);
	sun->setClicked(false);
	sun->setUpdate(false);
	sun->setDead(false);
	sun->setDuration(10.f);
	sun->setProductType(ProductType::Sun);
	sun->setPosition(bornPos);

	this->addChild(sun);
	m_products.push_back(sun);
	//设置动画
	auto animationName = "Sun";
	auto animation = AnimationCache::getInstance()->getAnimation(animationName);
	//获取第一帧
	auto firstFrame = (animation->getFrames().at(0))->getSpriteFrame();
	//设置贴图
	sun->bindSpriteWithSpriteFrame(firstFrame);
	//根据number设置太阳大小
	if (number < 25)
		sun->getSprite()->setScale(0.5f,0.5f);

	//运行动画和动作
	sun->getSprite()->runAction(Animate::create(animation));

	CallFunc*end = CallFunc::create([sun]()
	{
		sun->setUpdate(true);
	});

	auto seq = Sequence::createWithTwoActions(action,end);
	sun->runAction(seq);
}

在这里我使用了AnimationCache读取的外部动画文件,在使用时直接加载就可以了
enum class ProductType
{
	None,
	Sun,//太阳
	Gold,//金币
};
目前仅仅有太阳和金币这两种
void Product::update(float dt)
{
	//如果死亡或者已经点击过了,则不进行更新
	if (m_bDead || m_bClicked)
		return;
	if (m_bUpdate)
	{
		m_duration -= dt;
		if (m_duration <= 0.f)
			m_bDead = true;
	}
}

这是产品的普遍更新函数,都有一定的存活时间,在时间消耗完后直接消失

目前的触碰到阳光放在了onTouchEnded(),主要是为了点击阳光成功就不会向下执行种植等操作。
void GameScene::onTouchEnded(Touch*touch,SDL_Event*event)
{
	auto pos = touch->getLocation();
	//是否点击了ProductLayer
	auto product = m_pProductLayer->getClickedProduct(pos);
	if (product)
	{
		product->setClicked(true);
		this->collectProduct(product);

		return;
	}
	//...
}
在点击了阳光后会直接返回,不再执行后面的操作
void GameScene::collectProduct(Product*product)
{
	//点击了太阳
	if (product->getProductType() == ProductType::Sun)
	{
		//获取结束位置
		auto endPos = m_pPanelLayer->getSunBgPosition();
		auto deltaPos = product->getPosition() - endPos;

		auto length = deltaPos.length();

		MoveTo*move = MoveTo::create(length/400,endPos);
		CallFunc*end = CallFunc::create([this,product]()
		{
			this->addSun(product->getNumber());
			product->setDead(true);
		});
		auto seq = Sequence::createWithTwoActions(move,end);
		//运行动作
		product->stopAllActions();
		product->runAction(seq);
	}
}

这个结束位置就是获取在PanelLayer获取的阳光计数板背景的位置。






  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值