main.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. #include "SpriteData.hpp"
  5. #include "ajson5.h"
  6. #include "contourdata.h"
  7. #include "LevelGenerate.hpp"
  8. #include "FillGlobalConfig.hpp"
  9. #include "RandomGridFiller.hpp"
  10. #include "BoostGeometryTools.hpp"
  11. #include <opencv2/core.hpp>
  12. #include <opencv2/imgproc.hpp>
  13. #include <opencv2/highgui.hpp>
  14. #include <sstream>
  15. #include <ctime>
  16. #include <chrono>
  17. using namespace ArduinoJson;
  18. using namespace std;
  19. bool writeLevelJson(vector<tuple<int,vector<vector<FillResult>>>>& resultPlateFillResults,
  20. vector<ContourData::Point>& resultPlateCenterPointArr,
  21. string outfilename);
  22. int getGidByFileName(JsonArray *jTileSets, FillGlobalConfig::PlateItem* plate);
  23. int main(int argc, const char * argv[]) {
  24. cout<<"A program to generate level. 2024-11-23"<<endl;
  25. cout<<"usage:auto_fill_jewel_v3"<<endl;
  26. cout<<"version v3.0"<<endl ;
  27. // if( argc!=2 ) {
  28. // cout<<"缺少参数"<<endl;
  29. // return 11 ;
  30. // }
  31. string outname = "测试关卡100.json" ;
  32. FillGlobalConfig::getInstance() ; //inited
  33. vector<tuple<int,vector<vector<FillResult>>>> resultPlateFillResults;
  34. vector<ContourData::Point> resultPlateCenterPointArr;
  35. LevelGenerate genv3 ;
  36. genv3.generate( *FillGlobalConfig::getInstance()->getLevelData(100, 0),
  37. resultPlateFillResults,
  38. resultPlateCenterPointArr
  39. ) ;
  40. cout<<"write result to "<<outname<<endl;
  41. writeLevelJson(resultPlateFillResults, resultPlateCenterPointArr, outname);
  42. // string levelCsvfilename = argv[1] ;
  43. // LevelInputConfig levelInputConfig ;
  44. // bool isok = levelInputConfig.readFromCsv(levelCsvfilename) ;
  45. // LevelGenerate genv3 ;
  46. // genv3.generate(levelInputConfig) ;
  47. if(false)
  48. {//测试6个大的
  49. const float BIG_JEW_WID = 80 ;
  50. vector<RandomGridFiller::JewelBox> jewBoxArray ;
  51. RandomGridFiller::JewelBox jb1,jb2 ;
  52. jb1._cnt = 3 ;
  53. jb1._height = BIG_JEW_WID ;
  54. jb1._width = BIG_JEW_WID*0.67;
  55. jb1._jewelTypeId = 1 ;
  56. jb2._cnt = 3*2 ;
  57. jb2._height = BIG_JEW_WID*0.75 ;
  58. jb2._width = BIG_JEW_WID*0.75 ;
  59. jb2._jewelTypeId = 2 ;
  60. jewBoxArray.push_back(jb1) ;
  61. jewBoxArray.push_back(jb2) ;
  62. auto ms0 = std::chrono::system_clock::now().time_since_epoch() ;
  63. uint64_t ms00 = std::chrono::duration_cast<chrono::milliseconds>(ms0).count() ;
  64. RandomGridFiller RBFiller ;
  65. RBFiller._seed = 5 ;
  66. vector< vector<FillResult> > results(1) ;
  67. RBFiller.fill(jewBoxArray, 5, 14 , 200, 265, results[0] ) ;
  68. auto ms1 = std::chrono::system_clock::now().time_since_epoch() ;
  69. uint64_t ms11 = std::chrono::duration_cast<chrono::milliseconds>(ms1).count() ;
  70. cout<<"duration(ms) "<<ms11-ms00<<endl;
  71. for(int ires = 0 ;ires < results.size();++ ires ) {
  72. cv::Mat plateimage = cv::Mat::zeros( 270, 210, CV_8UC3 );
  73. for(int ibox = 0 ; ibox < results[ires].size(); ++ ibox ) {
  74. FillResult& fr = results[ires][ibox] ;
  75. BoostGeometryTools::BoostPolygon poly1 = BoostGeometryTools::makeRotateNTranslateBox(-fr._width/2, -fr._height/2, fr._width, fr._height, results[ires][ibox]._rotdeg, results[ires][ibox]._x, results[ires][ibox]._y) ;
  76. vector<cv::Point> cvpoints ;
  77. for(int ipt = 0 ;ipt < poly1.outer().size();++ ipt ) {
  78. cv::Point p2 ;
  79. p2.x = poly1.outer()[ipt].get<0>();
  80. p2.y = poly1.outer()[ipt].get<1>() ;
  81. cvpoints.push_back(p2) ;
  82. }
  83. cv::polylines(plateimage, cvpoints, true, cv::Scalar(rand()%255,rand()%255,rand()%255));
  84. }
  85. //
  86. stringstream ss ;
  87. ss<<"win"<<ires ;
  88. cv::imshow( ss.str().c_str() , plateimage );
  89. }
  90. cv::waitKey();
  91. }
  92. return 0;
  93. }
  94. int getGidByFileName(JsonArray &jTileSets, FillGlobalConfig::PlateItem* plate) {
  95. static int gid = 0;
  96. for (int i = 0; i < jTileSets.size(); i++){
  97. if (jTileSets[i]["image"] == plate->_pngName){
  98. return static_cast<int>(jTileSets[i]["firstgid"]);
  99. }
  100. }
  101. gid ++;
  102. JsonObject& obj = jTileSets.createNestedObject();
  103. obj["firstgid"] = gid;
  104. obj["image"] = plate->_pngName;
  105. obj["imageheight"] = plate->_bbhei;
  106. obj["imagewidth"] = plate->_bbwid;
  107. obj["margin"] = 0;
  108. obj["name"] = plate->_name;
  109. obj.createNestedObject("properties");
  110. obj["spacing"] = 0;
  111. obj["tileheight"] = plate->_bbhei;
  112. obj["tilewidth"] = plate->_bbwid;
  113. return gid;
  114. }
  115. bool writeLevelJson(vector<tuple<int,vector<vector<FillResult>>>>& resultPlateFillResults,
  116. vector<ContourData::Point>& resultPlateCenterPointArr,
  117. string outfilename)
  118. {
  119. auto fgc = FillGlobalConfig::getInstance() ;
  120. int totalJewelCnt = 0 ;
  121. for(auto itp = resultPlateFillResults.begin();itp!=resultPlateFillResults.end();++itp) {
  122. int plateId = std::get<0>( *itp ) ;
  123. vector<vector<FillResult>>& frArr = std::get<1>( *itp );
  124. for(auto itfr = frArr.begin(); itfr!=frArr.end();++itfr ) {
  125. totalJewelCnt+=itfr->size() ;
  126. }
  127. }
  128. DynamicJsonBuffer jsonBufferTiled;
  129. DynamicJsonBuffer jsonBuffer;
  130. JsonObject& tiledRoot = jsonBufferTiled.createObject();
  131. JsonObject& root = jsonBuffer.createObject();
  132. tiledRoot["height"] = 18;
  133. JsonArray& jLayerArr = tiledRoot.createNestedArray("layers");
  134. JsonObject& lyrObj = jLayerArr.createNestedObject();
  135. lyrObj["draworder"] = "topdown";
  136. lyrObj["height"] = 18;
  137. lyrObj["name"] = "Layer";
  138. JsonArray& jObjArr = lyrObj.createNestedArray("objects"); //盘子信息
  139. lyrObj["opacity"] = 1;
  140. lyrObj["type"] = "objectgroup";
  141. lyrObj["visible"] = true;
  142. lyrObj["width"] = 16;
  143. lyrObj["x"] = 0;
  144. lyrObj["y"] = 0;
  145. tiledRoot["nextobjectid"] = 4;
  146. tiledRoot["orientation"] = "orthogonal";
  147. tiledRoot.createNestedArray("properties");
  148. tiledRoot["renderorder"] = "right-down";
  149. tiledRoot["tileheight"] = 40;
  150. JsonArray& jTileSets = tiledRoot.createNestedArray("tilesets"); //盘子纹理图
  151. tiledRoot["tilewidth"] = 40;
  152. tiledRoot["version"] = 1;
  153. tiledRoot["width"] = 16;
  154. root.createNestedObject("target");//not used.
  155. root["bgtem"] = "no"; //背景redream文件
  156. root["jewel_count"] = totalJewelCnt ;
  157. JsonArray& jplatesArr = root.createNestedArray("plates");
  158. int ids = 1;
  159. for (int i = 0; i < resultPlateFillResults.size(); i ++){
  160. auto itp = resultPlateFillResults.begin() ;
  161. std::advance(itp, i) ;
  162. int plateId = std::get<0>( *itp ) ;
  163. JsonObject& tiledPlateObj = jObjArr.createNestedObject();
  164. tiledPlateObj["gid"] = getGidByFileName(jTileSets, fgc->getPlateItemById(plateId));
  165. tiledPlateObj["height"] = 0;
  166. tiledPlateObj["id"] = ids;
  167. tiledPlateObj["name"] = "plate";
  168. tiledPlateObj.createNestedObject("properties");
  169. tiledPlateObj["rotation"] = 0;
  170. tiledPlateObj["type"] = "";
  171. tiledPlateObj["visible"] = true;
  172. tiledPlateObj["width"] = 0;
  173. float platex = resultPlateCenterPointArr[i].x;
  174. float platey = resultPlateCenterPointArr[i].y;
  175. tiledPlateObj["x"] = platex - fgc->getPlateItemById(plateId)->_bbwid / 2;
  176. tiledPlateObj["y"] = platey - fgc->getPlateItemById(plateId)->_bbhei / 2;
  177. vector<vector<FillResult>>& frArr = std::get<1>( *itp );
  178. JsonObject& plateObj = jplatesArr.createNestedObject();
  179. plateObj["typeId"] = plateId ;
  180. plateObj["plateId"] = ids++;
  181. plateObj["x"] = platex;
  182. plateObj["y"] = platey;
  183. plateObj["sprite_frame_name"] = fgc->getPlateItemById(plateId)->_pngName;
  184. plateObj["sizeX"] = fgc->getPlateItemById(plateId)->_bbwid;
  185. plateObj["sizeY"] = fgc->getPlateItemById(plateId)->_bbhei;
  186. JsonArray& layerArr = plateObj.createNestedArray("layers");
  187. for(int il = 0 ; il < frArr.size() ; ++il ) {
  188. vector<FillResult>& frs = frArr[il];
  189. JsonObject& lyrObj = layerArr.createNestedObject();
  190. lyrObj["rotate"] = 0.0;
  191. lyrObj["scale_x"] = 1.0;
  192. lyrObj["scale_y"] = 1.0;
  193. lyrObj["scale"] = 1.0;
  194. lyrObj["sprite_frame_name"] = fgc->getPlateItemById(plateId)->_pngName;
  195. lyrObj["lyrId"] = ids++;
  196. lyrObj["zorder"] = il+1;
  197. JsonArray& posArr = lyrObj.createNestedArray("position");
  198. posArr.add(platex);
  199. posArr.add(platey);
  200. JsonArray& screwArr = lyrObj.createNestedArray("screws");
  201. for(int ij = 0 ;ij < frs.size();++ ij ) {
  202. FillResult& fr = frs[ij];
  203. FillGlobalConfig::JewelItem* jewPtr = fgc->getJewelItemById(fr._jewelTypeId);
  204. if( fr._jewelTypeId>=0 ) { // -1 is removed.
  205. JsonObject& jobj = screwArr.createNestedObject();
  206. jobj["rotate"] = fr._rotdeg;
  207. jobj["scale_x"] = jewPtr->_scale;
  208. jobj["scale_y"] = jewPtr->_scale;
  209. jobj["csx"] = 0;
  210. jobj["csy"] = 0;
  211. jobj["scale"] = jewPtr->_scale;
  212. jobj["sprite_frame_name"] = jewPtr->_pngName;
  213. jobj["screwId"] = ids++;
  214. jobj["typeId"] = fr._jewelTypeId ;
  215. JsonArray& posArr2 = jobj.createNestedArray("position");
  216. posArr2.add( fr._x ); // 钉子中心在游戏区域的坐标(原点左下角)
  217. posArr2.add( fr._y );
  218. }
  219. }
  220. }
  221. }
  222. string jsonText ;
  223. root.printTo(jsonText);
  224. ofstream ofs( outfilename.c_str() );
  225. if( ofs.good()==false ) return false;
  226. ofs<<jsonText;
  227. jsonText.clear();
  228. tiledRoot.printTo(jsonText);
  229. outfilename.insert(outfilename.size() - 5, "Tiled");
  230. ofstream ofsTiled( outfilename.c_str() );
  231. if( ofsTiled.good()==false ) return false;
  232. ofsTiled<<jsonText;
  233. return true;
  234. }