2017-03-06 18:50:05 wlk1229 阅读数 1730

Cocos2d-x 文字显示

声明:本文分析的是cocos2d-x-3.12的代码

cocos底层使用的是OpenGL进行页面渲染,但OpenGL并支持文字的处理,OpenGL主要是用于图像和3D模型的渲染。为了支持文字的渲染,cocos会将文字转换成要显示的图片,然后通过OpenGL把图片显示出来。

 

cocos2d-x 3.x中支持四种文字的处理,都实现在Lable类中,对应了Label的四种类型,        ttf字体TTF、美术字BMFONT、美术字CHARMAP、系统字 STRING_TEXTURE。对于STRING_TEXTURE系统字的Label实现,与其他三种Label有些不一样,系统字采用的是系统字体,cocos没有对应的字体实现,而其他三种Lbael都有对应的字体类型。

 

STRING_TEXTURE系统字Label

系统字的创建

可以通过Label类的以下静态函数创建。

static LabelcreateWithSystemFont(const  std::string& text, const  std::string& font, floatfontSize, const  Size& dimensions = Size::ZERO, TextHAlignment hAlignment = TextHAlignment::LEFT, TextVAlignment vAlignment = TextVAlignment::TOP);

参数: text显示的文字内容
font显示字体的名字。
fontSize字体大小

返回:返回的是一个Label类。

内容的更新

对于所有类型的Label创建完设置新文本后,不会立即生成相应的文字图片,创建的时候只是会设置一个Label需要更新的标志bool Label ::_contentDirty。当需要绘制Label时,如果发现Label内容需要更新则会调用Label::updateContent函数更新文本内容。

 

系统字Label::updateContent函数中会调用createSpriteForSystemFont函数,该函数会创建一个Texture2D纹理,并掉用Texture2D::initWithString函数初始化纹理,生成相应的文字图片。最后使用文字纹理生成一个sprite精灵,保存在Sprite * Label::_textSprite变量中。整个过程和以下几行代码类似:

    auto t = new (std::nothrow)Texture2D;

    t->initWithString("abcdefg", "Arial", 30);

    auto spt = Sprite::createWithTexture(t);

 

显示文字

系统字label是创建一个精灵,然后保存在Label::_textSprite中,所以显示系统中label时就是显示textSprite。以下时Label类绘制的代码。

void Label::drawSelf(bool visibleByCamera, Renderer* renderer, uint32_t flags)

{

    if (_textSprite)

    {

        if (_shadowNode)

        {

            _shadowNode->visit(renderer, _modelViewTransform, flags);

        }

        _textSprite->visit(renderer, _modelViewTransform, flags);

    }

    else if (visibleByCamera && !_utf8Text.empty())

    {

        draw(renderer, _modelViewTransform, flags);

    }

}

Label::drawSelf函数可以看出,如果是系统字则绘制textSprite,否则会调用draw函数绘制。

 

 

Font字体Label

字体Label根据不同字体的实现可以分为三种,分别是字体TTF、美术字BMFONT、美术字CHARMAP。这三种每一种都有对应一种字体实现。

 

TTF字体Label

TTF字体Label对应使用的字体类是FontFreeType类,该字体类接收一个*.ttf字体文件初始化,对应Label的类型是LabelType::BMFONT

Label的创建

Static Label * createWithTTF(const std::string& text, const std::string& fontFilePath, float fontSize, const Size& dimensions = Size::ZERO, TextHAlignment hAlignment = TextHAlignment::LEFT, TextVAlignment vAlignment = TextVAlignment::TOP);

static Label* createWithTTF(const TTFConfig& ttfConfig, const std::string& textTextHAlignment hAlignment = TextHAlignment::LEFT, int maxLineWidth = 0);

 

BMFONT美术字Label

美术字BMFONT的Label对应使用的字体类是FontFNT类,该类美术字由一个配置文件和一张图片组成,图片包含了所有字体中包含的文字,只需要包含几个需要的文字就行,配置文件会记录每个文字所在的位置和大小。FontFNT类只需要通过美术字的配置文件进行初始化就行了。这种美术字可以通过BMFont.exe等软件生成,软件会同时生成配置文件和相应的图片。对应的Label类型是LabelType::BMFONT

Label的创建

Static Label* createWithBMFont(const std::string& bmfontPath, const std::string& text, const TextHAlignment& hAlignment = TextHAlignment::LEFT, int maxLineWidth = 0, const Vec2& imageOffset = Vec2::ZERO);

 

CHARMAP美术字Label

CharMap美术字的Label对应的字体类型是FontCharMap类,该类使用的美术字是一张图片,图片上每个字的长宽都是一样的,且文字是按照ASCII顺序排列的。这类美术字通常可以用于数字的显示。对应的Label类型是LabelType::CHARMAP

 

Label的创建

Static Label * createWithCharMap(const std::string& charMapFile, int itemWidth, int itemHeight, int startCharMap);

Static Label * createWithCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap);

Static Label * createWithCharMap(const std::string& plistFile);

 

字符编码

cocos2d-x中label字符使用的是使用的是unicode编码,创建label时要传入UTF-8字符,C++11起UTF-8字符串可以通过字符串前面添加u8来实现,如:u8"abc中文"。如果传入的不是UTF-8字符串,因为UTF-8兼容ASCII,所以对于英文不会有影响,但是对于中文来说就可能出现乱码或无法显示等等。

对于TTF字体的Label字体中必须包含相应的文字,否则会显示异常,例如使用英文字体显示中文时,中文就无法显示。

如下:


	//字体SourceHanSerifSC-Heavy.otf为一种宋体字,中文字体
	auto label = Label::createWithTTF(u8"Abc中文", "fonts/SourceHanSerifSC-Heavy.otf", 48);
	label->setPosition(visibleSize / 2);
	this->addChild(label);

	//字体arial.ttf为英文字体,不包括中文字符,所以中文显示异常
	auto label2 = Label::createWithTTF(u8"Abc中文", "fonts/arial.ttf", 48);
	label2->setPosition(visibleSize.width / 2, visibleSize.height / 2 - 50);
	this->addChild(label2);

	//没有使用 u8显示会出现乱码
	auto label3 = Label::createWithSystemFont("Abc中文", "宋体", 48);
	label3->setPosition(visibleSize.width / 2, visibleSize.height / 2 - 100);
	this->addChild(label3);

结果:

 

 

字体Font

字体的类图大致如下。

 

 

三种字体类FontFreeTypeFontFNTFontCharMap都是继承至Font。在Label中并不直接使用Font类,而是使用了一个代理类FontAtlas类。FontAtlas类实现了将字体转换成Texture的功能。为了防止同样字体的FontAltas重复创建,Cocos增加了一个FontAtlasCache类,该类有一个unordered_map静态变量,保存了系统中以创建的FontAtlas类。

 

在Label类中一个了FontAtlas变量FontAtlas* _fontAtlas,当创建Font类型的Label是,系统会创建一个相应的FontAtlas变量,并保存在fontAtlas变量中。

 

Font类中有一个接口函数createFontAtlas,该函数可以创建处相应Font类的FontAtlas,在FontAlts里面也会保存相应的字体。

 

2014-03-13 01:04:58 u012510270 阅读数 390

cocos2d简介

Cocos2d作为一个流行的开源游戏引擎,包含了基本的图像处理引擎、声音处理引擎,同时Cocos2d还可以配合物理引擎box2d使用,实现更多仿真效果,是现在较为流行和先进的移动端游戏开发引擎。

cocos2d的基本构架

在cocos2d引擎中,提供了很多实现游戏设计的元素,概括来说,就是很多类,这些类可以完成不同的功能,包括实现人物、场景等,并能完成动画、音乐等。Cocos2d采用场景树结构来管理游戏对象,把一个游戏划分为不同的场景,场景又可以分为不同的层,一个层又可以拥有任意个可见的游戏对象.游戏对象又可以执行Action来修改其属性.每一个时刻都有一个场景在独立运行,通过切换不同的场景来完成一个游戏流程.[1]

1.CCNode类

CCNode是cocos2d中最重要的类,游戏中的每一个逻辑对象都是基于CCNode建立的。CCNode有如下的众多子类,包括场景、层、精灵(可理解为物体)等。除此之外,CCNode类关联一个CCAction类来完成动作控制,包括移动、切换等等,同理,CCAction也将完成所有子类的动作任务。其有如下特点[2]:

a)        是一个容器,可以包含任意多个其它节点.
b)        可以执行一个行为(CCAction)
c)        可以执行一定时的任务回调
d)        拥有坐标变换(transform)信息,如postion,scale,rotation等
e)        由于一个节点可以添加任意个子节点,所有的节点组成一个树状结构,因此父节点的坐标变换会影响子节点在世界坐标系中的坐标,一个节点只能拥有一个父节点

2.CCScene、CCLayer和CCSprite类

如上所说,CCNode会派生出很多子类,其中最多见的就是CCScene、CCLayer和CCSprite类。

CCScene类是游戏里的一个场景,但是每个场景由多个Layer组成,Layer以层叠的方式组成场景,而Sprite则是每个Layer里的每个角色。


参考:

[1][2] http://blog.csdn.net/liangneo/article/details/6770543










2015-09-26 23:19:41 victory08 阅读数 914

1 Cocos2D-x是什么?为什么Cocos2D-x能够跨平台?
Cocos2D-x是基于Cocos2D用C++重新编写的游戏引擎库。Cocos2D-x底层的实现依赖于通用的图形图像库,Cocos2D-x其实是基于图形图像处理的上层做了一层行为和动作的封装,也就是说任何系统只要支持通用的图形图像库,那么使用目标系统的C++编译器,就能够实现Cocos2D-x编写的游戏基于该平台的版本,所以一套Cocos代码打包成不同平台的版本,从而实现跨平台。
2 要准备哪些环境?
(1) Cocos2D-x源码,获取来源Cocos2D-x中国版网站:http://www.cocos.com/
(2) jdk
(3) android SDK + NDK
(4) python
(5) ant
运行环境:
1 操作系统:Windows8
2 Cocos2D-x-3.8.1
3 python2.7.10 注:用Python3.5编译的时候会报错,没有深究,直接换到Python低版本
4 ndk-r10e

第一步:生成android工程
cocos2D-x开发包已经把生成工程的事情封装好了,windows系统下只要执行cocos.py这条命令就能够生成一系列目标平台的工程文件,执行这条命令需要安装Python执行环境,并配置相关的系统变量。
Python安装没什么好说的,直接从官网上下载一个最新的版本安装就行了,安装完成后把安装路径配置到系统的path路径中。配置以下环境变量:
ANT_ROOT
ANDROID_SDK_ROOT
NDK_ROOT
JAVA_HOME
在命令行中,把目录定位到Cocos2d源码的子目录:\tools\cocos2d-console\bin
执行:cocos.py new HelloCocos -p hello.cocos -l cpp -d C:\Users\work\cocos_dir
生成以下目录:
这里写图片描述

第二步:编译生成APK
在命令行执行:cocos run -s C:\Users\work\cocos_dir\HelloCocos\proj.android -p android -m release

2012-11-23 18:14:45 kaciya 阅读数 1696

cocos2d2.0以后,关于图像处理部分已经全部改为使用shader来进行,下面我们来看看shader的使用过程吧。

首先,shader可以分为2类,一类是自定义的,一类是cocos2d提供的一些默认shader2者使用的方法有所不同。

  • cocos2d提供的默认shader

const GLchar * ccPosition_uColor_frag = 

#import "ccShader_Position_uColor_frag.h"

const GLchar * ccPosition_uColor_vert =

#import "ccShader_Position_uColor_vert.h"

//

const GLchar * ccPositionColor_frag =

#import "ccShader_PositionColor_frag.h"

const GLchar * ccPositionColor_vert =

#import "ccShader_PositionColor_vert.h"

//

const GLchar * ccPositionTexture_frag =

#import "ccShader_PositionTexture_frag.h"

const GLchar * ccPositionTexture_vert =

#import "ccShader_PositionTexture_vert.h"

//

const GLchar * ccPositionTextureA8Color_frag =

#import "ccShader_PositionTextureA8Color_frag.h"

const GLchar * ccPositionTextureA8Color_vert =

#import "ccShader_PositionTextureA8Color_vert.h"

//

const GLchar * ccPositionTextureColor_frag =

#import "ccShader_PositionTextureColor_frag.h"

const GLchar * ccPositionTextureColor_vert =

#import "ccShader_PositionTextureColor_vert.h"

//

const GLchar * ccPositionTextureColorAlphaTest_frag = 

#import "ccShader_PositionTextureColorAlphaTest_frag.h"

//

const GLchar * ccPositionTexture_uColor_frag = 

#import "ccShader_PositionTexture_uColor_frag.h"

const GLchar * ccPositionTexture_uColor_vert = 

#import "ccShader_PositionTexture_uColor_vert.h"

这些shader被包装在CCShaderCache类中,如果要调用,可以通过以下函数来进行

1、初始化shader以及shaderProgram

self.shaderProgram = [[CCShaderCachesharedShaderCache]programForKey:kCCShader_PositionTextureColor]

2、使用shader

[shaderProgram_ use]

3、决定使用哪些属性

ccGLEnableVertexAttribs(kCCVertexAttribFlag_PosColorTex )

4、为各个属性赋值,这些值将传入shader

// vertex

NSInteger diff =offsetof(ccV3F_C4B_T2F,vertices);

glVertexAttribPointer(kCCVertexAttrib_Position,3,GL_FLOAT, GL_FALSE,kQuadSize, (void*) (offset + diff));

// texCoods

diff = offsetof(ccV3F_C4B_T2F,texCoords);

glVertexAttribPointer(kCCVertexAttrib_TexCoords,2,GL_FLOAT, GL_FALSE,kQuadSize, (void*)(offset + diff));

// color

diff = offsetof(ccV3F_C4B_T2F,colors);

glVertexAttribPointer(kCCVertexAttrib_Color,4,GL_UNSIGNED_BYTE,GL_TRUE, kQuadSize, (void*)(offset + diff));

5、画出图形

glDrawArrays(GL_TRIANGLE_STRIP,0,4);

  • 自定义的Shader

这方面的主要函数都被包装在CCGLProgram类中

1、初始化shaderProgram

self.shaderProgram = [[CCGLProgramalloc]initWithVertexShaderByteArray:ccPositionTextureColor_vertfragmentShaderByteArray:Mask_frag];

2、将shader中的属性变量与访问索引绑定起来

cocos2d提供的shader的绑定方法:

[shaderProgram_addAttribute:kCCAttributeNamePositionindex:kCCVertexAttrib_Position];

[shaderProgram_addAttribute:kCCAttributeNameColorindex:kCCVertexAttrib_Color];

[shaderProgram_addAttribute:kCCAttributeNameTexCoordindex:kCCVertexAttrib_TexCoords];

3、链接shaderProgram_

[shaderProgram_link];

4、将程序中与shader中的各个参数绑定起来

如果前面属性变量没有绑定,那么也可以通过以下方式绑定

_positionSlot = glGetAttribLocation(shaderProgram_->program_,, "a_Position");

UniForms矩阵与shader中的矩阵绑定

[shaderProgram_updateUniforms];

自定义Shader变量的获取方法:

_maskLocation = glGetUniformLocation(shaderProgram_->program_,"u_mask");

5、使用Shader

[shaderProgram_use];

6、设置传入shader中的参数

//投影矩阵

[shaderProgram_setUniformForModelViewProjectionMatrix];

//属性参数

glVertexAttribPointer(kCCVertexAttrib_Position,3,GL_FLOAT, GL_FALSE,kQuadSize, (void*) (offset + diff));

//自定义参数

[shaderProgram_setUniformLocation:_maskLocationwithI1:1];

7、画图

glDrawArrays(GL_TRIANGLE_STRIP,0,4);



2016-05-18 11:55:04 Robin__Chou 阅读数 1108

1.Cocos2d-x定时器简介

Cocos2d-x中一共有三种定时器:
- 1、帧循环定时器
- 2、一次性定时器
- 3、自定义定时器

三种定时器中帧循环的实时性最高,帧循环定时器是在Cocos2d-x程序界面每帧图像显示时运行的定时器。帧循环定时器常常用于游戏中物体的碰撞检测。
一次性定时器比较好理解,就是定时完之后开始计时,到时间后运行时间处理函数。自定义定时器是用的最多的一种定时器,他可以根据我们自己的实际需要来设置成不同的工作模式。

2、帧循环定时器

使用方法:在init中使用帧循环定时器打开帧循环定时器,打开帧循环定时器的函数是:

scheduleUpdate();       //打开帧循环定时器,需要重载一个update()回调函数

帧循环定时器运行时,会在每一帧重绘的时候去调用一个名字为update的回调函数,所以在Layer类中需要重写update函数。

void update(float delta) override;

完成上述工作时候,在运行过程中就会在每一帧图像重绘的时候调用这个update函数了。有些时候可能还需要关闭帧循环定时器,这时候就需要使用一个函数:

unscheduleUpdate();     //停止帧循环定时器

该函数运行后,帧循环定时器就会被关闭,也就是说不会再去调用update回调函数。

的最多的一种定时器,他可以根据我们自己的实际需要来设置成不同的工作模式。

3、一次性定时器

一次性定时器就是在运行过程中只会调用依次回调函数的定时器。使用示例如下:

//一次性定时器, 2s中后开始执行
scheduleOnce(schedule_selector(T03Schedual::mySchedual), 2);            

该函数有两个参数,第一个参数包装一个类的成员函数(这个成员函数就是回调函数),第二个参数表示在定时后的x s后执行回调函数。

4、自定义定时器

自定义定时器有三个重载的形式:

<1> schedule(schedule_selector(T03Schedual::mySchedual));
<2> schedule(schedule_selector(T03Schedual::mySchedual), 2);
<3> schedule(schedule_selector(T03Schedual::mySchedual), 2.0, 10, 2);
  • <1>形式和帧循环定时器的作用相同,都是在每一帧图像重绘的时候调用回调函数。不同的是,因为自定义定时器的第一个参数包装的是一个类成员函数,所以该成员函数是自定义的名称。
  • <2>在<1>的基础上添加了一个参数,该参数表示的是调用的时间间隔。
  • <3>在<2>的基础上增加两个参数,依次表示,重复调用的次数(该次数+1),延时x s后开始定时。

5、定时器的使用

游戏动画的本质就是界面的重新绘制。使用定时器,在定时器中完成精灵的移动就可以完成动画的效果。代码涉及到 getChildByTag(),该函数的功能是从渲染树上获取Tag为固定值得精灵。下面代码实现使用定时器绘制在界面上左右移动的精灵,精灵的添加是在init函数中完成。
- (1)添加精灵

    CCSprite *spr = CCSprite::create("woman.png");
    spr->setScale(0.3);
    CCSize sz = CCDirector::sharedDirector()->getWinSize();
    spr->setPosition(ccp(100, sz.height / 2));
    spr->setTag(100);
    addChild(spr);
  • (2)定时器完成精灵的移动
void T03Schedual::mySchedual(float dt)
{
    CCSprite *spr = (CCSprite*)(getChildByTag(100));
    float v = 300 / 2;
    static bool flag = true;    //向右走
    if (flag)
    {
        spr->setPositionX(spr->getPositionX() + v*dt);
        if (spr->getPositionX() >= 400)
            flag = !flag;
    }
    else
    {
        spr->setPositionX(spr->getPositionX() - v*dt);
        if (spr->getPositionX() <= 100)
            flag = !flag;
    }
    //CCLog("Once Timer %g\n", dt);
}

运行结果:

Alt text

Alt text

cocos2d-x 图片变灰

阅读数 1714

没有更多推荐了,返回首页