学习小计(部分摘自cocos官方文档)1
1.AutoPolygon
裁剪矩形图片的透明部分,使资源所占空间更小。
AutoPolygon
是一个工具类,它可以在程序运行时,通过跟踪关键点和三角测量,将一个矩形图像划分成一系列小三角形块。
首先将图像资源传入 AutoPolygon
进行处理,然后我们使用它生成的对象进行精灵的创建就能得到多边形精灵。
用法:
// Generate polygon info automatically.
auto polygon = AutoPolygon::generatePolygon("图片资源文件名”);
// Create a sprite with polygon info.
//参数polygon为上行所创建的多边形对象;
auto sprite = Sprite::createwith(polygon );
2.动作的倒转
倒转(Reverse) 的功能也和字面意思一样,调用 reverse()
可以让一系列动作按相反的方向执行。reverse()
不是只能简单的让一个Action
对象反向执行,还能让 Sequence
和Spawn
倒转。
用法:
//返回值为actionname的反转动作对象
actionname->reverse();
3.场景图(Scene Graph)
场景图(Scene Graph)是一种安排场景内对象的数据结构,它把场景内所有的 节点(Node) 都包含在一个 树(tree) 上。(场景图虽然叫做"图",但实际使用一个树结构来表示)。
听起来这好像很复杂,可能你会问,我为什么要关注这个技术细节,Cocos2d-x 值得我研究的这么深入吗?值得!这个对你真正了解渲染器是如何绘制场景的非常重要。
当你开发游戏的时候,你会添加一些节点,精灵和动画到一个场景中,你期望的是每一个添加的对象都能被正确的展示,可是如果有个对象没有被展示呢?可能你错误的把这个对象隐藏到背景中了。怎么办?别着急,这是个小问题,停下来,拿出一张纸,把场景图画出来,你肯定能很容易的发现错误。
既然场景图是一个树结构,你就能遍历它,Cocos2d-x 使用 中序遍历
,先遍历左子树,然后根节点,最后是右子树。中序遍历下图的节点,能得到A, B, C, D, E, F, G, H, I
这样的序列。
初步了解了场景图,让我们看一下这个游戏场景。
分解这个场景,看一下它有哪些元素,这些最终会被渲染为一个树。
另一点要考虑的是,z-order 为负的元素,z-order 为负的节点会被放置在左子树,非负的节点会被放在右子树。实际开发的过程中,你可以按照任意顺序添加对象,他们会按照你指定的 z-order 自动排序。
4.瓦片地图
在游戏开发过程中,我们会遇到超过屏幕大小的地图,例如在即时战略游戏中,它使得玩家可以在地图中滚动游戏画面。这类游戏通常会有丰富的背景元素,如果直接使用背景图切换的方式,需要为每个不同的场景准备一张背景图,而且每个背景图都不小,这样会造成资源浪费。
瓦片地图就是为了解决这问题而产生的。一张大的世界地图或者背景图可以由几种地形来表示,每种地形对应一张小的的图片,我们称这些小的地形图片为瓦片。把这些瓦片拼接在一起,一个完整的地图就组合出来了,这就是瓦片地图的原理。
在 Cocos2d-x 中,瓦片地图实现的是 TileMap 方案,TileMap 要求每个瓦片占据地图上一个四边形或六边形的区域。把不同的瓦片拼接在一起,就可以组成完整的地图。TileMap 使用一种基于 XML 的 TMX 格式文件。
使用 TMX 文件创建一个瓦片地图:
// reading in a tiled map.
auto map = TMXTiledMap::create("TileMap.tmx");
addChild(map, 0, 99); // with a tag of '99'
瓦片地图可能有许多层,通过层名获取到一个特定的层。
// how to get a specific layer
auto map = TMXTiledMap::create("TileMap.tmx");
auto layer = map->getLayer("Layer0");
auto tile = layer->getTileAt(Vec2(1, 63));
每个瓦片都有独一无二的位置和 ID,这使得我们很容易选择特定的瓦片。
通过位置访问:
// to obtain a specific tiles id
unsigned int gid = layer->getTileGIDAt(Vec2(0, 63));
5.粒子系统
粒子系统是指计算机图形学中模拟特定现象的技术,它在模仿自然现象、物理现象及空间扭曲上具备得天独厚的优势,能为我们实现一些真实自然而又带有随机性的效果(如爆炸、烟花、水流)提供了方便。Cocos2d-x引擎中就为我们提供了强大的粒子系统。
下面是使用粒子系统完成的两个粒子特效:
创建粒子特效的工具
尽管你能手动创建粒子特效,按照喜好确定每个属性,但是使用工具往往更方便高效。下面介绍几个第三方工具:
- Particle Designer:Mac 上一款非常强大的粒子特效编辑器
- V-play particle editor:一款跨平台的粒子特效编辑器
- Particle2dx:一款 Web 粒子特效编辑器,打开网页即可进行设计
使用这些工具完成粒子特效的设计,最终会导出一个 .plist 文件,Cocos2d-x 通过使用这种文件,就能把粒子特效添加到场景中,添加方法和操作一个普通的节点类型一样。
创建方法:
// create by plist file
auto particleSystem = ParticleSystem::create("SpinningPeas.plist");
内置粒子特效
准备好添加粒子特效到你的游戏中了吗?是否习惯创建自定义粒子特效?不习惯也没关系,我们内置了一些粒子特效,你可以直接使用。这个列表都是:
- ParticleFire: Point particle system. Uses Gravity mode.
- ParticleFireworks: Point particle system. Uses Gravity mode.
- ParticleSun: Point particle system. Uses Gravity mode.
- ParticleGalaxy: Point particle system. Uses Gravity mode.
- ParticleFlower: Point particle system. Uses Gravity mode.
- ParticleMeteor: Point particle system. Uses Gravity mode.
- ParticleSpiral: Point particle system. Uses Gravity mode.
- ParticleExplosion: Point particle system. Uses Gravity mode.
- ParticleSmoke: Point particle system. Uses Gravity mode.
- ParticleSnow: Point particle system. Uses Gravity mode.
- ParticleRain: Point particle system. Uses Gravity mode.
比如使用内置的烟火特效 ParticleFireworks
:
auto emitter = ParticleFireworks::create();addChild(emitter, 10);
是这样的效果:
要是内置的粒子特效不是你想要的那样,也没关系,你可以直接手动设置参数!让我们拿上面的烟火特效示例,并通过手动改变属性进一步控制。
auto emitter = ParticleFireworks::create();// set the duration
emitter->setDuration(ParticleSystem::DURATION_INFINITY);// radius mode
emitter->setEmitterMode(ParticleSystem::Mode::RADIUS);// radius mode: 100 pixels from center
emitter->setStartRadius(100);
emitter->setStartRadiusVar(0);
emitter->setEndRadius(ParticleSystem::START_RADIUS_EQUAL_TO_END_RADIUS);
emitter->setEndRadiusVar(0); // not used when start == endaddChild(emitter, 10);
6.视差滚动
视差滚动是指让多层背景以不同的速度移动,从而形成的立体运动效果。比如超级马里奥游戏中,角色所在地面的移动与背景天空的移动,就是一个视差滚动。Cocos2d-x 通过ParallaxNode
对象模拟视差滚动。可以通过序列控制移动,也可以通过监听鼠标,触摸,加速度计,键盘等事件控制移动。ParallaxNode
对象比常规节点对象复杂一些,因为为了呈现不同的移动速度,需要多个子节点。它类似Menu
像一个容器,本身不移动,移动的是被添加进入其中的不同子节点。ParallaxNode
的创建:
// create ParallaxNode
auto paraNode = ParallaxNode::create();
添加多个节点对象:
// create ParallaxNode
auto paraNode = ParallaxNode::create();// background image is moved at a ratio of 0.4x, 0.5y
paraNode->addChild(background, -1, Vec2(0.4f,0.5f), Vec2::ZERO);// tiles are moved at a ratio of 2.2x, 1.0y
paraNode->addChild(middle_layer, 1, Vec2(2.2f,1.0f), Vec2(0,-200) );// top image is moved at a ratio of 3.0x, 2.5y
paraNode->addChild(top layer, 2, Vec2(3.0f,2.5f), Vec2(200,800) );
需要注意的是,被添加的每个 Node 对象被赋予了一个唯一的 z-order
顺序,以便他们堆叠在彼此之上。另外要注意addChild()
调用中两个 Vec2
参数,第一个决定这个子节点的移动速度与父节点移动速度的比率,第二个是相对父节点ParallaxNode
的偏移量。
7.键盘事件
对于桌面游戏,一般需要通过键盘做一些游戏内的控制,这时你就需要监听键盘事件。Cocos2d-x 支持键盘事件,就像上节介绍的触摸事件一样。
创建键盘事件监听器:
// creating a keyboard event listener
auto listener = EventListenerKeyboard::create();
listener->onKeyPressed = CC_CALLBACK_2(KeyboardTest::onKeyPressed, this);
listener->onKeyReleased = CC_CALLBACK_2(KeyboardTest::onKeyReleased, this);_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);// Implementation of the keyboard event callback function prototype
void KeyboardTest::onKeyPressed(EventKeyboard::KeyCode keyCode, Event* event)
{log("Key with keycode %d pressed", keyCode);
}void KeyboardTest::onKeyReleased(EventKeyboard::KeyCode keyCode, Event* event)
{log("Key with keycode %d released", keyCode);
}
可以看到,在使用键盘事件监听器时,可以监听两种不同的事件,每一个事件都有自己的触发时机。
两种事件及触发时机:
onKeyPressed
按键被按下时onKeyReleased
按下状态的按键被放开时
8.加速度传感器事件
现在一些移动设备配备有加速度传感器,我们可以通过监听它的事件获取各方向的加速度。
可以设想要完成一个游戏情景:通过来回移动手机,平衡小球在手机中的位置。这种场景的完成,就需要监听加速度传感器事件。
使用加速度传感器,需要先启用
Device::setAccelerometerEnabled(true);
创建加速度传感器监听器:
// creating an accelerometer event
auto listener = EventListenerAcceleration::create(CC_CALLBACK_2(
AccelerometerTest::onAcceleration, this));_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);// Implementation of the accelerometer callback function prototype
void AccelerometerTest::onAcceleration(Acceleration* acc, Event* event)
{// Processing logic here
}
9.鼠标事件
就像前几节介绍的那样,Cocos2d-x 支持响应鼠标事件
创建鼠标事件监听器:
_mouseListener = EventListenerMouse::create();
_mouseListener->onMouseMove = CC_CALLBACK_1(MouseTest::onMouseMove, this);
_mouseListener->onMouseUp = CC_CALLBACK_1(MouseTest::onMouseUp, this);
_mouseListener->onMouseDown = CC_CALLBACK_1(MouseTest::onMouseDown, this);
_mouseListener->onMouseScroll = CC_CALLBACK_1(MouseTest::onMouseScroll, this);_eventDispatcher->addEventListenerWithSceneGraphPriority(_mouseListener, this);void MouseTest::onMouseDown(Event *event)
{// to illustrate the event....EventMouse* e = (EventMouse*)event;string str = "Mouse Down detected, Key: ";str += tostr(e->getMouseButton());
}void MouseTest::onMouseUp(Event *event)
{// to illustrate the event....EventMouse* e = (EventMouse*)event;string str = "Mouse Up detected, Key: ";str += tostr(e->getMouseButton());
}void MouseTest::onMouseMove(Event *event)
{// to illustrate the event....EventMouse* e = (EventMouse*)event;string str = "MousePosition X:";str = str + tostr(e->getCursorX()) + " Y:" + tostr(e->getCursorY());
}void MouseTest::onMouseScroll(Event *event)
{// to illustrate the event....EventMouse* e = (EventMouse*)event;string str = "Mouse Scroll detected, X: ";str = str + tostr(e->getScrollX()) + " Y: " + tostr(e->getScrollY());
}
10.是否需要使用物理引擎
当你的需求很简单时,就不要使用物理引擎。比如只需要确定两个对象是否有碰撞,结合使用节点对象的update
函数和 Rect 对象的containsPoint()
,intersectsRect()
方法可能就足够了。例如:
void update(float dt)
{auto p = touch->getLocation();auto rect = this->getBoundingBox();if(rect.containsPoint(p)){// do something, intersection}
}
这种检查交集以确定两个对象是否有碰撞的方法,只能解决非常简单的需求,无法扩展。比如你要开发一个游戏,一个场景有 100 个精灵对象,需要判断它们互相是否有碰撞,如果使用这种方式那将非常复杂,同时性能消耗还会严重影响 CPU 的使用率和游戏运行的帧率,这游戏根本没法玩。这个时候就需要物理引擎了,在模拟物理情景上,物理引擎的扩展性好,性能的消耗也低。像刚才提到的那个情景,使用物理引擎就能很好的解决。初次了解物理引擎的话,肯定会觉得很陌生,我们来看一个简单的例子,通过例子来介绍术语,或许会容易接受一些。
// create a static PhysicsBody
auto physicsBody = PhysicsBody::createBox(Size(65.0f , 81.0f ), PhysicsMaterial(0.1f, 1.0f, 0.0f));
physicsBody->setDynamic(false);// create a sprite
auto sprite = Sprite::create("whiteSprite.png");
sprite->setPosition(Vec2(400, 400));// sprite will use physicsBody
sprite->addComponent(physicsBody);//add contact event listener
auto contactListener = EventListenerPhysicsContact::create();
contactListener->onContactBegin = CC_CALLBACK_1(onContactBegin, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);
虽然上面这个例子已经很简单了,但你可能还是觉得它复杂得有点吓人?别害怕,仔细的分析一下,就会发现也没那么复杂。代码流程:
PhysicsBody
对象创建Sprite
对象创建PhysicsBody
对象以组件的形式被添加到Sprite
对象- 创建监听器以响应
onContactBegin()
事件
保持耐心,一旦我们一步一步的去分析,慢慢的就能理解这个过程。
学习小计(部分摘自cocos官方文档)1相关推荐
- 学习小计(部分摘自cocos官方文档) 2
11.碰撞 你是否看到过车祸?是否跟什么物体相撞过?就像车的相撞一样,刚体对象也可以互相碰撞,当它们互相接触的时候,就认为发生了碰撞.当碰撞发生时,会触发一系列事件,它可以被完全忽略. 碰撞筛选 ...
- 微信小程序(note1:官方文档)
官方文档 关于微信小程序这块儿,主要练习怎么查看文档,因为微信开发文档特别全面,没有必要再额外写什么笔记. 但是对小程序开发文档的熟练度是非常重要的,所以此系列笔记,着重于常用的组件.接口- 微信小程 ...
- tensorflow学习笔记十7:tensorflow官方文档学习 How to Retrain Inception's Final Layer for New Categories
现代物体识别模型有数以百万计的参数,可能需要数周才能完全训练.学习迁移是一个捷径,很多这样的工作,以充分的训练模式的一组类ImageNet技术,并从现有的权重进行新课.在这个例子中,我们将从头再训练最 ...
- YII2 路由问题-摘自yii2官方文档
路由 当入口脚本在调用 run() 方法时,它进行的第一个操作就是解析输入的请求,然后实例化对应的控制器动作处理这个请求. 该过程就被称为引导路由(routing). 路由相反的操作会将给定的路由和参 ...
- UE4学习(一)C++编程官方文档解读
文档地址:https://docs.unrealengine.com/zh-CN/Programming/Introduction/index.html 文档详细介绍了C++编程的基础,一些宏和常用变 ...
- 微信小程序学习记录【1】【项目结构构成、官方文档构成、基本配置】
微信小程序学习记录[1][项目结构构成.基本配置]文章目录 项目结构构成 官方文档结构 基本配置 1. 小程序配置 1.1 app.json 1.2 page(页面名).json 1.3 sitema ...
- 微信小程序入门:初步了解官方文档(循环、视图容器、icon、image)
今天是正式学习微信小程序的第一天,学习微信小程序先从了解官方文档开始吧. 这一节开始学习微信小程序官方文档中的for循环.视图容器.icon.image等. 打开index文件夹下的index.wxm ...
- mysql中括号_手把手教你看MySQL官方文档
前言: 在学习和使用MySQL的过程中,难免会遇到各种问题.不知道当你遇到相关问题时会怎么做,我在工作或写文章的过程中,遇到不懂或需要求证的问题时通常会去查阅官方文档.慢慢的,阅读文档也有了一些经验, ...
- 如何全文搜索oracle官方文档
如何全文搜索oracle官方文档 [技巧]如何全文搜索oracle官方文档 一.1 BLOG文档结构图 一.2 导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它 ...
最新文章
- Python 图像处理简介——色彩阴影调整
- php-fpm 启动参数及重要配置详解
- XtraBackup出现 Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock'
- RabbitMQ创建远程连接用户
- Android动画之Tween动画实战
- 【page-monitor 前端自动化 上篇】初步调研
- 缓存nginx服务器的静态文件
- list可以存放python中任意类型的数据_Python中常见的数据类型小结
- ROS学习笔记-ROS语音识别与语音输出[1]
- python交互模式设置及VIM的tab补齐
- 单片机开发与Linux开发有何不同?
- Qt通过ODBC读取excel文件
- tableau获取筛选器值_认识Tableau中的筛选器
- Java笔记-Java端口扫描功能(含TCP包分析以及原理)
- DSB2017第一名代码尝试运行(记录自用)(一)
- Win7下 OpenCV+Qt开发环境搭建
- 简用计算机,你真的会使用“计算器”吗?
- OpenCV morphologyEx、erode、dilate、getStructuringElement (形态学算子)
- 关闭此标签页 关闭所有标签页easyUI
- 2012.4.19总结(一)
热门文章
- Google Earth Engine(GEE)——土地分类/覆盖案例分析含各类土地面积统计和精度评定(印度班加罗尔为例)
- 2021小红书国际妇女节营销报告
- OSChina 娱乐弹弹弹——程序猿其实很好找女朋友!
- [原创]ExtAspNet秘密花园(二) mdash; 一切从头开始
- 【TCP/IP网络协议】(五)传输层UDP协议
- dubbo-monitor启动异常之Native memory allocation (mmap) failed to map 1879048192 bytes for committing rese
- k8s创建pod资源失败OCI runtime create failed systemd cgroup flag passed, but systemd support for managing c
- python调用通达信函数_mootdx: 通达信数据读取 pytdx 的一个简便使用封装
- mmc/eMMC/SD-card/SPI/SDIO
- ELK收集nginx日志并展示来源IP城市分布图