cocos2dx 植物大战僵尸 1 简言创建关卡层
2017-05-19 14:51
459 查看
本系列不定期更新,我也在网上找了一些资源,但都没能很好地还原原作,不得不说有些遗憾,这次的编写使用的是类cocos2dx的语法,因为cocos2dx的更新速度很快,所以我采用的是类似于伪代码的形式,只贴上具体的代码,另外,我是边写程序边写心得,称不上是教程,我会写下来让我感到纠结的地方,有什么不对的或者不好的,请指点,大家共同努力
游戏框架采用的是MVC(应该是吧)。GameScene作为控制器,继承自Scene,目前没什么内容
植物大战僵尸(以下简称pvz)的关卡是多种多样的,有草地,后院,屋顶等类型,在这里我打算使用tmx来保存关卡的数据,比如初始阳光啦,是白天还是晚上啦,僵尸的出场等等。
pvz是塔防游戏,塔防游戏不可避免地就是炮塔可以放置在什么地方,即塔基,对pvz来说,关卡原生的塔基有3种,分别是草地,水面和石头面
这三种,大多数植物可以直接种在草地上
,一部分可以种植在水面上(如荷叶),有些则可以种植在石头面上(如花盆),并且毁灭蘑菇,也会在草地上留下一个被炸毁的痕迹,所以,我打算使用一个类来表示当前的地形状态,Terrain,这个类保存在LevelLayer层中,是和关卡息息相关的
这样做对目前的好处是,当前的Terrain并不是都需要显示在界面上的,如果要继承Sprite,就必须赋值一个图片,要不就会出错(继承自Sprite,就会有渲染,没有初始化的话渲染失败,就会出错)
接下来就是地图了。
第一张图是5*9 相对比较规则的图形,第二张是6*9相对规则的图形,而第三张就不是规则图形了。
我一开始计划使用上面瓦片,三种颜色对应三种不同的Terrain类型,这样满足前两个图形,那第三个图怎么办呢?自己独立开发一个地图编辑器不太可能,那就只有使用tiled的对象层功能了。
我新建了一个对象层,自己决定里面的地形的位置和类型,那不就可以了嘛。当然,这个方法可行,那么问题就在于程序中如何解析并生成对应的Terrain了
好了,放上效果图
目测很不错
对地图
目前分为两种,使用图块解析和,使用对象解析。
使用图块,图块内的属性包含着地形的类型,对象层也是如此,并且这里的地图类型分为3种,Lawn Water Stone 即草地 水面 石面,由于在外部文件中保存的这些是字符串,所以还要有一个转换,这个转换目前在TerrainMaker中进行,至于以后要不要再增加其他的类型,则是以后扩展使用了,比如你可以加个沙漠类型的图,上面只能种仙人掌,其他的植物只能种在花盆上。
在生成Terrain对象的时候,要设置
1 地形类型
2 位置
3 尺寸大小
4 当前是否可以种植()
这三个是必选的,需要注意的是,这里的Terrain继承自Entity,也就是说,它是可以显示图形的,而地形显示图形的目前仅一种,就是被毁灭菇炸后留下的坑,这个是草地所特有的,不过也没必要特地再创建一个子类,在被毁灭菇炸坏后可以设置一个动画,只不过这个动画特别长,每隔一段不短的时间会换帧,在动画结束时就可以设置地形状态可种植,不过需要注意的是,当前的地形的精灵是空的,所以无法运行动画,这难不倒我,先从AnimationCache获取到对应动画,然后获取该动画的第一SpriteFrame,然后内部精灵通过createWithSpriteFrame创建就可以了,还有一个需要注意的,由于使用的是组合,所以得设置两个动作,一个为动画,另一个为DelayTime和CallFunc的组合动作,上面那个交给内部精灵,组合动作交给地形类,各司其职
游戏框架采用的是MVC(应该是吧)。GameScene作为控制器,继承自Scene,目前没什么内容
植物大战僵尸(以下简称pvz)的关卡是多种多样的,有草地,后院,屋顶等类型,在这里我打算使用tmx来保存关卡的数据,比如初始阳光啦,是白天还是晚上啦,僵尸的出场等等。
pvz是塔防游戏,塔防游戏不可避免地就是炮塔可以放置在什么地方,即塔基,对pvz来说,关卡原生的塔基有3种,分别是草地,水面和石头面
这三种,大多数植物可以直接种在草地上
,一部分可以种植在水面上(如荷叶),有些则可以种植在石头面上(如花盆),并且毁灭蘑菇,也会在草地上留下一个被炸毁的痕迹,所以,我打算使用一个类来表示当前的地形状态,Terrain,这个类保存在LevelLayer层中,是和关卡息息相关的
class Terrain:public Entity { CC_SYNTHESIZE(TerrainType,m_terrainType,TerrainType);//该地形的类型 CC_BOOL_SYNTHESIZE(m_bDestroyed,Destroyed);//当前的地形是否被毁坏 这个是自己封装的,类似与SYNTHESIZE public: Terrain(); ~Terrain(); CREATE_FUNC(Terrain); bool init(); };还有就是实体类,实体类倒是简单,就是一切看的见的就是实体类,这里我是采用了组合,当然,继承也是可以的。
class Entity:public Node { protected: Sprite*m_pSprite; public: Entity(); ~Entity(); Sprite*getSprite()const; //和bind不同,此函数不改变content size void setSprite(Sprite*sprite); void bindSprite(Sprite*sprite); bool bindSpriteWithSpriteFrameName(const string&spriteName); //创建动画 static Animate*createAnimate(std::string format,int begin,int end,float delayPerUnit,unsigned int loops=-1);
这样做对目前的好处是,当前的Terrain并不是都需要显示在界面上的,如果要继承Sprite,就必须赋值一个图片,要不就会出错(继承自Sprite,就会有渲染,没有初始化的话渲染失败,就会出错)
接下来就是地图了。
第一张图是5*9 相对比较规则的图形,第二张是6*9相对规则的图形,而第三张就不是规则图形了。
我一开始计划使用上面瓦片,三种颜色对应三种不同的Terrain类型,这样满足前两个图形,那第三个图怎么办呢?自己独立开发一个地图编辑器不太可能,那就只有使用tiled的对象层功能了。
我新建了一个对象层,自己决定里面的地形的位置和类型,那不就可以了嘛。当然,这个方法可行,那么问题就在于程序中如何解析并生成对应的Terrain了
class TerrainMaker { private: function<void (Terrain*)> m_callback; public: TerrainMaker(); //开始解析 void startParse(TMXTiledMap*tiledMap,const function<void (Terrain*)>& callback); private: void parseTileLayer(TMXLayer*layer,TMXTiledMap*tiledMap); void parseObjectGroup(TMXObjectGroup*objectGroup); TerrainType convertStrToTerrainType(const string&sType);这个就是Terrain解析,并且每解析一个就回调函数
bool LevelLayer::initWithLevel(const string&sLevel) { //加载关卡 m_pTiledMap = TMXTiledMap::create(sLevel); this->addChild(m_pTiledMap); //获取地形 TerrainMaker maker; maker.startParse(m_pTiledMap,SDL_CALLBACK_1(LevelLayer::makeTerrainCallback,this)); return true; }生成Terrain回调函数,并进行一个小测试
void LevelLayer::makeTerrainCallback(Terrain*terrain) { m_terrains.push_back(terrain); this->addChild(terrain); //进行一个小小的测试 Sprite*sprite = Sprite::create("0.png"); terrain->setSprite(sprite); }
好了,放上效果图
目测很不错
对地图
目前分为两种,使用图块解析和,使用对象解析。
使用图块,图块内的属性包含着地形的类型,对象层也是如此,并且这里的地图类型分为3种,Lawn Water Stone 即草地 水面 石面,由于在外部文件中保存的这些是字符串,所以还要有一个转换,这个转换目前在TerrainMaker中进行,至于以后要不要再增加其他的类型,则是以后扩展使用了,比如你可以加个沙漠类型的图,上面只能种仙人掌,其他的植物只能种在花盆上。
在生成Terrain对象的时候,要设置
1 地形类型
2 位置
3 尺寸大小
4 当前是否可以种植()
这三个是必选的,需要注意的是,这里的Terrain继承自Entity,也就是说,它是可以显示图形的,而地形显示图形的目前仅一种,就是被毁灭菇炸后留下的坑,这个是草地所特有的,不过也没必要特地再创建一个子类,在被毁灭菇炸坏后可以设置一个动画,只不过这个动画特别长,每隔一段不短的时间会换帧,在动画结束时就可以设置地形状态可种植,不过需要注意的是,当前的地形的精灵是空的,所以无法运行动画,这难不倒我,先从AnimationCache获取到对应动画,然后获取该动画的第一SpriteFrame,然后内部精灵通过createWithSpriteFrame创建就可以了,还有一个需要注意的,由于使用的是组合,所以得设置两个动作,一个为动画,另一个为DelayTime和CallFunc的组合动作,上面那个交给内部精灵,组合动作交给地形类,各司其职
相关文章推荐
- cocos2dx 植物大战僵尸 2 创建卡片层
- cocos2dx 植物大战僵尸 19 读报僵尸
- cocos2dx 植物大战僵尸 17 路障僵尸
- cocos2dx 植物大战僵尸 21 塔基的更新
- cocos2dx 植物大战僵尸 13 僵尸的产生
- cocos2dx 植物大战僵尸 5 塔基Terrain的更新
- cocos2dx 植物大战僵尸 14 僵尸的攻击
- cocos2dx 植物大战僵尸 6 植物层
- cocos2dx 植物大战僵尸 11 场景自带的植物
- cocos2dx 植物大战僵尸 12 僵尸卡片
- cocos2dx 植物大战僵尸 20 卷心菜投手
- cocos2dx 植物大战僵尸 22 寒冰射手
- cocos2dx 植物大战僵尸 23 撑杆僵尸
- cocos2dx 植物大战僵尸 24 坚果和大坚果
- cocos2dx 植物大战僵尸 3 卡片
- cocos2dx 植物大战僵尸 9 容器植物类
- cocos2dx 植物大战僵尸 16 僵尸的行走死亡和攻击死亡
- cocos2dx 植物大战僵尸 4 太阳
- cocos2dx 植物大战僵尸 10 铲子的实现
- cocos2dx 植物大战僵尸 18 土豆雷