// // main.cpp // auto_fill_jewel_v3 // // Created by Red on 2024/11/22. // /* 需求: 1.给定宝石种类和每类数量 2.程序随机给出5种盘子组合 3.关卡由多个盘子组成,每个盘子包含若干不同层,每层上面包含宝石。 4.宝石有大、中、小三个尺度,按面积算: 1大=2中=4小 5.盘子有大、小、迷你3种,其容量分别对应 6个大宝石,3个大宝石,1个大宝石。(确认没有中盘子) 6.每个关卡最大有9个大盘子。 7.盘子之间的层数差异在0-1个。迷你盘子数量可以很多,这个是不是需要人工控制后面再问吧。 8.盘子会移动,但是盘子间不会重叠。 9.大中小号盘子有横的有竖着的。 10.重叠区百分比可以从0.05到0.2,程序自行判断最优值。 11.宝石只提供 80x80的资源,对应大。如果有中和小,需要程序缩放(0.75,0.50)。大、中、小是不同的宝石各消各的。 */ #include #include #include #include "SpriteData.hpp" #include "ajson5.hpp" #include "contourdata.h" #include "LevelGenerate.hpp" #include "FillGlobalConfig.hpp" #include "RandomGridFiller.hpp" #include "BoostGeometryTools.hpp" #include #include #include #include #include #include #include #include //#include "LevelThumbTool.hpp" using namespace ArduinoJson; using namespace std; #include "levelinputdata.h" #include "levelextinputdata.h" #include "LevelOutputWriter.hpp" int main(int argc, const char * argv[]) { cout<<"A program to generate level. 2024-11-23"< resultPlateFillResults ; vector resultPlateCenterPointArr ; string errorStr ; bool genok = genv3.generate_v2(levelInputData, levelExtData, resultPlateFillResults, resultPlateCenterPointArr,errorStr); if( genok==false ) { cout<<"Error: "<>>>& result1,string& info ) { auto fgc = FillGlobalConfig::getInstance() ; int nbig=0; int nmid = 0 ; int nsml = 0 ; stringstream ss ; for(auto it = result1.begin(); it!= result1.end(); ++ it ) { int plateId = std::get<0>( *it ) ; vector>& layers = std::get<1>(*it); FillGlobalConfig::PlateItem* plate = fgc->getPlateItemById(plateId) ; if( plate->_size == FILLGLOBALCONFIG_PLATESIZE_LG ){ nbig++; ss<<"LG:"<_size==FILLGLOBALCONFIG_PLATESIZE_MD ){ nmid++; ss<<"MD:"<>>>& resultPlateFillResults, vector& resultPlateCenterPointArr, string outfilename) { auto fgc = FillGlobalConfig::getInstance() ; int totalJewelCnt = 0 ; for(auto itp = resultPlateFillResults.begin();itp!=resultPlateFillResults.end();++itp) { int plateId = std::get<0>( *itp ) ; vector>& frArr = std::get<1>( *itp ); for(auto itfr = frArr.begin(); itfr!=frArr.end();++itfr ) { totalJewelCnt+=itfr->size() ; } } DynamicJsonBuffer jsonBuffer; JsonObject& root = jsonBuffer.createObject() ; root.createNestedObject("target");//not used. root["bgtem"] = "no"; //背景redream文件 root["jewel_count"] = totalJewelCnt ; JsonArray& jplatesArr = root.createNestedArray("plates") ; int ids = 1 ; for(int ip = 0 ; ip < resultPlateFillResults.size() ; ++ ip ) { JsonObject& plateObj = jplatesArr.createNestedObject() ; auto itp = resultPlateFillResults.begin() ; std::advance(itp, ip) ; int plateId = std::get<0>( *itp ) ; vector>& frArr = std::get<1>( *itp ); float platex = resultPlateCenterPointArr[ip].x ; float platey = resultPlateCenterPointArr[ip].y ; plateObj["typeId"] = plateId ; plateObj["plateId"] = ids++ ; // plateObj[""] = plateObj["x"] = platex ; //这里是盘子中心在游戏区域的坐标(原点左下角) plateObj["y"] = platey ; plateObj["sprite_frame_name"] = fgc->getPlateItemById(plateId)->_pngName ; JsonArray& layerArr = plateObj.createNestedArray("layers") ; for(int il = 0 ; il < frArr.size() ; ++il ) { vector& frs = frArr[il] ; JsonObject& lyrObj = layerArr.createNestedObject() ; lyrObj["rotate"] = 0.0 ; lyrObj["scale_x"] = 1.0 ; lyrObj["scale_y"] = 1.0 ; lyrObj["scale"] = 1.0 ; lyrObj["sprite_frame_name"] = fgc->getPlateItemById(plateId)->_pngName ; lyrObj["lyrId"] = ids++ ; lyrObj["zorder"] = il+1 ; JsonArray& posArr = lyrObj.createNestedArray("position") ; posArr.add(platex) ; posArr.add(platey) ; JsonArray& screwArr = lyrObj.createNestedArray("screws") ; for(int ij = 0 ;ij < frs.size();++ ij ) { FillResult& fr = frs[ij] ; FillGlobalConfig::JewelItem* jewPtr = fgc->getJewelItemById(fr._jewelTypeId); if( fr._jewelTypeId>=0 ) { // -1 is removed. JsonObject& jobj = screwArr.createNestedObject(); jobj["rotate"] = fr._rotdeg ; jobj["scale_x"] = jewPtr->_scale ; jobj["scale_y"] = jewPtr->_scale ; jobj["csx"] = 0; jobj["csy"] = 0; jobj["scale"] = jewPtr->_scale ; jobj["sprite_frame_name"] = jewPtr->_pngName ; jobj["screwId"] = ids++ ; jobj["typeId"] = fr._jewelTypeId ; JsonArray& posArr2 = jobj.createNestedArray("position") ; posArr2.add( fr._x) ; // 钉子中心在盘子内部的坐标(原点左下角) posArr2.add( fr._y) ; } } } } string jsonText ; root.printTo(jsonText); ofstream ofs( outfilename.c_str() ); if( ofs.good()==false ) return false; ofs<getPlateItemById( std::get<0>(*itPlate) ) ; vector>& layersArr = std::get<1>(*itPlate); cv::Mat plateimage = cv::Mat::zeros( platePtr->_bbwid, platePtr->_bbhei , CV_8UC3 ); for(int ibox = 0 ; ibox < layersArr[ilayer].size() ; ++ ibox ) { FillResult& fr = layersArr[ilayer][ibox] ; BoostGeometryTools::BoostPolygon poly1 = BoostGeometryTools::makeRotateNTranslateBox(-fr._width/2, -fr._height/2, fr._width, fr._height, fr._rotdeg, fr._x, fr._y) ; vector cvpoints ; for(int ipt = 0 ;ipt < poly1.outer().size();++ ipt ) { cv::Point p2 ; p2.x = poly1.outer()[ipt].get<0>(); p2.y = poly1.outer()[ipt].get<1>() ; cvpoints.push_back(p2) ; } cv::polylines(plateimage, cvpoints, true, cv::Scalar(rand()%255,rand()%255,rand()%255)); } // stringstream ss ; ss<<"win"<