转载至: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,讲解如何在场景中添加敌人。