以前的代碼中并有設定行數這個概念,但是植物大戰僵屍這個遊戲裡确實是有一個概念的,那怎麼設定行數呢?個人認為,每一行都有一個僵屍的行走路徑,并且路徑之間是不交叉的,那麼我們就可以先生成路徑,然後在生成terrain的時候檢測目前和那個路徑發生了碰撞,如果發生碰撞,就擷取這個折線的所在行數,傳遞給terrain,然後把terrain添加到對應的容器中 這個行數是跟植物的攻擊方式有關的,植物的攻擊方式有以下幾種(不考慮玉米加農炮) 1.植物所在行有僵屍就攻擊 豌豆類植物 膽小噴菇 仙人掌等 2植物所在行有僵屍,且需要擷取第一個僵屍的位置 卷心菜 玉米 西瓜 3感應區域内有僵屍,就進行攻擊 大小噴菇 楊桃 憂郁蘑菇 貓尾草 洋芋雷 4定時攻擊 櫻桃炸彈 火爆辣椒等 因為 有的植物(如豌豆類)攻擊需要根據目前所在行數,擷取所在行的僵屍,是以需要行數這個概念。 是以我在tmx添加一個對象層,為zombie path
這個是折線
并且内部有一個屬性,表示目前第幾行
然後在LevelLayer中讀取并解析
void LevelLayer::loadZombiePath()
{
auto groupGroup = m_pTiledMap->getObjectGroup("zombie path");
auto &objects = groupGroup->getObjects();
//對對象進行解析,cocos2dx的對象是Value,是以需要按照一定格式解析
for (const auto& object : objects)
{
ZombiePath*zombiePath = new ZombiePath();
const auto &dict = object.asValueMap();
auto x = dict.at("x").asInt();
auto y = dict.at("y").asInt();
auto properties = dict.at("properties").asValueMap();
auto points = dict.at("polyline").asValueVector();
for (const auto& dict : points)
{
const auto&point = dict.asValueMap();
auto realX = x + point.at("x").asInt();
auto realY = y + point.at("y").asInt();
zombiePath->points.push_back(Point(realX,realY));
}
zombiePath->row = properties.at("row").asInt();
m_zombiePathVec.push_back(zombiePath);
}
}
更改terrain的存儲方式為 map<int,vector<Terrain*>> m_terrains,每一行儲存一行的塔基terrain
void LevelLayer::makeTerrainCallback(Terrain*terrain)
{
//檢測該地形在第幾行
auto rect = terrain->getBoundingBox();
for (auto zombiePath : m_zombiePathVec)
{
const auto& points = zombiePath->points;
auto row = zombiePath->row;
for (int i = 0;i < points.size() - 1;i++)
{
auto pos1 = points.at(i);
auto pos2 = points.at(i + 1);
if (rect.intersectLine(pos1,pos2))
{
m_terrains[row].push_back(terrain);
//添加到實體層
auto layer = this->getEntityLayer();
layer->addChild(terrain);
}
}
}
}
這個函數是先擷取目前的塔基的包圍盒,然後再和目前的行走路徑判斷,如果相交,則表示此行即為塔基所在的行, 至于那個intersectLine,這個不是cocos2dx的函數,是我自己加上的,因為SDL有着對應的實作,為SDL_IntersectRectAndLine()
這些都是為了以後的植物所做的準備。。。下一節也是如此