cocos2d-x大型地图的实现
2015-11-23 15:33
357 查看
所谓大型地图,是指类似于pc端沙盒游戏那样的地图。需要加载大量的图片资源。而cocos并不是针对这样的游戏设计(现目前手机端很少有2d的类似游戏)。
笔者最近再开发一款类似《饥荒》的生存类游戏,所以涉及到大型地图的实现,下面来和大家聊一聊我自己的实现方式。
· 首先是底层地图实体的逻辑,要实现物体的碰撞,我使用了方格数组来储存地图的相应信息:
struct MapRect { LandType landType_ = DRY_LAND; short int positionX_ = 0; short int positionY_ = 0; };
底层的数据结构要越简单越好,因为要大量的使用.
· 然后是地图上面的实体,在我设计的游戏中有entity和land两种,entity是人为定义的碰撞体积,而land是不规则的图片,我用了像素检测来判断它的边缘,并且存入底层的方格数组中:
class VirtualMap { public: VirtualMap(); ~VirtualMap(); public://inlitialize map data bool recordData();//将地图数据存入文件 bool loadData();//from xml;to be done bool loadLandIndex();//from Imgs bool loadPlantIndex();//from plant.xml bool setCache();//set Map sprite cache public://部分成员部分暴露出来供绘制使用 //map data MapRect _landIndex[401][401];//地图网格的数据 SimpleArray<Land*, MAX_LAND_NUMBER> _land; //entities data Vector<Animals*> _animal; Vector<Plants*> _plants; Vector<Products*> _droppedOutProducts; protected://handle imgs int getAlpha(Point, Image*);//图片上的位置和图片在地图上的位置 };
部分函数将数据内容存入本地文件,这样地图加载,例如像素检测功能只需要在游戏第一次启动时执行就行
(SimpleArray是自己设计的数据结构,线程安全的动态数组,此处不表)
· 函数的实现,此处用了rapidxml解析本地的xml文件
#include"VirtualMap.h" VirtualMap::VirtualMap() :_land(NullLand::create()) { for (int i = 0; i < 20; i++) { _land[i] = NullLand::create(); } } VirtualMap::~VirtualMap() { } bool VirtualMap::loadLandIndex() { //加载地图数据 rapidxml::xml_document<> doc_; rapidxml::file<> docl_(FileUtils::getInstance()->fullPathForFilename("land.xml").c_str()); doc_.parse<0>(docl_.data()); if (!doc_.first_node()) { log("ERROR_LAND_XML_NULL"); return false; } else { rapidxml::xml_node<>* node_root = doc_.first_node("ROOT");//获取根节点 rapidxml::xml_node<>* node_land_first = node_root->first_node("land");//指向第一个元素 int count = 0; while (node_land_first) { auto land = new Land(DRY_LAND); rapidxml::xml_node<>* first_sibling = node_land_first->first_node("landType"); land->_landType = (LandType)atoi(first_sibling->value());//字符串转换int first_sibling = first_sibling->next_sibling("positionX"); land->_imgPosition.x = atoi(first_sibling->value()); first_sibling = first_sibling->next_sibling("positionY"); land->_imgPosition.y = atoi(first_sibling->value()); first_sibling = first_sibling->next_sibling("sprite"); land->_imgName = first_sibling->value(); first_sibling = first_sibling->next_sibling("width"); land->_contentSize.x = atoi(first_sibling->value()); first_sibling = first_sibling->next_sibling("height"); land->_contentSize.y = atoi(first_sibling->value()); //end _land.push(land); count++; node_land_first = node_land_first->next_sibling("land"); //移动指针到下一个节点 } } //加载完毕 //处理像素信息 int count = 0; while (_land[count]->_imgName != NullLand::create()->_imgName) { auto img = new Image; auto path = FileUtils::getInstance()->fullPathForFilename("land_0.png"); img->initWithImageFile(path); int w = _land[count]->_contentSize.x / RECT_SIZE; int h = _land[count]->_contentSize.y / RECT_SIZE; int x = _land[count]->_imgPosition.x / RECT_SIZE; int y = _land[count]->_imgPosition.y / RECT_SIZE; for (int a = 0; a < w; a++) { for (int b = 0; b < h; b++) { if (getAlpha(Point(a*RECT_SIZE, b*RECT_SIZE),img)>0)//>20则为图片非透明内容 { _landIndex[a+x][b+y].landType_ = _land[count]->_landType; } } } count++; } return true; } bool VirtualMap::loadPlantIndex() { rapidxml::xml_document<> doc_; rapidxml::file<> docl_(FileUtils::getInstance()->fullPathForFilename("plant.xml").c_str()); doc_.parse<0>(docl_.data()); if (!doc_.first_node()) { log("ERROR_LAND_XML_NULL"); return false; } else { rapidxml::xml_node<>* node_root = doc_.first_node("ROOT");//获取根节点 rapidxml::xml_node<>* node_land_first = node_root->first_node("plant");//指向第一个元素 int count = 0; while (node_land_first) { rapidxml::xml_node<>* first_sibling = node_land_first->first_node("plantType"); auto pp = Plants::create((PlantType)atoi(first_sibling->value()));//字符串转换int first_sibling = first_sibling->next_sibling("positionX"); pp->ActiveEntity::getPosition().x = atoi(first_sibling->value())/RECT_SIZE; first_sibling = first_sibling->next_sibling("positionY"); pp->ActiveEntity::getPosition().y = atoi(first_sibling->value()) / RECT_SIZE; _plants.pushBack(pp); count++; node_land_first = node_land_first->next_sibling("plant"); //移动指针到下一个节点 } } return true; } int VirtualMap::getAlpha(Point position,Image* img) { position.x += 5; position.y += 5; unsigned char* imgPixelData_ = img->getData(); int w = img->getWidth(); int h = img->getHeight(); int pa = (((h - position.y) - 1)*w + position.x) * 4 + 3; unsigned int alpha = imgPixelData_[pa]; return alpha; } bool VirtualMap::setCache() { return true; }
关于像素检测,我做了小小的测试,可以看到地图上的渲染图(CSDN图片上传炸了,伤感,下次补上)
相关文章推荐
- 我是运营,我没有假期
- 每个 Linux 游戏玩家都绝不想要的恼人体验
- 在 Fedora 上使用 Steam play 和 Proton 来玩 Windows 游戏
- Steam 让我们在 Linux 上玩 Windows 的游戏更加容易
- 如何使用 Steam Play 在 Linux 上玩仅限 Windows 的游戏
- 新一代iPad适配应用之游戏篇
- VB实现的《QQ美女找茬游戏》作弊器实例
- C#实现洗牌游戏实例
- C#实现的算24点游戏算法实例分析
- C#实现简单的井字游戏实例
- C++编写简单的打靶游戏
- C++实现基于控制台界面的吃豆子游戏
- 百度地图经纬度转换到腾讯地图/Google 对应的经纬度
- 纯javascript实现的小游戏《Flappy Pig》实例
- JavaScript实现俄罗斯方块游戏过程分析及源码分享
- JS小游戏之仙剑翻牌源码详解
- JS小游戏之宇宙战机源码详解
- Android基本游戏循环实例分析
- JavaScript游戏之优化篇
- js实现俄罗斯方块小游戏分享