除了我们常用的基本节点类型,Cocos2d-x还提供了更多高级节点类型,以帮助构建特殊功能。或许你想制作一个基于瓦片地图的游戏?抑或是一个2D的side-scroller游戏?再或者,你可能想要在游戏中添加粒子效果?Cocos2d-x提供了节点对象来帮助你实现这些目标!
1、瓦片地图
瓦片地图是由一个个的瓦片构成的地图。每个瓦片都可以有独立行为。TMX是一种基于XML的地图格式,它最初被用来设计瓦片式地图,不过由于它支持多种对象类型,所以也适用于更多的普通游戏。TMX对象可以很容易地创建:
// reading in a tiled map。
auto map = TMXTiledMap::create("TileMap。tmx");
addChild(map, 0, 99); // with a tag of '99'
瓦片地图可以有多个图层,由z-order来决定。您可以通过图层名称来访问一个特定图层:
// 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。 所以我们很容易从中挑选特定的瓦片。你可以通过ID来访问任一个瓦片:
// to obtain a specific tiles id
unsigned int gid = layer->getTileGIDAt(Vec2(0, 63));
以瓦片地图的布局为例:
如何创建一个瓦片地图?有很多工具可以来创建。Tiled是一种很流行的工具。它发展速度很快,并且拥有极佳的用户社区。上面的屏幕截图就是Tiled项目的实例。
2、粒子系统
你的游戏可能需要一些类似于燃烧的火焰、咒语施放或爆炸的效果。如何才能实现这些复杂的效果呢?或者,到底能不能实现这些呢?答案是肯定的。使用粒子系统。“粒子系统”这个词指的是一种计算机图形技术,该技术使用了大量非常小的精灵或其他图形对象来模拟某种模糊的现象,而这种效果使用传统渲染技术很难实现。例如一些高度混乱系统、自然现象、或进程导致的化学反应的实例。这里有几个粒子效果的例子:
用于创建粒子效果的工具
你大可选择始终手动创建粒子效果,让每个属性都符合你的喜好。但是我们有一些第三方工具可用于创建粒子效果。包括:
- Particle Designer:一个在Mac上非常强大的粒子效果编辑器
- V-play particle editor:这是一个Cocos2d-x上的跨平台粒子编辑器
- Particle2dx:一个在线Web粒子设计器
这些工具通常导出一个.plist文件,Cocos2d-x读取该文件,以便在游戏中使用你所创造的粒子模型。就像我们接触过的所有其他类一样,我们还是使用create()方法:
// create by plist file
auto particleSystem = ParticleSystem::create("SpinningPeas。plist");
内置粒子效果
你准备好添加粒子效果到你的游戏了吗?我们希望如此!你是否还不太适应创建自定义粒子效果呢?为方便起见,你可以选择一些内置的粒子效果。看一看这个列表:
-
ParticleFire:点粒子系统。使用重力模式。
-
ParticleFireworks:点粒子系统。使用重力模式。
-
ParticleSun:点粒子系统。使用重力模式。
-
ParticleGalaxy:点粒子系统。使用重力模式。
-
ParticleFlower:点粒子系统。使用重力模式。
-
ParticleMeteor:点粒子系统。使用重力模式。
-
ParticleSpiral:点粒子系统。使用重力模式。
-
ParticleExplosion:点粒子系统。使用重力模式。
-
ParticleSmoke:点粒子系统。使用重力模式。
-
ParticleSnow:点粒子系统。使用重力模式。
-
ParticleRain:点粒子系统。使用重力模式。
以使用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 == end
addChild(emitter, 10);
3、视差
视差节点是一种特殊节点类型,模拟了一个滚动视差。你说什么?一个视……什么?是的,视差。简而言之,你可以把一个ParallaxNode认为是一种特殊效果,这个特殊效果让我们从不同的位置观看一个物体的时候,这个物体显示的位置或方向也会不同。举一些简单的例子来说,比如我们从取景器取像或者从相机镜头往外看的时候。你能够想到很多游戏应用这种功能,比如经典的超级马里奥。ParallaxNode对象可以按序列移动,也可由鼠标、触摸、加速计或键盘事件手动移动。
视差节点比普通节点稍微更复杂了一些。为什么呢?因为视差节点需要使用多个节点来起作用。仅一个ParallaxNode是无法正常工作的。你至少需要两个其他的节点对象来完成一个ParallaxNode。通常,在真正的Cocos2d-x风潮中,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) );
OK,不论是看起来还是感觉起来都很熟悉,对吗?注意几件事情!每个新增的节点都被指定一个唯一的z-order,以便他们形成堆栈。还要注意到addchild()中调用的其他两个Vec2类型的参数。这两个参数分别是比例和偏移量。这些参数可以被认为是与父节点的速度比。
4、裁剪节点(ClippingNode)
在平常开发中,我们经常用裁剪节点做新手引导之类。
ClippingNode(裁剪节点)可以用来对节点进行裁剪,可以根据一个模板切割图片的节点,生成任何形状的节点显示。
ClippingNode是Node的子类,可以像普通节点一样放入Layer,Scene,Node中。
-
ClippingNode 原理:
ClippingNode是利用模板遮罩来完成对Node区域裁剪的技术。
##ClippingNode 常用方法
-
create
可以使用
static ClippingNode* create();
方法创建一个ClippingNode对象。如下:auto clipper = ClippingNode::create();
也可以使用
static ClippingNode* create(Node *stencil);
方法创建;在创建的时候指定裁剪模板auto stencil = Sprite::create("CloseNormal.png");//模板节点 clipper = ClippingNode::create(stencil);
-
setStencil 可以使用
void setStencil(Node *stencil);
方法设置“裁剪模板”节点。 如下:clipper->setStencil(stencil);//设置裁剪模板
-
setInverted
可以使用
void setInverted(bool inverted);
方法,设置是显示被裁剪的部分,还是显示裁剪。true 显示剩余部分。false显示被剪掉部分。 如下:clipper->setInverted(true);//设置底板可见,显示剩余部分
-
setAlphaThreshold
可以使用
void setAlphaThreshold(GLfloat alphaThreshold);
,设置alpha阈值, 只有模板(stencil)的alpha像素大于alpha阈值(alphaThreshold)时内容才会被绘制。 alpha阈值(threshold)范围应是0到1之间的浮点数。 alpha阈值(threshold)默认为1。 如下:clipper->setAlphaThreshold(0);//设置绘制底板的Alpha值为0
##ClippingNode示例
auto bg = LayerColor::create(Color4B(255, 255, 255,255));
this->addChild(bg, -1);//1
auto stencil = Sprite::create("CloseNormal.png");
stencil->setScale(2);//2
auto clipper = ClippingNode::create();
clipper->setStencil(stencil);//设置裁剪模板 //3
clipper->setInverted(true);//设置底板可见
clipper->setAlphaThreshold(0);//设置绘制底板的Alpha值为0
this->addChild(clipper);//4
auto content = Sprite::create("HelloWorld.png");//被裁剪的内容
clipper->addChild(content);//5
clipper->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
- 添加了一个白色的LayerColor作为背景层。
- 创建一个精灵,作为裁剪模板,并放大2倍
- 创建ClippingNode节点,并设置裁剪模板
- 设置裁剪显示,Alpha阈值,并将裁剪节点加到层中
- 设置被裁剪的内容
5、绘画节点DrawNode
auto drawNode = DrawNode::create();
drawNode->setPosition(Director::getInstance()->getVisibleSize()/2);
addChild(drawNode);
drawNode->drawSegment(Vec2(-100,-100), Vec2(100,100), 5, Color4F(1,1,0,1));
drawNode->drawDot(Vec2(200,200), 20, Color4F(0,0,1,1));
drawNode->drawPoint(Vec2(-200,-200), 20, Color4F(0,0,0,1));
drawNode->drawCircle(Vec2(0,0), 200, 90, 60, true, 1, 1, Color4F(1,1,0,1));