Cocos2d-x 3.2 大富翁游戏项目开发-第二十八部分 游戏保存和载入存档游戏

Cocos2d-x 3.2 大富翁游戏项目开发-第二十八部分 游戏保存和载入存档游戏,第1张

概述1、游戏保存 如图,在右下角增加保存图标,点击后进行游戏的保存。 游戏保存采用json格式,具体如下:{ "map_level":2, // 游戏关卡 "gameRoundCount":66, // 游戏回合数 "players":[ //角色信息 { "playerTag":1, //角色1 "playerPosition_x":320, //角色所处的x坐标 1、游戏保存

如图,在右下角增加保存图标,点击后进行游戏的保存。



游戏保存采用Json格式,具体如下:{	"map_level":2,// 游戏关卡	"gameRoundCount":66,// 游戏回合数	"players":[  //角色信息		{		"playerTag":1,//角色1		"playerposition_x":320,//角色所处的x坐标		"playerposition_y":192,//角色所处的y坐标		"restTimes":3,//角色休息回合数		"stop_x":0,//角色停留的x坐标		"stop_y":0,//角色停留的y坐标		"money":509000,//角色资金		"strength":100,//角色体力		"comeFromeRow":4,//角色从上一个位置的行		"comeFromCol":10,//角色从上一个位置的列		"isMyTurn":false,//角色是否该行走		"skill":"1-2-2",//角色技能等级		"lottery":"",//角色购买的彩票号码		"stocks":[				//角色持有的股票信息			{"stockCode":800100,"makedealprice":10,"storeNumber":100},{"stockCode":800200,"makedealprice":0,"storeNumber":0},{"stockCode":800300,{"stockCode":800400,"storeNumber":400},{"stockCode":800500,"storeNumber":0}			]		},{		"playerTag":2,//角色2的保存信息,同上		"playerposition_x":423.635,"playerposition_y":96,"restTimes":0,"stop_x":10,"stop_y":13,"money":410300,"strength":80,"comeFromeRow":2,"comeFromCol":15,"isMyTurn":false,"skill":"3-2-1","lottery":"","stocks":[			{"stockCode":800100,"makedealprice":20,"storeNumber":200},"storeNumber":0}			]		}	],"landlayer":[ //地块的信息,在x行,y列 地块的gID值		{"x":5,"y":7,"gID":12},{"x":5,"y":12,{"x":6,"y":9,"y":10,"gID":11},{"x":7,"gID":1},"y":13,{"x":8,"y":11,{"x":9,"y":8,{"x":10,"y":6,{"x":11,"gID":13},"gID":15},{"x":12,"gID":14},{"x":13,{"x":14,"gID":10},{"x":15,{"x":16,{"x":17,"gID":10}		]}

//在添加go按钮的方法中同时添加保存按钮voID  GameBaseScene::addGobutton(){......    saveMenuItembutton = MenuItemImage::create("map/save_normal.png","map/save_pressed.png",this,menu_selector(GameBaseScene::gobuttonCallback)); 	saveMenuItembutton->setposition(ccp(winSize.wIDth,0));	saveMenuItembutton->setAnchorPoint(ccp(1,0));	saveMenuItembutton->setTag(savebuttonTag);	menu->addChild(saveMenuItembutton);}voID GameBaseScene::gobuttonCallback(cocos2d::CCObject *pSender){	.........	//当点击后调用saveGame()方法保存游戏	if(tag == savebuttonTag)	{		if(saveGame())		{			CocosToast::createtoast(this,LanguageString::getInstance()->getLanguageString(SAVE_SUCESS)->getCString(),TOAST_SHOW_TIME,winSize/2);		}else		{			CocosToast::createtoast(this,LanguageString::getInstance()->getLanguageString(SAVE_FAIL)->getCString(),winSize/2);		}	}}


saveGame()进行具体的游戏保存
cocos2dx使用了rAPIdJson库来替换原来的Jsoncpp,我们就用这个cocos2dx自带的Json库
//*** 生成 Json 文件,存储在 getWritablePath 文件夹下 *** ,当前在proj.win32\DeBUG.win32目录下

bool GameBaseScene::saveGame(){	rAPIdJson::document writedoc; //创建document	writedoc.Setobject();	rAPIdJson::document::AllocatorType& allocator = writedoc.GetAllocator();	rAPIdJson::Value players(rAPIdJson::kArrayType);//创建players数组	writedoc.AddMember("map_level",map_level,allocator); //添加map_level属性值	writedoc.AddMember("gameRoundCount",gameRoundCount,allocator); //添加gameRoundCount回合数	int playerNumber=1;		rAPIdJson::Value player1_Json(rAPIdJson::kObjectType); //创建player1的Json对象	rAPIdJson::Value player2_Json(rAPIdJson::kObjectType); //创建player2的Json对象	rAPIdJson::Value player3_Json(rAPIdJson::kObjectType); //创建player3的Json对象	//保存各个角色的信息	for(auto it=players_vector.begin();it!=players_vector.end();it++)	{		RicherPlayer* richerPlayer = dynamic_cast<RicherPlayer*>(*it);		switch(playerNumber)		{		case 1:			{				//在player1_Json对象中添加角色各个属性值,Json object 格式 “名称/值” 				player1_Json.AddMember("playerTag",richerPlayer->getTag(),allocator); 				player1_Json.AddMember("playerposition_x",richerPlayer->getposition().x,allocator);				player1_Json.AddMember("playerposition_y",richerPlayer->getposition().y,allocator);				 player1_Json.AddMember("restTimes",richerPlayer->restTimes,allocator);				 player1_Json.AddMember("stop_x",richerPlayer->stop_x,allocator);				 player1_Json.AddMember("stop_y",richerPlayer->stop_y,allocator);				 player1_Json.AddMember("money",richerPlayer->getMoney(),allocator);				 player1_Json.AddMember("strength",richerPlayer->getStrength(),allocator);				 player1_Json.AddMember("comeFromeRow",richerPlayer->getComeFromeRow(),allocator);				 player1_Json.AddMember("comeFromCol",richerPlayer->getComeFromCol(),allocator);				 player1_Json.AddMember("isMyTurn",richerPlayer->getIsMyTurn(),allocator);				 player1_Json.AddMember("skill",String::createWithFormat("%d-%d-%d",richerPlayer->skill_vector.at(0),richerPlayer->skill_vector.at(1),richerPlayer->skill_vector.at(2))->getCString(),allocator);						 std::string tempstr;				 tempstr = "";				 for(auto i=0;i<richerPlayer->lottery_vector.size();i++)				 {					 tempstr.append(String::createWithFormat("%02d",richerPlayer->lottery_vector.at(i))->getCString()).append("_");				  }				 player1_Json.AddMember("lottery",String::createWithFormat("%s",tempstr.c_str())->getCString(),allocator);				 rAPIdJson::Value stocks(rAPIdJson::kArrayType);				 for(auto i=0;i<richerPlayer->stockMap.size();i++)				{					 rAPIdJson::Value stock(rAPIdJson::kObjectType);					 stock.AddMember("stockCode",richerPlayer->stockMap.at(i)->getCode(),allocator);					 stock.AddMember("makedealprice",richerPlayer->stockMap.at(i)->getMakedealprice(),allocator);					 stock.AddMember("storeNumber",richerPlayer->stockMap.at(i)->getStoreNumber(),allocator);					 stocks.PushBack(stock,allocator);				 }				 player1_Json.AddMember("stocks",stocks,allocator);				// 将player1_Json加入到players数组				 players.PushBack(player1_Json,allocator);				 break;			}		case 2:			{				//添加角色2属性值				 player2_Json.AddMember("playerTag",allocator);				 player2_Json.AddMember("playerposition_x",allocator);				 player2_Json.AddMember("playerposition_y",allocator);				 player2_Json.AddMember("restTimes",allocator);				 player2_Json.AddMember("stop_x",allocator);				 player2_Json.AddMember("stop_y",allocator);				 player2_Json.AddMember("money",allocator);				 player2_Json.AddMember("strength",allocator);				 player2_Json.AddMember("comeFromeRow",allocator);				 player2_Json.AddMember("comeFromCol",allocator);				 player2_Json.AddMember("isMyTurn",allocator);				 player2_Json.AddMember("skill",allocator);								 std::string tempstr;				 tempstr = "";				 for(auto i=0;i<richerPlayer->lottery_vector.size();i++)				 {					 tempstr.append(String::createWithFormat("%02d",richerPlayer->lottery_vector.at(i))->getCString()).append("_");				  }				 player2_Json.AddMember("lottery",allocator);				 }				 player2_Json.AddMember("stocks",allocator);				 players.PushBack(player2_Json,allocator);				 break;			}		case 3:			{			//添加角色3属性值				 player3_Json.AddMember("playerTag",allocator);				 player3_Json.AddMember("playerposition_x",allocator);				 player3_Json.AddMember("playerposition_y",allocator);				 player3_Json.AddMember("restTimes",allocator);				 player3_Json.AddMember("stop_x",allocator);				 player3_Json.AddMember("stop_y",allocator);				 player3_Json.AddMember("money",allocator);				 player3_Json.AddMember("strength",allocator);				 player3_Json.AddMember("comeFromeRow",allocator);				 player3_Json.AddMember("comeFromCol",allocator);				 player3_Json.AddMember("isMyTurn",allocator);				 player3_Json.AddMember("skill",richerPlayer->lottery_vector.at(i))->getCString()).append("_");				  }				 player3_Json.AddMember("lottery",allocator);				 }				 player3_Json.AddMember("stocks",allocator);				 players.PushBack(player3_Json,allocator);				 break;			}		}		playerNumber++;	}	//将players数组写入到writedoc	 writedoc.AddMember("players",players,allocator);	// 保存地块Json	 rAPIdJson::Value landlayerjson(rAPIdJson::kArrayType);	Size _landLayerSize = landLayer->getLayerSize(); 	for (int j = 0;  j < _landLayerSize.wIDth; j++) {  		for (int i = 0;  i < _landLayerSize.height; i++) {  			Sprite* _sp = landLayer->tileAt(Point(j,i));  			if (_sp) 			{  				rAPIdJson::Value landJson(rAPIdJson::kObjectType);				int gID = landLayer->getTileGIDAt(Point(j,i));				landJson.AddMember("x",j,allocator);				landJson.AddMember("y",i,allocator);				landJson.AddMember("gID",gID,allocator);				landlayerjson.PushBack(landJson,allocator);			}  		}  	}	writedoc.AddMember("landlayer",landlayerjson,allocator);	//把Json数据保存到path路径文件下,文件名称为saveJsonname ,saveJsonname在SeaScene.cpp中赋值   StringBuffer buffer;	  rAPIdJson::Writer<StringBuffer> writer(buffer);	  writedoc.Accept(writer);	  auto path = fileUtils::getInstance()->getWritablePath();	  path.append(saveJsonname);	  file* file = fopen(path.c_str(),"wb");	  if(file)	  {		fputs(buffer.GetString(),file);		fclose(file);	  }	cclOG("%s",buffer.GetString());  return true;}

2、载入存档

效果如图


//在addMenuSprites()增加载入游戏按钮voID MenuScene:: addMenuSprites(){.............	LabelTTF* loadGameTTF = LabelTTF::create(LanguageString::getInstance()->getLanguageString(LOAD_GAME)->getCString(),Font_MENU,Btn_FontSize);	Controlbutton* loadGameBtn = Controlbutton::create(loadGameTTF,btnnormal4);	loadGameBtn->setBackgroundSpriteForState(btnPress4,Control::State::SELECTED);	loadGameBtn->setposition(ccp(visibleSize.wIDth/2,visibleSize.height-360));	loadGameBtn->setPreferredSize(Size(Btn_WIDth,Btn_Height));	loadGameBtn->addTargetWithActionForControlEvents(this,cccontrol_selector(MenuScene::menutouchDown),Control::EventType::touch_DOWN);	loadGameBtn->setTag(Btn_Load_Game_TAG);	addChild(loadGameBtn);........}

//点击后进入到popupLoadGameLayer(),d出游戏存档的界面voID MenuScene::popupLoadGameLayer(){      PopupLayer* popDialog = PopupLayer::create(DIALOG_BG);   	popDialog->setContentSize(CCSizeMake(Quit_Dialog_Size_WIDth,winSize.height));     popDialog->setTitle(LanguageString::getInstance()->getLanguageString(LOAD_GAME)->getCString());    popDialog->setContentText(LanguageString::getInstance()->getLanguageString(DIALOG_CONTENT)->getCString(),20,60,250);	popDialog->setPopType(LOADGAME);    popDialog->setCallbackFunc(this,callfuncN_selector(MenuScene::quitbuttonCallback));       popDialog->addbutton(button_BG2,button_BG3,LanguageString::getInstance()->getLanguageString(CANCEL)->getCString(),Btn_Quit_Cancel_TAG);      this->addChild(popDialog);}

PopupLayer会根据pop类型,调用setLoadGameContext(),创建载入游戏的对话框界面voID PopupLayer::onEnter(){......	case LOADGAME:		{			setLoadGameContext(contentSize);			break;		}......}

//该方法主要是判断path路径下是否有存档文件。如果没有存档,显示无存档,有则显示关卡图片voID PopupLayer::setLoadGameContext(Size size){	Menu* menu = Menu::create();	menu->setposition(CCPointZero);  	//判断是否有夏日海滩的存档文件	  auto beach_path = fileUtils::getInstance()->getWritablePath();	  beach_path.append("beach_save.Json");	  file* beach_file = fopen(beach_path.c_str(),"r");	  //有则显示海滩图片,否则显示无存档	  if(beach_file)	  {		beachLoadGameMenuItem = MenuItemImage::create("map/beach_load_normal.png","map/beach_load_pressed.png",menu_selector(PopupLayer::loadGamebuttonCallback)); 		beachLoadGameMenuItem->setposition(winSize/2+Size(0,120));		beachLoadGameMenuItem->setTag(save_beach_tag);		menu->addChild(beachLoadGameMenuItem);		fclose(beach_file);	  }else	  {		beachLoadGameMenuItem = MenuItemImage::create("map/blank.png","map/blank.png",menu_selector(PopupLayer::loadGamebuttonCallback));		beachLoadGameMenuItem->setposition(winSize/2+Size(0,120));		menu->addChild(beachLoadGameMenuItem);	  }	//判断是否有海底世界的存档文件	  auto sea_path = fileUtils::getInstance()->getWritablePath();	  sea_path.append("sea_save.Json");	  file* sea_file = fopen(sea_path.c_str(),"r");	  if(sea_file)	  {		seaLoadGameMenuItem = MenuItemImage::create("map/sea_load_normal.png","map/sea_load_pressed.png",menu_selector(PopupLayer::loadGamebuttonCallback)); 		seaLoadGameMenuItem->setposition(winSize/2+Size(0,20));		seaLoadGameMenuItem->setTag(save_sea_tag);		menu->addChild(seaLoadGameMenuItem);		fclose(sea_file);	  }else	  {		seaLoadGameMenuItem = MenuItemImage::create("map/blank.png",menu_selector(PopupLayer::loadGamebuttonCallback));		seaLoadGameMenuItem->setposition(winSize/2+Size(0,20));		menu->addChild(seaLoadGameMenuItem);	  }	//判断是否有空中花园的存档文件	  auto garden_path = fileUtils::getInstance()->getWritablePath();	  garden_path.append("garden_save.Json");	  file* garden_file = fopen(garden_path.c_str(),"r");	  if(garden_file)	  {		gardenLoadGameMenuItem = MenuItemImage::create("map/garden_load_normal.png","map/garden_load_pressed.png",menu_selector(PopupLayer::loadGamebuttonCallback)); 		gardenLoadGameMenuItem->setposition(winSize/2+Size(0,-80));		gardenLoadGameMenuItem->setTag(save_garden_tag);		menu->addChild(gardenLoadGameMenuItem);		fclose(garden_file);	  }else	  {		gardenLoadGameMenuItem = MenuItemImage::create("map/blank.png",menu_selector(PopupLayer::loadGamebuttonCallback));		gardenLoadGameMenuItem->setposition(winSize/2+Size(0,-80));		menu->addChild(gardenLoadGameMenuItem);	  }	addChild(menu);}

//当点击各个存档文件图片后,载入相应的游戏存档,恢复游戏voID PopupLayer::loadGamebuttonCallback(cocos2d::CCObject *pSender){		int tag = ((Node*)pSender)->getTag();	if(tag == save_beach_tag)	{		log("beach load");	}	if(tag == save_sea_tag)	{		//点击海底世界图片,首先进入海底世界关卡		TransitionFadeBL* scene = 	TransitionFadeBL::create(1,SeaScene::createScene());		Director::getInstance()->pushScene(scene);		//然后发送载入游戏的消息		String * str = String::createWithFormat("%d-%d",MSG_LOAD_GAME_TAG,tag);		NotificationCenter::getInstance()->postNotification(MSG_LOAD_GAME,str);			log("sea load");	}	if(tag == save_garden_tag)	{		log("garden load");	}}

//GameBaseScene收到载入的消息后,调用reloadGame()方法,载入游戏存档voID GameBaseScene::receivednotificationOMsg(Object* data){........	case MSG_LOAD_GAME_TAG:		{			int map_level = messageVector.at(1)->intValue();			reloadGame(map_level);						break;		}.......}

//开始具体游戏的载入恢复bool GameBaseScene::reloadGame(int map_level){	//根据关卡,载入相应的存档文件	auto path = fileUtils::getInstance()->getWritablePath();	switch(map_level)	{	case 1:		{			path.append("beach_save.Json");			break;		}	case 2:		{			path.append("sea_save.Json");			break;		}	case 3:		{			path.append("garden_save.Json");			break;		}	}	//*** 读取 Json 文件 ***	rAPIdJson::document readdoc;	bool bRet = false;	ssize_t size = 0;	std::string load_str;	// getfileData 如果不指定,读取根目录是 Resource 文件夹	unsigned char* Titlech = fileUtils::getInstance()->getfileData(path,"r",&size);	load_str = std::string((const char*)Titlech,size);	readdoc.Parse<0>(load_str.c_str());		if(readdoc.HasParseError())	{		cclOG("GetParseError%s\n",readdoc.GetParseError());	}	if(!readdoc.IsObject())		return 0;	//回合数载入	rAPIdJson::Value& _gameRoundCount = readdoc["gameRoundCount"];	gameRoundCount = _gameRoundCount.GetInt();	refreshRounddisplay();	//土地等级载人	rAPIdJson::Value& _landlayer = readdoc["landlayer"];	if(_landlayer.IsArray())	{		for(int i=0; i<_landlayer.Capacity(); i++)		{			rAPIdJson::Value& arraydoc = _landlayer[i];			int x = arraydoc["x"].GetInt();			cclOG("x:%d",x);			int y = arraydoc["y"].GetInt();			cclOG("y:%d",y);			int gID = arraydoc["gID"].GetInt();			cclOG("gID:%d",gID);			landLayer->setTileGID(gID,ccp(x,y));		}	}	//人物信息载人	rAPIdJson::Value& _players = readdoc["players"];	if(_players.IsArray())	{		for(int i=0; i<_players.Capacity(); i++)		{			rAPIdJson::Value& arraydoc = _players[i];			RicherPlayer* _richerPY = players_vector.at(i);			int _restTimes = arraydoc["restTimes"].GetInt();				float _playerpositionX = arraydoc["playerposition_x"].GetDouble();				float _playerpositionY = arraydoc["playerposition_y"].GetDouble();			int _stop_x = arraydoc["stop_x"].GetInt();						int _stop_y = arraydoc["stop_y"].GetInt();						int _money = arraydoc["money"].GetInt();			int _strength = arraydoc["strength"].GetInt();			int _comeFromeRow = arraydoc["comeFromeRow"].GetInt();			int _comeFromCol = arraydoc["comeFromCol"].GetInt();			bool _isMyTurn = arraydoc["isMyTurn"].GetBool();			const char* _skill = arraydoc["skill"].GetString();			const char* _lottery = arraydoc["lottery"].GetString();			Vector<String*> lotteryVector = Util::splitString(_lottery,"_");			for(int i=0;i<lotteryVector.size();i++ )			{				_richerPY->lottery_vector.push_back(lotteryVector.at(i)->intValue());			}			_richerPY->restTimes = _restTimes;			_richerPY->setposition(ccp(_playerpositionX,_playerpositionY));			_richerPY->setComeFromeRow(_comeFromeRow);			_richerPY->setComeFromCol(_comeFromCol);			_richerPY->setIsMyTurn(_isMyTurn);			_richerPY->stop_x = _stop_x;			_richerPY->stop_y = _stop_y;			_richerPY->setMoney(_money);			_richerPY->setStrength(_strength);			Vector<String*> skillVs = Util::splitString(_skill,"-");			_richerPY->skill_vector.at(0) = skillVs.at(0)->intValue();			_richerPY->skill_vector.at(1) = skillVs.at(1)->intValue();			_richerPY->skill_vector.at(2) = skillVs.at(2)->intValue();			refreshMoneyLabel(_richerPY,0);			refreshStrengthLabel(_richerPY,0);		}	}	//股票载入	for(int i=0; i<players_vector.size(); i++)	{		RicherPlayer* _richerPY = players_vector.at(i);		rAPIdJson::Value& _stocks = _players[i]["stocks"];		if(_stocks.IsArray())		{			for(int i=0; i<_stocks.Capacity(); i++)			{				rAPIdJson::Value& arraydoc = _stocks[i];				int _stockCode = arraydoc["stockCode"].GetInt();					int _makedealprice = arraydoc["makedealprice"].GetInt();							int _storeNumber = arraydoc["storeNumber"].GetInt();					_richerPY->stockMap.at(i)->setMakedealprice(_makedealprice);				_richerPY->stockMap.at(i)->setStoreNumber(_storeNumber);			}		}	}    return 0;}

至此,游戏从保存文档中恢复完毕。

点击下载代码 未完待续................ 总结

以上是内存溢出为你收集整理的Cocos2d-x 3.2 大富翁游戏项目开发-第二十八部分 游戏保存和载入存档游戏全部内容,希望文章能够帮你解决Cocos2d-x 3.2 大富翁游戏项目开发-第二十八部分 游戏保存和载入存档游戏所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1043589.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-24
下一篇 2022-05-24

发表评论

登录后才能评论

评论列表(0条)

保存