有没有搞错 粤语,下个植物大战僵尸都要100多M

当前位置:
& 植物大战僵尸
CopyRight2004年-年 YXdown.Com 游迅网 All Rights Reserved
备案编号:沪ICP备号-3cocos2dx(27)
新建一个僵尸基类,注意如果使用cocos2dx,把SDL改为CC
/*僵尸移动方向*/
enum class ZombieDir
class ZombieDelegate
virtual Plant*getTopPlant(Terrain*terrain) = 0;
class ZombieBase : public Entity
SDL_BOOL_SYNTHESIZE(m_bDead,Dead);//是否死亡
SDL_SYNTHESIZE(int,m_nHitPoint,HitPoint);//当前血量
SDL_SYNTHESIZE(float,m_fBaseSpeed,BaseSpeed);//基础移动速度
SDL_SYNTHESIZE(int,m_nRow,Row);//当前行数
SDL_SYNTHESIZE(string,m_zombieName,ZombieName);//僵尸名称
SDL_SYNTHESIZE(ZombieDir,m_dir,ZombieDir);//僵尸当前移动方向
SDL_SYNTHESIZE(float,m_fColdDownTime,ColdDownTime);//攻击冷却时间
SDL_SYNTHESIZE(int,m_nDamage,Damage);//伤害值
protected:
Terrain*m_pA//当前塔基
ZombieDelegate*m_pD
MoveBehavior*m_pMoveB
ZombieBase();
~ZombieBase();
void setDelegate(ZombieDelegate*pDelegate);
void setAim(Terrain*plant);
Terrain*getAim();
void clearAim();
bool isDying()
void setMoveBehavior(MoveBehavior*behavior);
MoveBehavior*getMoveBehavior();
virtual float getCurSpeed()
virtual Rect getCollisionBoundingBox()
僵尸基类保存了所有僵尸都会拥有的属性。
下面说一说僵尸的攻击,僵尸需要先检测和哪一个塔基发生了碰撞,然后再判断这个塔基是否存在植物,如果存在,则setAim()为当前的攻击目标,因为一般的僵尸的攻击不是以口计算的,而是以时间计算的,所以还会有一个攻击冷却时间。
以前的代码中虽然添加过僵尸的行走路径,但我目前没什么好的思路,所以目前就仅仅实现一个简单的行为,等到以后想实现更复杂的行走,只要修改或者增加行为类即可,而不用修改僵尸类,这就是组合的好处了。僵尸基类并没有什么实质性的内容,下面看看僵尸类
class Zombie : public ZombieBase
enum class State
static const int ANIMATION_TAG;
~Zombie();
static Zombie*create(const string&zombieName);
bool init(const string&zombieName);
virtual void update(float dt);
virtual float getCurSpeed()
virtual Rect getCollisionBoundingBox()
void changeState(State state);
};普通的僵尸只有三种状态,站立,行走,攻击(暂时不添加死亡状态)。然后僵尸类会在update函数中对当前的状态进行更新,看看实现吧
bool Zombie::init(const string&zombieName)
this-&setZombieName(zombieName);
//设置类型todo
m_nType = 1;
//获取站立状态贴图
auto animationName = StringUtils::format("%sIdle%02d",zombieName.c_str(),m_nType);
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,size.height/2);
this-&setContentSize(size);
this-&addChild(m_pSprite);
//运行站立动画
auto animate = Animate::create(animation);
animate-&setTag(ANIMATION_TAG);
m_pSprite-&runAction(animate);
//设置为站立状态
m_state = State::I
获取animation,之后运行动画,并且设置当前的状态为站立状态
void Zombie::update(float dt)
//TODO 当前如果处于站立状态,则直接跳转到行走状态
if (m_state == State::Idle)
this-&changeState(State::Walk);
//当前存在攻击目标
else if (m_pAim != nullptr)
if (m_pAim-&getInnerPlant() != nullptr)
this-&changeState(State::Attack);
m_elapsed +=
//到达攻击时间
if (m_elapsed &= this-&getColdDownTime())
m_elapsed -= this-&getColdDownTime();
//进行攻击
auto topPlant = m_pDelegate-&getTopPlant(m_pAim);
topPlant-&hurt(this-&getDamage());
else//重新计时
this-&clearAim();
m_elapsed = 0.f;
//没有攻击目标,行走
else if (m_pAim == nullptr)
this-&changeState(State::Walk);
if (m_pMoveBehavior)
m_pMoveBehavior-&performMove(this);
}如果当前塔基中存在植物,则进行攻击计时。僵尸在攻击植物时,植物可能会被铲除,或者上面添加新的植物,如花盆上种植其他植物,这里就是获取塔基的最上层的植物进行攻击。另外就是m_pDelegate,为
class ZombieDelegate
virtual Plant*getTopPlant(Terrain*terrain) = 0;
目前的update函数就是对僵尸状态的更新,值得一提的是,僵尸攻击植物是按时间计算的,而不是按"口"计算,这个需要注意float Zombie::getCurSpeed()const
return ZombieBase::getCurSpeed();
Rect Zombie::getCollisionBoundingBox()const
Rect rect = this-&getSprite()-&getSpriteFrameRect();
//对x y坐标进行设置
auto r = this-&getBoundingBox();
rect.origin.x += r.origin.x;
rect.origin.y += r.origin.y;
}getCollisionBoundingBox()是对getBoundingBox()的碰撞面积的一个加强版,这个主要针对使用TexturePacker导出的精灵表,并且这个精灵表需要裁剪空白之处。虽然以前的代码中计划使用box2d进行模拟碰撞,但使用了的话逻辑处理并不算很好,所以box2d不再使用,以前的代码我会进行一些小小的改变。
void Zombie::changeState(State state)
//状态没有发生改变,直接退出
if (m_state == state)
if (m_state == State::Walk)
//停止原先的动画
this-&getSprite()-&stopActionByTag(ANIMATION_TAG);
//设置新动画
auto animationName = StringUtils::format("%sWalk%02d",m_zombieName.c_str(),m_nType);
auto animation = AnimationCache::getInstance()-&getAnimation(animationName);
auto animate = Animate::create(animation);
animate-&setTag(ANIMATION_TAG);
this-&getSprite()-&runAction(animate);
else if (m_state == State::Attack)
//停止原先的动画
this-&getSprite()-&stopActionByTag(ANIMATION_TAG);
//设置新动画
auto animationName = StringUtils::format("%sAttack",m_zombieName.c_str(),m_nType);
auto animation = AnimationCache::getInstance()-&getAnimation(animationName);
auto animate = Animate::create(animation);
animate-&setTag(ANIMATION_TAG);
this-&getSprite()-&runAction(animate);
}改变状态,同时改变相应的动画,那个ANIMATION_TAG是静态常量,为了方便动画的移除(cocos2dx源码中的stopAllActions()是会删除当前节点的存储表)
之后就是僵尸层和僵尸工厂的实现了,这些和植物层以及植物工厂很像。
ZombieBase*ZombieLayer::makeZombie(const string&zombieName,int row)
ZombieBase*zombie =
MoveBehavior*moveBehavior =
//对应生成僵尸,同时设置一些属性
if (zombieName == ZOMBIE_NAME)
zombie = m_pZombieFactory-&createCommonZombie(ZOMBIE_NAME);
zombie-&setZombieDir(ZombieDir::Left);
moveBehavior = new LineMoveBehavior();
if (zombie != nullptr)
m_zombies[row].push_back(zombie);
//设置行走类型
zombie-&setMoveBehavior(moveBehavior);
生成对应的僵尸,并且放到对应的容器之中。另外就是行为的实现了
void LineMoveBehavior::performMove(ZombieBase*zombie)
auto dir = zombie-&getZombieDir();
auto curPos = zombie-&getPosition();
float speed = zombie-&getCurSpeed();
Point nextP
if (dir == ZombieDir::Left)
nextPos = curPos - Point(speed,0.f);
else if (dir == ZombieDir::Right)
nextPos = curPos + Point(speed,0.f);
zombie-&setPosition(nextPos);
很简单的实现,就是根据当前的朝向,决定是否是相加还是相减
Zombie*ZombieFactory::createCommonZombie(const string&zombieName)
auto zombie = Zombie::create(zombieName);
//设置基础属性
zombie-&setDead(false);
zombie-&setHitPoint(200);
zombie-&setBaseSpeed(0.15f);
zombie-&setColdDownTime(1.f);
zombie-&setDamage(100);
}接下来就是点击了僵尸卡片之后的处理了void GameScene::onTouchEnded(Touch*touch,SDL_Event*event)
auto selectedCard = m_pCardLayer-&getSelectedCard();
//存在选中的卡片,则阳光足够,cd完成
if (selectedCard)
bool bRet =
//获取当前的关卡类型,来创建是植物还是僵尸
auto levelType = m_pLevelLayer-&getLevelCardShowType();
if (levelType == LevelCardType::Plant)
bRet = this-&tryPlanting(selectedCard,terrain);
else if (levelType == LevelCardType::Zombie)
bRet = this-&tryMakingZombie(selectedCard,terrain);
//创建完成,则判断消耗了什么
auto cardType = selectedCard-&getCardType();
if (cardType == CardType::Common)
//减少阳光值
this-&subSun(selectedCard-&getWorth());
//取消点击
m_pCardLayer-&unselectedCard();
//该卡片开始cd
selectedCard-&setCurCD(selectedCard-&getCD());
else if (cardType == CardType::Consumable)
m_pCardLayer-&removeCard(selectedCard);
}//选中了铲子
}这里添加了一个判断,标识当前的卡片是僵尸还是植物bool GameScene::tryMakingZombie(Card*card,Terrain*terrain)
bool bRet =
//获取关卡对应的行数
int row = terrain-&getRow();
//获取对应的路径
const auto path = m_pLevelLayer-&getZombiePathOfRow(row);
//生成僵尸
auto zombie = m_pZombieLayer-&makeZombie(card-&getCardName(),row);
//设置位置
auto pos = terrain-&getPosition();
auto terrainSize = terrain-&getContentSize();
auto zombieSize = zombie-&getContentSize();
pos.y -= (zombieSize.height - terrainSize.height)/2.f;
zombie-&setPosition(pos);
zombie-&setRow(row);
//添加到场景中
auto entityLayer = this-&getEntityLayer();
entityLayer-&addChild(zombie,row);
}目前的僵尸的x轴是获取的地基的x轴的,这个以后再进行更新吧。本节结果截图豆丁微信公众号
君,已阅读到文档的结尾了呢~~
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
C# 通过Devart.Data.Oracle.dll连接oracle如何才能摆脱客户端啊
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='http://www.docin.com/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口}

我要回帖

更多关于 有没有搞错 粤语 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信