cocos2d-x大型地图的实现

来源:互联网 发布:mac免费翻墙教程 编辑:程序博客网 时间:2024/05/22 07:46

所谓大型地图,是指类似于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 cachepublic://部分成员部分暴露出来供绘制使用    //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图片上传炸了,伤感,下次补上)

0 0
原创粉丝点击