123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- //
- // 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 <iostream>
- #include <string>
- #include <vector>
- #include "SpriteData.hpp"
- #include "ajson5.hpp"
- #include "contourdata.h"
- #include "LevelGenerate.hpp"
- #include "FillGlobalConfig.hpp"
- #include "RandomGridFiller.hpp"
- #include "BoostGeometryTools.hpp"
- #include <opencv2/core.hpp>
- #include <opencv2/imgproc.hpp>
- #include <opencv2/highgui.hpp>
- #include <sstream>
- #include <ctime>
- #include <chrono>
- #include <tuple>
- #include <sstream>
- //#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"<<endl;
- cout<<"usage:auto_fill_jewel_v3 level0001_01.json level0001_01_ext.json output.json"<<endl;
- cout<<"version v3.3"<<endl ;
- if( argc!=4 ) {
- cout<<"缺少参数"<<endl;
- return 11 ;
- }
-
- string levelinFilename = argv[1] ;
- string levelextFilename = argv[2] ;
- string outputFilename = argv[3] ;
-
- LevelInputData levelInputData ;
- LevelExtInputData levelExtData ;
-
- bool ok1 = levelInputData.readFromFile(levelinFilename);
- bool ok2 = levelExtData.readFromFile(levelextFilename) ;
- if( ok1==false ) {
- cout<<"加载关卡输入参数失败 "<<levelinFilename <<endl;
- return 12 ;
- }
- if( ok2==false ) {
- cout<<"加载关卡扩展参数失败 "<<levelextFilename <<endl;
- return 13 ;
- }
- FillGlobalConfig::getInstance() ; //初始化单例
- LevelGenerate genv3 ;
- vector<PlateFillResult> resultPlateFillResults ;
- vector<ContourData::Point> resultPlateCenterPointArr ;
- string errorStr ;
- bool genok = genv3.generate_v2(levelInputData, levelExtData, resultPlateFillResults, resultPlateCenterPointArr,errorStr);
- if( genok==false ) {
- cout<<"Error: "<<errorStr<<endl;
- return 14 ;
- }
- cout<<"write results"<<endl;
- LevelOutputWriter writer ;
- writer.writeLevelJson(levelInputData, levelExtData, resultPlateFillResults, resultPlateCenterPointArr, outputFilename) ;
- cout<<"done"<<endl;
-
- return 0;
- }
- /*
- void plateInfo(vector<tuple<int,vector<vector<FillResult>>>>& 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<vector<FillResult>>& layers = std::get<1>(*it);
- FillGlobalConfig::PlateItem* plate = fgc->getPlateItemById(plateId) ;
- if( plate->_size == FILLGLOBALCONFIG_PLATESIZE_LG ){
- nbig++;
- ss<<"LG:"<<layers.size()<<";" ;
- }
- else if( plate->_size==FILLGLOBALCONFIG_PLATESIZE_MD ){
- nmid++;
- ss<<"MD:"<<layers.size()<<";" ;
- }
- else{
- nsml++ ;
- ss<<"SM:"<<layers.size()<<";" ;
- }
- }
- stringstream ss2 ;
- ss2<<"N-LG:"<<nbig<<"; N-MD:"<<nmid<<"; N-SM:"<<nsml<<" "<<ss.str() ;
- info = ss2.str() ;
- }
- */
- /*
- bool writeLevelJson(vector<tuple<int,vector<vector<FillResult>>>>& resultPlateFillResults,
- vector<ContourData::Point>& 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<vector<FillResult>>& 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<vector<FillResult>>& 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<FillResult>& 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<<jsonText;
- return true ;
- }
- */
- //测试输出结果到屏幕
- /*
- void testPrintPlateToScreenByOpenCV () {
- if(false)
- {//测试
-
- int iplate = 5 ;
- int ilayer = 2 ;
-
- auto itPlate = resultPlateFillResults.begin() ;
- std::advance(itPlate, iplate) ;
- FillGlobalConfig::PlateItem* platePtr = FillGlobalConfig::getInstance()->getPlateItemById( std::get<0>(*itPlate) ) ;
- vector<vector<FillResult>>& 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<cv::Point> 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"<<iplate<<"-"<<ilayer ;
- cv::imshow( ss.str().c_str() , plateimage );
- cv::waitKey();
- }
- }
- */
|