您的位置:首页 > 移动开发 > Cocos引擎

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图片上传炸了,伤感,下次补上)

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  游戏设计 地图 游戏