cocos2dx源码完全解析,cocos2dx开发

http://www.itjxue.com  2023-01-24 03:26  来源:未知  点击次数: 

win7 用vs2015 打开cocos2dx 源码,一大片提示错误,都是 namespace "cocos2d::std" 没有 xxx 这种

可能程序不兼容, 可以更换个版本试试。另外建议参考下程序对配置的要求。

或者右键需要运行的程序 选择兼容性 用兼容模式运行试试。

怎样制作基于Cocos2d-x的SLG游戏

创建项目

如果要说到环境搭建,那又该是一篇长篇大论了,所以这里我就不说了,不清楚的同学到网上问度娘吧,会有很多不同系统不同版本搭建的结果的。

Cocos2d-x创建项目的方式一直都在不停的改动,所以这里我觉得很有必要给大家介绍下如何创建项目。

创建3.2的项目其实很简单,打开终端(Windows是cmd)进入到引擎文件夹目录,然后输入以下命令就可以创建。

cocos new SLG -p com.cocos2dx.rs -l cpp -d /Users/cocos2d-x/workspace/cocos2dx/cocos2d-x-3.2/projects

如下图:

p1

说明:

new:new后是项目名

-p :-p后是包名

-l :-l后是语言(cpp指c++)

-d :-d后是项目生成路径

如果一切无误,那等待几分钟以后你就可以在给定的目录下找到新建的项目了。打开项目工程后,下面我们就可以开始游戏的制作了。

前期准备

打开工程后,运行程序,你会发现它不是一个空的项目,在Classes和Resource文件夹下Cocos2d-x已经给出了一些实质性的东西,当然这些不是一定都有用的,它们存在的目的是为了给我们展示一个典型的Cocos2d-x的例子。

除了AppDelegate.h 和 AppDelegate.cpp文件,这两个文件夹下其他的东西都是可被删除的(不过在删除之前,可以先看一下HelloWorld类,了解下它的类结构、类方法,以便对Cocos2d-x进行初步的学习,也方便初学者依葫芦画瓢再写一个类似的场景)。AppDelegate类是创建项目时自动生成的一个类,它控制着游戏的生命周期,是Cocos2d-x游戏的通用入口文件,类似于一般 Windows 工程中main函数所在的文件。

打开AppDelegate.cpp文件,在游戏加载期的最后一个applicationDidFinishLaunching()函数中我们可以设置第一个启动的游戏场景,如下:

auto scene = GameScene::createScene();

director-runWithScene(scene);

GameScene是我们新建的一个游戏场景,下面会讲解。

分辨率适配

在我的游戏中,首先第一件事还是做分辨率适配,这是个恒古不变的定律。现如今市场中各种屏幕尺寸和分辨率的移动设备层出不穷,为了更好地适应这些设备,游戏的分辨率适配是十分有必要的。

在农场游戏中,很最要的一点就是实现大地图背景的拖动、放大缩小等操作,所以可想而知,我们的地图不是全部都显示在屏幕内的,也就是说,我们不能像之前的方式那样把整个显示内容做适配,我们应该留有一定的边距供玩家拖动。如下图所示:

p2

同样是在applicationDidFinishLaunching函数中,我们添加如下一段代码对游戏做分辨率适配,以便它能更好的适应不同的运行环境。

glview-setDesignResolutionSize(480.0f, 320.0f, ResolutionPolicy::FIXED_HEIGHT);

std::vector searchPath;

searchPath.push_back("H_1920");

FileUtils::getInstance()-setSearchPaths(searchPath);

director-setContentScaleFactor(1440.0f / 320.0f);

分辨率适配的原理,建议大家阅读一下:Cocos2d-x 多分辨率适配完全解析这篇文章,虽然它不是针对最新版Cocos2dx引擎,但它还是能很清楚的告诉你分辨率适配的原理和方法。

还有要说明的一点是,我们的游戏地图的高为1920,分辨率适配时则只设为了1440,意思就是说,我们本该全在屏幕内的内容留出了4分之一的高度在屏幕外。

编辑游戏地图

模拟经营游戏中,游戏地图多为拼接而成,这里我们用瓦片地图编辑器(Tiled Map Editor)来制作游戏的地图,它可以把编辑后的地图文件保存为TMX格式的文件,能被Cocos2d-x很好的支持。瓦片地图(Tile Map)不但生成简单,而且可以灵活的用于引擎中。关于瓦片地图的介绍可参考瓦片地图一文。

接下来我们开始创建地图。

运行TiledMap编辑器,新建一个地图文件。填写如下对话框:

p3

在地图方向选项内,可以选择正常、45度(传说中的2.5D)和45度交错,这里我们选择45度。接下来需要设置地图大小,这里的数值是指有多少格tile元件,并不是像素,这里我们选择30×30的地图。

最后是确定tile元件的大小,根据美工提供的地面元件大小设置,这个教程里,我们使用128×64的大小。

在地图大小一栏中,你可以看到最终的地图大小为3840 * 1920。

点击确认之后,你可能已经发现了,这个游戏地图它是菱形的,如下图所示。

p4

这里你可能会想,为什么要菱形的啦,选择45度交错建一个接近矩形的不行吗?呵呵,其实这样也是可以的,只不过啦,Cocos2d-x引擎中默认是不支持45度交错的,如果需要在引擎中加载这种交错的地图必须自己修改引擎代码(看到这,是不是整个人都不好了),而且在修改过后还不能正确的得到地图的大小,需要自己编写计算大小的公式代码。鉴于这一点,我在想,难道《全名农场》、《请叫我海盗》等游戏地图的四个角都不能被点击操作都是因为这个原因吗? 哈哈,就当是我想多了吧。其实菱形就菱形吧,其他的游戏也都这样,可以在菱形地图的下层贴一层背景来掩盖这一现象。

接下来,我们还是回到正题开始拼接地图吧。选择地图-》新图块,然后填写如下所示的对话框。

p5

选择浏览按钮,将准备好的图块文件载入编辑器。接着设置图块的宽度和高度(默认情况下是一个tile元件的大小,但),根据图块文件中图块的大小来设置。边距、间距什么的,可不做修改,0就好。

最后选中相应的图块,拖动到渲染区拼一个理想的地图。

p6

暂时我们就只简单的拼一个地图就可以了,后面再根据游戏需要,设置一些必要的对象和属性。

加载地图资源

新建一个GameScene场景,加载游戏地图。不过在此之前,请把编辑好的tmx和图块文件拷贝到Resource文件夹下。GameScene的结构和HelloWorld差不多,照着HelloWorld类依葫芦画瓢就可以建一个。你可以先看看它是如何实现的,再实现自己的类。这里就不多说了。

在Cocos2d-x中使用TMX,有以下流程供你参考:

首先用地图编辑器编辑你的地图,导出成TMX 格式。

将导出的TMX 文件和相关图片放在工程的Resoure文件夹下。

使用Cocos2d-x中TMXTileMap 类的create方法创建地图对象,TMX 文件的解析是引擎内部完成的,所以我们不需要担心。TMXTileMap 是Node 的子类,因此只要添加到场景中即可。

通过TMXTileMap,可以获得其他相关对象,比如单个瓦片(属Sprite类),比如对象组(ObjectGroup类),比如层(TMXLayer类)等;你可以通过TMXLayer类修改,删除或者添加某个网格位置的瓦片,这样可以动态的修改地图了,你还可以进行其他的操作,相关的API 我们后面使用到了再做讲解。

在GameScene类的init函数中添加如下的代码创建游戏地图:

mapLayer = LayerColor::create(Color4B(78,127,41,255));

this-addChild(mapLayer,-1);

auto map = TMXTiledMap::create("mymap4.tmx");

mapLayer-setContentSize(map-getContentSize());

mapLayer-addChild(map, 10);

auto treeSprite = Sprite::create("1.png");

treeSprite-setAnchorPoint(Vec2(0, 0));

treeSprite-setPosition(Vec2(0, 0));

treeSprite-setScale(2);

mapLayer-addChild(treeSprite, 11);

代码中新建了一个带颜色的背景层,背景层的尺寸等于加载的TMX地图大小。接着把地图和如下的一个遮盖层(其实就是为了防止菱形的地图看起来那么突兀而添加的一层)依次添加到层上。

cocos2dx 3.x版本中导入tiled地图如何导入对象层中对象的自定义信息(源码+注释)

步骤如下:

1. cocos2d-x 中使用类 TMXTiledMap 创建瓦片地图

2. 使用 TMXTiledMap 中的 getObjectGroup 接口取得对象层

3. 使用对象层的 getObject 接口获取对象信息,对象信息是一个 ValueMap 实例

4. 从 ValueMap 中取出数据

测试地图如下所示:

如图所示:

1. 有一个名为 object 的对象层

2. object 对象层中有一个名为 test 的对象

3. test 对象有一个名为 attr 的属性

代码以及注释如下所示:

cocos2dx CCFileUtils 或者CCDictionary如何读取文件

在cocos2d-x中可以用.plist格式的文件来保存数据,它是XML文件格式的一种,在cocos2d-x解析.plist方面相关的资料比较少,但本身也很简单,要解析.plist文件可以参考cocos2d-x类库中的CCSpriteFrameCache类和CCParticleSystem类,它主要是使用CCDictionary类来对.plist文件进行操作。

下面有一个.plist文件:

?xml version="1.0" encoding="UTF-8"?

plist version="1.0"

dict

keylevel1/key

dict

keybg_far_scene/key

dict

keypath/key

stringimages/far_scene.png/string

keypos/key

string{358, 309}/string

/dict

keybg_near_scene/key

dict

keypath/key

stringimages/near_scene.png/string

keypos/key

string{360, 100}/string

/dict

/dict

/dict

/plist

读取.plist文件的代码如下:

const char* testPlistPath = "BSPlistDatas\\test.plist";

const char* fullPath = CCFileUtils::sharedFileUtils()-fullPathFromRelativeFile("test.plist", testPlistPath);

CCDictionary* plistDic = CCDictionary::createWithContentsOfFile(testPlistPath);

CCDictionary* levelDic = dynamic_castCCDictionary*(plistDic-objectForKey("level1"));

CCDictionary* farScene = dynamic_castCCDictionary*(levelDic-objectForKey("bg_far_scene"));

CCString* farScenePath = dynamic_castCCString*(farScene-objectForKey("path"));

CCPoint point = CCPointFromString(farScene-valueForKey("pos")-getCString());

CCLog("path = %s", farScenePath-getCString());

CCLog("pos = %f, %f", point.x, point.y);

第一行是.plist文件的相对路径,通过CCFileUtils类获得文件中绝对路径后,使用CCDictionary::createWithContensOfFile(filePath);将文件中内容加载到CCDictionary数据结构的内存中,然后通过xxxForKey获得相应的key下的value。

这里需要注意的是,当在读取'pos'的时候,它的值一个{x, y}的字符串,这是.plist文件中的数组存储规则,我们可以通过cocos2d-x提供函数api将这样的字符串转化为CCpoint对象。

CCPoint point = CCPointFromString(farScene-valueForKey("pos")-getCString());

上面这句话就是做了这样的一个转化的过程,同样的cocos2d-x还支持CCSize、CCRect的字符串的转化。他们转化的方法以及在.plist中对应的字符串格式如下:

CCPoint: CCPointFromString();{x, y}

CCSize: CCSizeFromString();{w, h}

CCRect: CCSizeFromString();{x, y, w, h}

这样我们2D游戏所初始化所需要的数据都基本上够用了,可以尝试将游戏的初始数据放在.plist中,然后修改调整数值就可以直接修改plist文件,而无需重新编译程序了,从而实现游戏数据和游戏逻辑的分离。

cocos2dx 3.10 事件机制

cocos2dx的事件机制里存在三类: Event、EventListener、EventDispatcher

先理解一下它们之间的关系

当我们按下按钮时(Event),会触发一个特定的事件(EventListener相当于回调函数),而这个特定的事件又存储在EventDispatcher里,可能按下这个按钮会触发多个事件,而事件的先后就是靠EventDispatcher来决定的。

Event的相关类

当出现来自鼠标,键盘,触屏,摇杆等输入源的输入时,这个事实称之为事件

引擎无时无刻都在感受事件。

Event

可以看出Event主要包含三个变量,一个是事件类型_type(也就是定义的枚举类型:触摸、键盘等),isStopped判断事件是否停止,只要事件停止,其相关的Listener都要停止callback调用。

EventTouch

它对应于四种触摸操作,不同的EventCode可以告诉Listener来调用不同的callback。

EventCustom

它是用户自定义事件,userData记录用户自定义数据,另一个eventName是用户给事件取的别名

上面的源码都有英文注释,我就不多解释了,我只说一个最重要的_isRegistered,它判断事件有没有被注册,如果没有被注册就不会触发。(如何注册事件?将事件加入dispatcher)

在讲它之前,我们先了解一下它的一个重要变量。

sceneGraphListeners: 一个事件(比如说触摸事件),需要按照一定的响应序列,依次对这些Node进行事件响应,所以该类型的事件都会绑定一个与此相关联的node,并且 响应顺序是与node在scene下的zorder相关的 。该类型下的事件优先级统一为0。(与渲染树有关)

fixedListeners: 优先级根据 fixedPriority 的数值从小往大排序、

只要出现了删除,修改,添加监听器的时候,监听器列表需要重新排序,都需要设置相应的 DirtyFlag 操作。但是 Cocos-2dx v3.10 里面的 updateListeners 函数有删除监听器的操作,然而并没有设置相应的 DirtyFlag 操作。

会抛出下面的异常

Gt0Index() 方法其实就是获取到当前监听器中 fixedPriority == 0 的监听器在监听器向量中的位置,它 只有在给 Listener 排序的时候会设置,但是如果更新了对应 ListenerID 的向量(EventListenerVector),但是没有重新排序,就会出现 _gt0Index 未及时更新的情况 ,导致抛出这个异常。

引用:

Cocos2dx游戏引擎(3.x)----新的事件分发机制

cocos2dx之event事件(一)

cocos2dx之event事件(三):事件分发器EventDispatcher

Cocos2dx-v3.10 事件分发机制源码解析

(责任编辑:IT教学网)

更多

推荐通讯数据软件文章