#include #include #include #include "framework/cpp/tiledmap.h" namespace f8 { a8::XValue TiledObject::GetProperty(const std::string& prop_name) { auto itr = prop_hash.find(prop_name); return itr != prop_hash.end() ? itr->second : a8::XValue(); } bool TiledObject::HasProperty(const std::string& prop_name) { auto itr = prop_hash.find(prop_name); return itr != prop_hash.end(); } a8::XValue TiledLayer::GetProperty(const std::string& prop_name) { auto itr = prop_hash.find(prop_name); return itr != prop_hash.end() ? itr->second : a8::XValue(); } bool TiledLayer::HasProperty(const std::string& prop_name) { auto itr = prop_hash.find(prop_name); return itr != prop_hash.end(); } bool TiledMap::LoadTmxFile(const std::string& filename) { a8::XObject xobj; if (!xobj.ReadFromXmlFile(filename)) { return false; } std::shared_ptr tileset_node = xobj.At("child_node.tileset")->At(0); tile_width = tileset_node->At("attrs.tilewidth")->AsXValue(); tile_height = tileset_node->At("attrs.tileheight")->AsXValue(); #if 0 tile_count = tileset_node->At("attrs.tilecount")->AsXValue(); tile_columns = tileset_node->At("attrs.columns")->AsXValue(); tile_rows = tile_count/tile_columns + 1; tile_columns += 1; tile_count = tile_rows * tile_columns; #endif for (int i = 0; i < xobj.At("child_node.layer")->Size(); ++i) { std::shared_ptr layer_node = xobj.At("child_node.layer")->At(i); TiledLayer layer; { for (int ii = 0; ii < layer_node->At("attr_names")->Size(); ++ii) { std::string attr_name = layer_node->At("attr_names")->At(ii)->AsXValue(); layer.prop_hash[attr_name] = layer_node->At("attrs." + attr_name)->AsXValue(); } std::shared_ptr prop_nodes = layer_node->At("child_node.properties")->At(0)->At("child_node.property"); for (int j = 0; j < prop_nodes->Size(); ++j) { std::shared_ptr prop_node = prop_nodes->At(j); layer.prop_hash[prop_node->At("attrs.name")->AsXValue()] = prop_node->At("attrs.value")->AsXValue(); } std::shared_ptr data_node = layer_node->At("child_node.data")->At(0); layer.data = data_node->At("node_value")->AsXValue(); } std::string layer_name = layer_node->At("attrs.name")->AsXValue(); if (layer_name.compare("ground") == 0) { tile_columns = layer_node->At("attrs.width")->AsXValue(); tile_rows = layer_node->At("attrs.height")->AsXValue(); tile_count = tile_rows * tile_columns; } auto itr = layer_hash.find(layer_name); if (itr != layer_hash.end()) { itr->second.push_back(layer); } else { layer_hash[layer_name] = std::list({layer}); } } for (int group_id = 0; group_id < xobj.At("child_node.objectgroup")->Size(); group_id++) { std::shared_ptr objgroup_node = xobj.At("child_node.objectgroup")->At(group_id); for (int i = 0; i < objgroup_node->At("child_node.object")->Size(); i++) { std::shared_ptr object_node = objgroup_node->At("child_node.object")->At(i); TiledObject object; { for (int ii = 0; ii < object_node->At("attr_names")->Size(); ii++) { std::string attr_name = object_node->At("attr_names")->At(ii)->AsXValue(); object.prop_hash[attr_name] = object_node->At("attrs." + attr_name)->AsXValue(); } std::shared_ptr prop_nodes = object_node->At("child_node.properties")->At(0)->At("child_node.property"); for (int j = 0; j < prop_nodes->Size(); j++) { std::shared_ptr prop_node = prop_nodes->At(j); object.prop_hash[prop_node->At("attrs.name")->AsXValue()] = prop_node->At("attrs.value")->AsXValue(); } } std::string object_name = object_node->At("attrs.name")->AsXValue(); auto itr = object_group_hash.find(object_name); if (itr != object_group_hash.end()) { itr->second.push_back(object); } else { object_group_hash[object_name] = std::list({ object }); } } } return true; } std::list* TiledMap::GetObjectGroup(const std::string& object_class_name) { auto itr = object_group_hash.find(object_class_name); return itr != object_group_hash.end() ? &itr->second : nullptr; } StagePoint* TiledMap::GetStageObject(int point) { auto itr = stage_object_hash.find(point); return itr != stage_object_hash.end() ? &itr->second : nullptr; } bool TiledMap::HasStageObject(int point) { auto itr = stage_object_hash.find(point); return itr != stage_object_hash.end(); } std::vector* TiledMap::GetStagePath(const std::string& path_name) { auto itr = stage_path_hash.find(path_name); return itr != stage_path_hash.end() ? &itr->second : nullptr; } bool TiledMap::HasStagePath(const std::string& path_name) { auto itr = stage_path_hash.find(path_name); return itr != stage_path_hash.end(); } void TiledMap::Init() { grid_cell_list.reserve(tile_count); grid_cell_list.assign(tile_count,GridCell{}); for (auto& pair : layer_hash) { for (auto& layer : pair.second) { std::string name = layer.GetProperty("name").GetString(); bool has_speed = layer.HasProperty("area_id"); int speed = layer.GetProperty("area_id"); bool has_trigger = layer.HasProperty("isTrigger"); bool istrigger = layer.GetProperty("isTrigger");; int trigger_point = layer.GetProperty("objName"); bool has_num = layer.HasProperty("num"); //int num = layer.GetProperty("num"); std::vector grid_cell_path_list; a8::StringList str_list; str_list.SetText(layer.data.GetString().c_str()); for (int i = 1; i < str_list.Count(); ++i) { std::string str_line = str_list.String(i); std::vector split_list; a8::Split(str_line, split_list); int split_count = split_list.size(); for(int j = 0; j < split_count; ++j){ int value = a8::XValue(split_list[j]); if(value > 0){ int index = (i-1)*tile_columns + j; if (has_speed) { grid_cell_list[index].x = j; grid_cell_list[index].y = i-1; grid_cell_list[index].speed = speed; grid_cell_list[index].value = value; } if (has_trigger) { TriggerPoint tp; { tp.x = j; tp.y = i-1; tp.point = trigger_point; tp.istrigger = istrigger; trigger_list.push_back(tp); } } if (has_num) { grid_cell_path_list.push_back(&grid_cell_list[index]); } } } } if (grid_cell_path_list.size() > 0) { stage_path_hash[name] = grid_cell_path_list; } } } for (auto& pair : object_group_hash) { for (auto& object : pair.second) { StagePoint sp; sp.x = object.GetProperty("tile_x"); sp.y = object.GetProperty("tile_y"); sp.point = object.GetProperty("name"); std::string str_relation = object.GetProperty("relation").GetString(); std::vector split_list; a8::Split(str_relation, split_list, ','); for (auto& point : split_list) { sp.relation_list.push_back(a8::XValue(point)); } int point = object.GetProperty("name"); stage_object_hash[point] = sp; } } } void TiledMap::Dump() { Init(); #if 0 for (auto& pair : stage_path_hash) { a8::XPrintf("stage$:%s\n", {pair.first}); for (auto& gc : pair.second) { a8::XPrintf("path$x:%d,y:%d,speed:%d,value:%d\n", {gc->x, gc->y, gc->speed, gc->value}); } } #endif #if 0 for (auto& tp : trigger_list) { a8::XPrintf("x:%d,y:%d,point:%d,istrigger:%d\n", {tp.x, tp.y, tp.point, a8::XValue(tp.istrigger)}); } #endif #if 0 int len = grid_cell_list.size(); a8::XPrintf("grid_cell_size:%s\n", {len}); for (int i= 0; i < len; ++i) { auto gc = grid_cell_list[i]; a8::XPrintf("i:%d, x:%d,y:%d,speed:%d,value:%d\n", {i, gc.x, gc.y, gc.speed, gc.value}); } #endif #if 0 for (auto& pair : stage_object_hash) { a8::XPrintf("object$:%s\n", {pair.first}); a8::XPrintf("value$x:%d,y:%d,p:%s,relation:", {pair.second.x, pair.second.y, pair.second.point}); for (auto& relation : pair.second.relation_list) { a8::XPrintf("%s,", {relation}); } a8::XPrintf("\n",{}); } #endif return; a8::XPrintf("map$tile_count:%d\n", {tile_count}); a8::XPrintf("map$tile_width:%d\n", { tile_width }); a8::XPrintf("map$tile_height:%d\n", { tile_height }); a8::XPrintf("layer$layer_hash.size:%d\n", {layer_hash.size()}); for (auto& pair : layer_hash) { a8::XPrintf(" layer$layer_type:%s\n", {pair.first}); for (auto& layer : pair.second) { a8::XPrintf("data$data:%s\n",{layer.data}); for (auto& pair2 : layer.prop_hash) { a8::XPrintf(" layer$%s:%s\n", {pair2.first, pair2.second}); } } } a8::XPrintf("object$object_group_hash.size:%d\n", {object_group_hash.size()}); for (auto& pair : object_group_hash) { a8::XPrintf(" object$layer_type:%s\n", {pair.first}); for (auto& layer : pair.second) { for (auto& pair2 : layer.prop_hash) { a8::XPrintf(" object$%s:%s\n", {pair2.first, pair2.second}); } } } } bool TiledMap::CalcCurrPos(std::vector& path_points, int old_pos_x, int old_pos_y, int time_ms, int& curr_pos_x, int& curr_pos_y) { if (path_points.size() < 2) { return false; } StagePoint* sp_terminal = GetStageObject(path_points[path_points.size()-1]); if (sp_terminal) { if (old_pos_x == sp_terminal->x && old_pos_y == sp_terminal->y) { curr_pos_x = old_pos_x; curr_pos_y = old_pos_y; return true; } //报错放终点 curr_pos_x = sp_terminal->x; curr_pos_y = sp_terminal->y; } std::vector stage_path_list; { std::string path_point; bool path_start = true; for (auto& point : path_points) { if (path_start) { path_point = a8::XValue(point).GetString(); path_start = !path_start; } else { std::string point_str = a8::XValue(point).GetString(); path_point += "-" + point_str; stage_path_list.push_back(path_point); path_point = point_str; } } } std::vector grid_all_list; { bool exc_once = true; for (auto& stage_path : stage_path_list) { std::vector* grid_list = nullptr; std::string stage_path_reverse; std::vector split_list; a8::Split(stage_path,split_list,'-'); if (split_list.size() != 2) { return false; } StagePoint* sp = GetStageObject(a8::XValue(split_list.at(0))); if (sp == nullptr) { return false; } grid_list = GetStagePath(stage_path); if (grid_list == nullptr) { stage_path_reverse = split_list[1] + "-" + split_list[0]; grid_list = GetStagePath(stage_path_reverse); if (grid_list == nullptr) { return false; } } std::vector grid_sort_list = SortGridList(grid_list,sp); if (grid_sort_list.size() < 2) { return false; } if (exc_once) { grid_all_list.insert(grid_all_list.end(),grid_sort_list.begin(),grid_sort_list.end()); exc_once = false; } else { grid_all_list.insert(grid_all_list.end(),grid_sort_list.begin()+1,grid_sort_list.end()); } } } if (grid_all_list.empty()) { return false; } { bool has_index = false; int index = 0; for (auto& gc : grid_all_list) { if (gc->x == old_pos_x && gc->y == old_pos_y) { has_index = true; break; } index++; } if (!has_index) { return false; } int grid_all_count = grid_all_list.size(); for (int i = index; i < grid_all_count-1; ++i) { GridCell* gc_first = grid_all_list[i]; GridCell* gc_second = grid_all_list[i+1]; int speed = gc_first->speed; int time_use = 0; if (gc_second->x == gc_first->x) { time_use = a8::XValue((((float)tile_height / speed)*1000)); } else if (gc_second->y == gc_first->y) { time_use = a8::XValue((((float)tile_width / speed)*1000)); } else { float width_pow = std::pow(tile_width,2.0); float height_pow = std::pow(tile_height,2.0); float value_sqrt = std::sqrt(width_pow+height_pow); time_use = a8::XValue(((value_sqrt / speed)*1000)); } time_ms -= time_use; curr_pos_x = gc_second->x; curr_pos_y = gc_second->y; if (time_ms < 0) { return true; } } } if (time_ms > 0) { return true; } return false; } std::vector TiledMap::SortGridList(std::vector* grid_list, StagePoint* sp) { std::vector grid_sort_list; std::map grid_tag_hash; int grid_list_count = grid_list->size(); int old_x = 0; int old_y = 0; for (auto& gc : *grid_list) { grid_tag_hash[gc] = false; } for (auto& gc : *grid_list) { if (gc->x == sp->x && gc->y == sp->y) { grid_sort_list.push_back(gc); old_x = gc->x; old_y = gc->y; grid_tag_hash[gc] = true; } } for (int count = 1; count < grid_list_count; ++count) { GridCell* gc_next = nullptr; for (int i = 0; i < grid_list_count; ++i) { GridCell* gc = grid_list->at(i); for (int x = old_x-1; x <= old_x+1; ++x) { for(int y = old_y-1; y <= old_y+1; ++y) { if (gc->x == x && gc->y == y && !grid_tag_hash[gc]) { grid_tag_hash[gc] = true; gc_next = gc; old_x = gc->x; old_y = gc->y; break; } } if (gc_next != nullptr) { break; } } if (gc_next != nullptr) { break; } } if (gc_next != nullptr) { grid_sort_list.push_back(gc_next); } } return grid_sort_list; } void TiledMap::SetGridCellSpeedByAreaId(std::map& area_speed_hash) { for (auto& pair : stage_path_hash) { for (auto& grid_cell : pair.second) { auto itr = area_speed_hash.find(grid_cell->speed); if (itr != area_speed_hash.end()) { grid_cell->speed = itr->second; } } } } void TiledMap::LoadWayPointsData(const std::string& filename) { a8::XObject waypoints_json; if (!waypoints_json.ReadFromJsonFile(filename)) { abort(); return; } for (auto& pair : stage_object_hash) { int stage_id = pair.first; StagePoint& stage = pair.second; for (int relation_point : stage.relation_list) { std::string path_name = a8::Format("%d-%d", {stage_id, relation_point}); std::shared_ptr points_xobj = waypoints_json.At(path_name); if (!points_xobj) { path_name = a8::Format("%d-%d", {relation_point, stage_id}); points_xobj = waypoints_json.At(path_name); if (!points_xobj) { continue; // abort(); } } if (stage_path_hash.find(path_name) != stage_path_hash.end()) { continue; } stage_path_hash[path_name] = std::vector(); std::vector& path_points = stage_path_hash[path_name]; for (int i = 0; i < points_xobj->Size(); ++i) { int x = points_xobj->At(i)->At(0)->AsXValue(); int y = points_xobj->At(i)->At(1)->AsXValue(); int index = y*tile_columns + x; path_points.push_back(&grid_cell_list[index]); } } } } }