cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第四步---编辑器(3)--坐标保存&加载文件操作

/* 说明:

**1.本次游戏实例是《cocos2d-x游戏开发之旅》上的最后一个游戏,这里用3.0重写并做下笔记

**2.我也问过木头本人啦,他说:随便写,第一别完全照搬代码;第二可以说明是学习笔记---好人

**3.这里用cocos2d-x 3.0版本重写,很多地方不同,但是从重写过程中也很好的学习了cocos2d-x

*/

***每一步对应的所有代码以及用到的资源都会打包在最后给出

***为避免代码过多,每一步的代码都做了标记--一看就晓得是第几步实现的避免出错改不回去(难不成还用Git?)

***可以根据设计思路(好吧,那名字太高大上。实际就是这一步要干啥)先自己实现---cocos2d-x本来就是如此,相同的功能有许多不同实现方法;先自己折腾是蛮不错的。

***为了方便移植到手机上,对于每一步都进行编译android测试;因为很多时候代码在win32下可以,编译就会出错,给出的代码会是测试过后的。

本次笔记内容:

1、稍微分析

2、看代码

3、下次内容预览

4、代码&资源下载

5、这里主要是文件操作;到这里编辑器部分也结束啦。后面就是游戏过程的设计啦

效果图---没啥效果,文件操作又看不出什么

那么到这里,先将代码分类下:

一:分析

1、我们可以先处理编辑不同关卡的实现,每次nextLvl的时候,将本层清空,重新加载地图

2、然后就是与文件挂钩,对于TowerPos和MonsterPos我们有对应容器保存;但是我们需要保存到文件中,为后面游戏加载做准备

二:代码

先处理简单的,编辑不同级别的关卡,添加 deleteAllPos函数,以及修改改变关卡的函数:

这里对于切换关卡实际上就是编辑层清空,重新加载其他关卡地图,进行编辑---(好吧,这里由于只有三个地图,就限制三个关卡,而且地图都是一样的.......)

void TowerPosEditorLayer::deleteAllPos(){
	this->removeAllChildrenWithCleanup(true);
	m_monsterPosList.clear();
	m_towerPosList.clear();
}

void TowerPosEditorLayer::nextLvl(){
	if(m_iCurLevel == 3){
		return ;
	}
	deleteAllPos();
	m_iCurLevel ++;
	loadConfigFile();
}

void TowerPosEditorLayer::preLvl(){
	if(m_iCurLevel == 1){
		return;
	}
	deleteAllPos();
	m_iCurLevel --;
	loadConfigFile();
}

到这也可以进行测试

------------------------------------------------------------------------------------

但是编辑过的地图怎么能不保存;而且,假若我编辑了第一关之后,保存,然后到第二关之后,我觉得第一关有一点点需要修改怎么办?

那么这里用一个坐标的文件操作  PosLoadUtil

这里又两个功能,加载已有的,和 把已有的输出到文件

需要小小的总结的是这是一个单例类,粗糙的了解一下单例类:

比如你拍一部电影,今天在北京有一个场戏,明天去上海由一场戏;那么这里看做是两个场景,不同的场景,你导演总不会变:Director 应该就是一个单例类(我是这么理解的)

那么我们自己来弄一个单例类:独家供应饭店;首先是没有的,我们就create一个 ,它是static 的也就是存在整个电影的拍摄过程;随便你去哪里,打个电话::getInstence()--->送饭啦;就OK

上马:.h

class PosLoadUtil : public Node{
public:
	static PosLoadUtil* getInstance();
	virtual bool init();

	//**4**
	void putToFile(Vector<PosBase*> posList, const char* sFilePath);

	//**4**选择传Vector<PosBase*>类型的引用
	void loadPosWithFile(Vector<PosBase*>& List,
		EnumPosType posType,
		const char* sFilePath,
		Node* container,
		int level,
		bool isDebug);

private:
	static PosLoadUtil* _posLoadUtil;
};

。cpp

#include "PosLoadUtil.h"

PosLoadUtil* PosLoadUtil::_posLoadUtil = NULL;

PosLoadUtil* PosLoadUtil::getInstance(){
	if(_posLoadUtil == NULL){
		_posLoadUtil = new PosLoadUtil();
		if(_posLoadUtil && _posLoadUtil->init()){
			_posLoadUtil->autorelease();
		}else{
			CC_SAFE_DELETE(_posLoadUtil);
		}
	}
	return _posLoadUtil;
}

bool PosLoadUtil::init(){
	return true;
}

void PosLoadUtil::putToFile(Vector<PosBase*> posList, const char* sFilePath){
	FILE* file = fopen(sFilePath, "w");

	// xml头部信息
	fprintf(file,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
	fprintf(file,"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n");

	// plist父节点字段开头
	fprintf(file,"<plist version=\"1.0\">\n");

	// <array>
	fprintf(file,"<array>\n");
	// 各个属性
	PosBase* posBase = NULL;
	for(auto ref : posList) {
		posBase = dynamic_cast<PosBase*>(ref);

		if(posBase != NULL) {
			// <dict>
			fprintf(file,"    <dict>\n");

			// <key>x</key>
			fprintf(file,"        <key>x</key>\n");

			// <integer>80</integer>
			fprintf(file,"        <integer>%.0f</integer>\n", posBase->getPos().x);

			// <key>y</key>
			fprintf(file,"        <key>y</key>\n");

			// <integer>266</integer>
			fprintf(file,"        <integer>%.0f</integer>\n", posBase->getPos().y);

			// </dict>
			fprintf(file,"    </dict>\n");
		}
	}
	// </array>
	fprintf(file,"</array>\n");

	// plist父节点字段结束
	fprintf(file,"</plist>\n");

	fclose(file);
}

 void PosLoadUtil::loadPosWithFile(Vector<PosBase*>& List,
	 EnumPosType posType,
	 const char* sFilePath,
	 Node* container, int iLevel, bool isDebug ) {

	// 读取plist文件
	auto value_Vector = FileUtils::getInstance()->getValueVectorFromFile(sFilePath);

	for(auto ref : value_Vector) {
		//将value_Vector 里面读取的对象ref 转化为ValueMap 类型
		auto temp_map = ref.asValueMap();

		//转化之后的ValueMap 对象 temp_map 取出x,y值
		auto x = temp_map.at("x").asFloat();
		auto y = temp_map.at("y").asFloat();

		PosBase* posBase = PosBase::create(ccp(x,y), posType, isDebug);

		List.pushBack(posBase);

		container->addChild(posBase,iLevel);
	}
}

然后,在PosEditorLayer中的文件输出函数中修改:

void PosEditorLayer::outputPosToPlistFile(){
	CCLOG("outputPosToPlistFile");
	// 输出炮台坐标配置文件
    __String* sTowerPosPath = __String::createWithFormat("game/towerPos_level_%d.plist", _curLevel);
	PosLoadUtil::getInstance()->putToFile(m_towerPosList,sTowerPosPath->getCString());

	// 输出怪物坐标配置文件
	__String* sMonsterPosPath = __String::createWithFormat("game/monsterPos_level_%d.plist", _curLevel);
	PosLoadUtil::getInstance()->putToFile(m_monsterPosList,sMonsterPosPath->getCString());
}

在PosEditorLayer的preLoad函数中:

void PosEditorLayer::preLoad(){
	/*******省略代码***********************
	//加载TowerPos
	__String* sTowerPosPath =__String::createWithFormat("game/towerPos_level_%d.plist",_curLevel);
	PosLoadUtil::getInstance()->loadPosWithFile(m_towerPosList,
		enTowerPos,
		sTowerPosPath->getCString(),
		this,10,true); /**/

	//加载MonsterPos
	__String* sMonsterPosPath = __String::createWithFormat("game/monsterPos_level_%d.plist", _curLevel);
	PosLoadUtil::getInstance()->loadPosWithFile(m_monsterPosList,
		enMonsterPos,
		sMonsterPosPath->getCString(),
		this,10,true);
}

好吧,可以欢乐的测试啦,相应目录下也可以看到对应文件

当然,就算你最开始的目录下没有对应文件,你加载也不会出问题

小小的注意一下:这里怪物的路线点,得按顺序编辑之后再保存,不然后面怪物走的时候,是按照点的顺序走的。。。会乱走

三:下次内容预览

编辑了你想要的地图之后;开始了正式的游戏Scene;炮台的坐标点加载之后肯定在点的位置是要放置炮台的。。

----------------------------------------

四:源码&资源

-----------------------------------------

个人愚昧观点,欢迎指正与讨论

时间: 2024-08-08 09:09:42

cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第四步---编辑器(3)--坐标保存&加载文件操作的相关文章

cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第一步---开始界面&amp;关卡选择

/* 说明: **1.本次游戏实例是<cocos2d-x游戏开发之旅>上的最后一个游戏,这里用3.0重写并做下笔记 **2.我也问过木头本人啦,他说:随便写,第一别完全照搬代码:第二可以说明是学习笔记---好人 **3.这里用cocos2d-x 3.0版本重写,很多地方不同,但是从重写过程中也很好的学习了cocos2d-x */ ***每一步对应的所有代码以及用到的资源都会打包在最后给出 ***为避免代码过多,每一步的代码都做了标记--一看就晓得是第几步实现的避免出错改不回去(难不成还用Git

cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第一步---開始界面&amp;amp;关卡选择

/* 说明: **1.本次游戏实例是<cocos2d-x游戏开发之旅>上的最后一个游戏,这里用3.0重写并做下笔记 **2.我也问过木头本人啦.他说:随便写,第一别全然照搬代码:第二能够说明是学习笔记---好人 **3.这里用cocos2d-x 3.0版本号重写,非常多地方不同.可是从重写过程中也非常好的学习了cocos2d-x */ ***每一步相应的全部代码以及用到的资源都会打包在最后给出 ***为避免代码过多.每一步的代码都做了标记--一看就晓得是第几步实现的避免出错改不回去(难不成还用

cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第九步---英雄发动攻击

/* 说明: **1.本次游戏实例是<cocos2d-x游戏开发之旅>上的最后一个游戏,这里用3.0重写并做下笔记 **2.我也问过木头本人啦,他说:随便写,第一别完全照搬代码:第二可以说明是学习笔记---好人 **3.这里用cocos2d-x 3.0版本重写,很多地方不同,但是从重写过程中也很好的学习了cocos2d-x */ ***每一步对应的所有代码以及用到的资源都会打包在最后给出 ***为避免代码过多,每一步的代码都做了标记--一看就晓得是第几步实现的避免出错改不回去(难不成还用Git

cocos2d-x 3.0游戏实例学习笔记 《卡牌塔防》第0步---知识点总结&amp;效果预览

/* 说明: **1.本次游戏实例是<cocos2d-x游戏开发之旅>上的最后一个游戏,这里用3.0重写并做下笔记 **2.我也问过木头本人啦,他说:随便写,第一别完全照搬代码:第二可以说明是学习笔记 **3.这里用cocos2d-x 3.0版本重写,很多地方不同,但是从重写过程中也很好的学习了cocos2d-x */ 环境:Win7 .cocos2d-x 3.0final .C++ .VS2012 笔记思路:后面就按这种思路写笔记啦 1.首先给出每次实现的效果截图 2.然后给出设计思路 3.

cocos2d-x 3.0游戏实例学习笔记 《跑酷》移植到android手机

说明:这里是借鉴:晓风残月前辈的博客,他是将泰然网的跑酷教程,用cocos2d-x 2.X 版本重写的,目前我正在学习cocos2d-X3.0 于是就用cocos2d-X 3.0重写,并做相关笔记 好吧,自从上次<跑酷>完结之后,就什么没做什么的,主要是修复了一点点bug ,也在相应的文章里面做出了相应的改动.不过,只能在window上看着玩又有什么太大意思呢!!!于是乎又尝试着弄到手机上试试--OK,初生牛犊不要脸,哦不!不怕喷.这里记录一下我的移植过程.(这里会用到新的大小的资源.待会也会

cocos2d-x 3.0游戏实例学习笔记 《跑酷》一 开始界面

开始界面和前辈的基本上差不多:cocos2d-x游戏开发 跑酷(一)开始界面     但是也有不同 下面先给出游戏过程中用到的所有资源 开始界面定义为:MainScene 有如下功能: 1.背景 2.进入游戏界面按钮 3.预先加载背景音乐文件 .h文件 #ifndef __MainScene__H__ #define __MainScene__H__ #include "cocos2d.h" class MainScene : cocos2d::Layer{ public: virtu

cocos2d-x 3.0游戏实例学习笔记 《跑酷》第六步--物理碰撞检测(1)

说明:这里是借鉴:晓风残月前辈的博客,他是将泰然网的跑酷教程,用cocos2d-x 2.X 版本重写的,目前我正在学习cocos2d-X3.0 于是就用cocos2d-X 3.0重写,并做相关笔记 那么这一步,我们先不急着给主角和金币岩石碰撞检测,我这里把cocos2d-x 3.0 的物理碰撞检测单独抽取出来,之前看了cocos的官网,有一个教程:用新物理引擎完成碰撞检测,就是一个车和猫的碰撞检测,车撞倒猫,猫就消失.我之前也单独试了下.但是那个教程的代码好像完整性不好,不能运行...于是我又借

coco2d-x 3.0游戏实例学习笔记 《跑酷》 二 游戏界面--全新的3.0物理世界

从这里开始,就和之前前辈的有很多不同啦. 在MainScene中,开始按钮中,我们就要通过回调函数,进入到我们的游戏场景啦. 那么在游戏场景中我们定义为:PlayScene ,而且是一个带物理世界的场景,cocos2d-x 3.0中要创建物理Scene是很简单的,因为它都帮我们封装好了. 那么这一步,我们在PlayScene 中主要完成以下功能: 1.物理世界创建 2.创建一个地面的物理刚体 相关知识个人见解: 所谓的创建物理世界,个人觉得是一个抽象的东东,作为新手,开始并不能理解,开始你可以就

cocos2d-x 3.0游戏实例学习笔记 《跑酷》第四步--地图循环&amp;主角添加动作

这一步当中,我们主要完成以下功能: 1.地图的无限滚动---让主角看起来真的是在跑动 2.给主角添加Jump跳跃和crouch下蹲动作 那么首先来让背景滚动起来,在PlayScene.h中添加: //初始化背景 void initBG(); //用update函数让地图滚动 virtual void update(float dt); //背景精灵 cocos2d::Sprite* bgSprite1; cocos2d::Sprite* bgSprite2; cocos2d::Sprite* g