现在的位置: 首页 > 综合 > 正文

二、地图的创建

2017年12月28日 ⁄ 综合 ⁄ 共 3362字 ⁄ 字号 评论关闭

转载至:http://cn.cocos2d-x.org/tutorial/show?id=1147

继续上一章节的内容,主要实现地图的创建和加载。在创建地图时,我们会在其上标记出一些点来表示敌人的行进路线,同时会在程序中获取这些标示的路径点对象。在后续的文章中,敌人会一个一个的搜索这些路径点,并依次朝着搜索到的点移动。 

     

地图 

地图的创建

下面我们先来用地图编辑器制做一幅地图,你可以在地图上设置塔防游戏地形的布局,同时为敌人铺设一条行走的道路,让它有路可走。       

这里你可能会想:道路弯弯曲曲的,毫不规则,我怎么知道怎样让敌人沿着它走啦!——这的确是个令人困惑的问题。

     

不过不用担心,Tiled Map编辑器牛逼的功能就要派上用场了,它支持对象组(ObjectGroups)功能,我们可以在地图上创建一个对象层,用对象来标示敌人移动轨迹的途经点。如下图所示: 

     

创建一幅地图可分为两个步骤:   

1. 创建普通图层“bg”,它是我们的背景层,你可以根据自己的喜好,任意设置地图的布局。

2. 创建对象层“obj”,并添加对象。这里对象就是指图中的小矩形,用这些矩形对象就可以计算敌人的行进路线,它们记录了敌人们移动的顺序和位置坐标。也正因为如此,我们在添加这些对象时是不需要在乎其大小的,注意摆放位置和顺序就行了。这里我们可以为矩形对象添加属性名来标示它的顺序,从0开始,依次增加,Cocos2d-x会为我们创建ValueMap类型的结构来保存相关的数据。打开.txm文件,会更有利于你清楚的理解。如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
<objectgroup name="obj" width="48" height="27">  
<object name="0" x="333" y="861"/>  
<object name="1" x="339" y="497"/>  
<object name="2" x="727" y="494"/>  
<object name="3" x="726" y="306"/>  
<object name="4" x="427" y="303"/>  
<object name="5" x="436" y="54"/>  
<object name="6" x="1106" y="48"/>  
<object name="7" x="1097" y="588"/>  
<object name="8" x="821" y="597"/>  
<object name="9" x="803" y="815"/>  
<object name="10" x="458" y="815"/>  
</objectgroup>

     

加载地图到场景

创建好地图后,接下来我们需要把地图加载到场景中去,具体代码在PlayLayer的init方法中实现:

1
2
3
4
5
6
7
8
9
// 1  
map = TMXTiledMap::create("map1.tmx");  
// 2  
auto bgLayer = map->getLayer("bg");  
bgLayer->setAnchorPoint(Point(0.5f, 0.5f));  
bgLayer->setPosition(Point(winSize.width / 2 ,winSize.height / 2));  
// 3  
objects = map->getObjectGroup("obj");  
this->addChild(map, -1);

    1. 将TMX地图文件加载到游戏中需要用Cocos2dx提供的TMXTiledMap类,直接通过.txm文件就可以创建瓦片地图。

    2. Tiled Map编辑器中每一个Layer都可以用TMXLayer类表示,获取地图的层可以通过getLayer("层名")来得到。 

         

获取背景层以后,我们需要重新设置它的显示位置和锚点。因为按我们前面的分辨率适配方案来看,在默认情况下,如果把地图直接添加到场景中,地图会从屏幕的左下角为起点开始显示,超出屏幕的后半段部分将被裁剪,如下方左图所示状态。   

     

显然地,这是不合理的,地图应该位于屏幕正中,所以我们设置它的显示位置和锚点把它放在正中。另外,`winSize = Director::getInstance()->getWinSize(); 

     

3. 获取地图的对象组TMXObjectGroup通过getObjectGroup("层名")来得到。

     

获取路径点信息

PlayLayer中,我们定义了Node类型的Vector来保存从地图中获取的路径点,之所以用Node表示路径点,那是因为对于路径点这一概念而言,我们只需要知道它的坐标信息就可以了,它不需要有太多的功能,所以Node类型的对象足已。其定义为:`Vector<Node*> pointsVector;`

     

TMXObjectGroup对象objects中存放了我们需要的所有路径点信息,我们需要遍历objects中所有的对象,把相应的数据值取出来保存在向量pointsVector中。具体方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void PlayLayer::initPointsVector(float offX)  
{  
    Node *runOfPoint = NULL;  
// 1  
int count = 0;  
ValueMap point;  
point = objects->getObject(std::to_string(count));  
// 2  
while (point.begin()!= point.end())  
{  
// 3  
float x = point.at("x").asFloat();  
float y = point.at("y").asFloat();  
// 4  
runOfPoint = Node::create();   
runOfPoint->setPosition(Point(x - offX , y  ));  
this->pointsVector.pushBack(runOfPoint);  
count++;  
point = objects->getObject( std::to_string(count));  
}  
runOfPoint = NULL;  
}

      

理解这个方法非常重要,所以让我们一部分一部分代码来看。

1. 调用getObject("对象名")方法获取对象组中的对象,它将返回ValueMap类型的值。     

在TXM中,我们为每一个对象都取了名字,从0开始,按路径顺序依次加1,这里的count就标示了对象的名称。    

ValueMap的定义为:std::unordered_map<std::string, Value> ValueMap;它其实就是键-值对的集合,我们可使用键作为参数来获取某个属性的值。关于Vaule,请参考文章:Vaule

2. 遍历每一个对象;

3. 获取每个对象的X值,Y值;

4. 创建一个Node来保存路径点,并且设置它的坐标位置,然后把它加到pointsVector向量中去,方便以后查找。 

             

要注意的是,我们需要修正路径点的坐标值,瓦片地图的背景层我们已经放置到了屏幕正中,但对象层开始显示的位置依旧是从屏幕最左端开始,如果不修正就会造成如下所示的错位状况:

     

分辨率适配时,我们选择了FIXED_HEIGHT 模式作为分辨率适配模式,它会纵向放大地图以适应屏幕的高度,横向按原始宽高比放大,所以这里我们只需要修正X轴的坐标就可以了。为了和地图背景层位置保持一致,我们修正X轴坐标把它放在正中。如下图所示: 

X轴的偏差值offX为:(地图宽 - 屏幕宽)/2,即:`( map->getContentSize().width - winSize.width )/ 2; ` 

     

好了,到现在我们已经能成功的在场景中加载地图了,下一章中我们将会继续围绕第一部分demo,讲解如何在场景中添加敌人。

抱歉!评论已关闭.