Cocos2dx-- 聊天系统之富文本(RichText)与字体对齐

2023-05-16

前言

游戏开发中我们一般都会有聊天系统,我们可以同时或单独发文字,图片,表情,超链接等信息的文本即称为富文本。如下图所示:
这里写图片描述

我使用的是cocos-3.4引擎版本里的RichText富文本控件实现这些操作的,但cocos自带封装的RichText还有一些问题,1:如上图看到的一样,当中英文混输时右边字体没对齐(看需求,QQ都没处理这问题)。2:聊天信息有时会需求像上面一样还要一个背景底框装着,底框大小随发送内容变化,这时我们就需要知道富文本的宽度和高度而cocos的RichText没有封装这个接口需要我们自己扩展。本章就讲讲怎么来解决这两个问题。

解决步骤

1,在UIRichText.h中新增获取富文本大小接口

public:
Size xxgetRealSize();
Size xxrealSize;

2,默认右没不齐是因为它的换行是根据字的平均长度来计算的,即单个字长度=总长度/总字数,而不同字的宽度是很可能不相同的。现在我的改法是:循环计算出每个字的大小求和换行,当然这样的效率是比默认的低,所以这个对齐还是看需求,有的QQ消息也没处理这个对齐问题。下面是UIRichText.cpp修改后的完整代码,有注释,修改处都用@cxx标记了。

/****************************************************************************
 Copyright (c) 2013 cocos2d-x.org

 http://www.cocos2d-x.org

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 ****************************************************************************/

#include "UIRichText.h"
#include "platform/CCFileUtils.h"
#include "2d/CCLabel.h"
#include "2d/CCSprite.h"
#include "base/ccUTF8.h"
#include "ui/UIHelper.h"

#include "platform/CCDevice.h"  //@cxx
#include "base/ccMacros.h"  //@cxx
#include "base/CCDirector.h" //@cxx

NS_CC_BEGIN

namespace ui {


bool RichElement::init(int tag, const Color3B &color, GLubyte opacity)
{
    _tag = tag;
    _color = color;
    _opacity = opacity;
    return true;
}


RichElementText* RichElementText::create(int tag, const Color3B &color, GLubyte opacity, const std::string& text, const std::string& fontName, float fontSize)
{
    RichElementText* element = new (std::nothrow) RichElementText();
    if (element && element->init(tag, color, opacity, text, fontName, fontSize))
    {
        element->autorelease();
        return element;
    }
    CC_SAFE_DELETE(element);
    return nullptr;
}

bool RichElementText::init(int tag, const Color3B &color, GLubyte opacity, const std::string& text, const std::string& fontName, float fontSize)
{
    if (RichElement::init(tag, color, opacity))
    {
        _text = text;
        _fontName = fontName;
        _fontSize = fontSize;
        return true;
    }
    return false;
}

RichElementImage* RichElementImage::create(int tag, const Color3B &color, GLubyte opacity, const std::string& filePath)
{
    RichElementImage* element = new (std::nothrow) RichElementImage();
    if (element && element->init(tag, color, opacity, filePath))
    {
        element->autorelease();
        return element;
    }
    CC_SAFE_DELETE(element);
    return nullptr;
}

bool RichElementImage::init(int tag, const Color3B &color, GLubyte opacity, const std::string& filePath)
{
    if (RichElement::init(tag, color, opacity))
    {
        _filePath = filePath;
        return true;
    }
    return false;
}

RichElementCustomNode* RichElementCustomNode::create(int tag, const Color3B &color, GLubyte opacity, cocos2d::Node *customNode)
{
    RichElementCustomNode* element = new (std::nothrow) RichElementCustomNode();
    if (element && element->init(tag, color, opacity, customNode))
    {
        element->autorelease();
        return element;
    }
    CC_SAFE_DELETE(element);
    return nullptr;
}

bool RichElementCustomNode::init(int tag, const Color3B &color, GLubyte opacity, cocos2d::Node *customNode)
{
    if (RichElement::init(tag, color, opacity))
    {
        _customNode = customNode;
        _customNode->retain();
        return true;
    }
    return false;
}

RichText::RichText():
_formatTextDirty(true),
_leftSpaceWidth(0.0f),
_verticalSpace(0.0f),
_elementRenderersContainer(nullptr)
{

}

RichText::~RichText()
{
    _richElements.clear();
}

RichText* RichText::create()
{
    RichText* widget = new (std::nothrow) RichText();
    if (widget && widget->init())
    {
        widget->autorelease();
        return widget;
    }
    CC_SAFE_DELETE(widget);
    return nullptr;
}

bool RichText::init()
{
    if (Widget::init())
    {
        return true;
    }
    return false;
}

void RichText::initRenderer()
{
    _elementRenderersContainer = Node::create();
    _elementRenderersContainer->setAnchorPoint(Vec2(0.5f, 0.5f));
    addProtectedChild(_elementRenderersContainer, 0, -1);
}

void RichText::insertElement(RichElement *element, int index)
{
    _richElements.insert(index, element);
    _formatTextDirty = true;
}

void RichText::pushBackElement(RichElement *element)
{
    _richElements.pushBack(element);
    _formatTextDirty = true;
}

void RichText::removeElement(int index)
{
    _richElements.erase(index);
    _formatTextDirty = true;
}

void RichText::removeElement(RichElement *element)
{
    _richElements.eraseObject(element);
    _formatTextDirty = true;
}

    //渲染富文本
void RichText::formatText()
{
    if (_formatTextDirty)
    {
        _elementRenderersContainer->removeAllChildren();
        _elementRenders.clear();
        if (_ignoreSize) //是否忽略换行
        {
            addNewLine();
            for (ssize_t i=0; i<_richElements.size(); i++)
            {
                RichElement* element = _richElements.at(i);
                Node* elementRenderer = nullptr;
                switch (element->_type)
                {
                    case RichElement::Type::TEXT:
                    {
                        RichElementText* elmtText = static_cast<RichElementText*>(element);
                        if (FileUtils::getInstance()->isFileExist(elmtText->_fontName))
                        {
                            elementRenderer = Label::createWithTTF(elmtText->_text.c_str(), elmtText->_fontName, elmtText->_fontSize);
                        }
                        else
                        {
                            elementRenderer = Label::createWithSystemFont(elmtText->_text.c_str(), elmtText->_fontName, elmtText->_fontSize);
                        }
                        break;
                    }
                    case RichElement::Type::IMAGE:
                    {
                        RichElementImage* elmtImage = static_cast<RichElementImage*>(element);
                        elementRenderer = Sprite::create(elmtImage->_filePath.c_str());
                        break;
                    }
                    case RichElement::Type::CUSTOM:
                    {
                        RichElementCustomNode* elmtCustom = static_cast<RichElementCustomNode*>(element);
                        elementRenderer = elmtCustom->_customNode;
                        break;
                    }
                    default:
                        break;
                }
                elementRenderer->setColor(element->_color);
                elementRenderer->setOpacity(element->_opacity);
                pushToContainer(elementRenderer);
            }
        }
        else
        {
            addNewLine();
            for (ssize_t i=0; i<_richElements.size(); i++)
            {

                RichElement* element = static_cast<RichElement*>(_richElements.at(i));
                switch (element->_type)
                {
                    case RichElement::Type::TEXT:
                    {
                        RichElementText* elmtText = static_cast<RichElementText*>(element);
                        handleTextRenderer(elmtText->_text.c_str(), elmtText->_fontName.c_str(), elmtText->_fontSize, elmtText->_color, elmtText->_opacity);
                        break;
                    }
                    case RichElement::Type::IMAGE:
                    {
                        RichElementImage* elmtImage = static_cast<RichElementImage*>(element);
                        handleImageRenderer(elmtImage->_filePath.c_str(), elmtImage->_color, elmtImage->_opacity);
                        break;
                    }
                    case RichElement::Type::CUSTOM:
                    {
                        RichElementCustomNode* elmtCustom = static_cast<RichElementCustomNode*>(element);
                        handleCustomRenderer(elmtCustom->_customNode);
                        break;
                    }
                    default:
                        break;
                }
            }
        }
        formarRenderers();
        _formatTextDirty = false;
    }
}

//begin @cxx   得到一行文字的个数
bool s_getLineTextNumber(const std::string& text, const std::string& fontName, float fontSize , float rowWidth , int &textNumber)
{
    bool ret =  true ;
    float maxW = rowWidth ;
    int count = 0 ;

    while(true)
    {
        std::string tempChar = Helper::getSubStringOfUTF8String(text,count,1);  //截取字符串
        float tempW,tempH ;
        if(tempChar.length() == 0 )
        {
            break ;
        }
        bool bSuccess = Device::CalculateTextSize(tempChar.c_str(),fontName.c_str(),fontSize, tempW, tempH);
        if( !bSuccess )
        {
            ret = false ;
            break ;
        }
        //tempW = tempW / CC_CONTENT_SCALE_FACTOR();

        maxW -= tempW ;
        if(maxW< -tempW / 2)
        {
            break ;
        }
        count++ ;
    }

    textNumber = count ;

    return ret ;
}
//end @cxx

void RichText::handleTextRenderer(const std::string& text, const std::string& fontName, float fontSize, const Color3B &color, GLubyte opacity)
{
    auto fileExist = FileUtils::getInstance()->isFileExist(fontName);
    Label* textRenderer = nullptr;
    if (fileExist)
    {
        textRenderer = Label::createWithTTF(text, fontName, fontSize);
    } 
    else
    {
        textRenderer = Label::createWithSystemFont(text, fontName, fontSize);
    }
    float textRendererWidth = textRenderer->getContentSize().width;
    float saveLeftSpaceWidth = _leftSpaceWidth ; //@cxx
    _leftSpaceWidth -= textRendererWidth;
    if (_leftSpaceWidth < 0.0f)
    {
        float overstepPercent = (-_leftSpaceWidth) / textRendererWidth;
        std::string curText = text;
        size_t stringLength = StringUtils::getCharacterCountInUTF8String(text);

        //原来代码(原来是求出整个文字长度和文字个数,用平均长度作为每个字长度,所以混输对不齐)
        //int leftLength = stringLength * (1.0f - overstepPercent);
        //std::string leftWords = Helper::getSubStringOfUTF8String(curText,0,leftLength);
        //std::string cutWords = Helper::getSubStringOfUTF8String(curText, leftLength, stringLength - leftLength);

        //begin @cxx  现在改为循环计算每个字的长度
        int leftLength = 0 ;
        std::string leftWords = "" ;
        std::string cutWords = "" ;

        float rowWidth = saveLeftSpaceWidth ; //_customSize.width ;
        int textNumber = 0  ;
        if( s_getLineTextNumber( curText, fontName, fontSize , rowWidth , textNumber) )//计算一行多少字
        {
            leftLength = textNumber ;
            leftWords = Helper::getSubStringOfUTF8String(curText,0,leftLength);
            cutWords = Helper::getSubStringOfUTF8String(curText, leftLength, stringLength - leftLength);
        }
        else
        {
            leftLength = stringLength * (1.0f - overstepPercent);
            leftWords = Helper::getSubStringOfUTF8String(curText,0,leftLength);
            cutWords = Helper::getSubStringOfUTF8String(curText, leftLength, stringLength - leftLength);
        }
        //end of @cxx

        if (leftLength > 0)
        {
            Label* leftRenderer = nullptr;
            if (fileExist)
            {
                leftRenderer = Label::createWithTTF(Helper::getSubStringOfUTF8String(leftWords, 0, leftLength), fontName, fontSize);
            }
            else
            {
                leftRenderer = Label::createWithSystemFont(Helper::getSubStringOfUTF8String(leftWords, 0, leftLength), fontName, fontSize);
            }
            if (leftRenderer)
            {
                leftRenderer->setColor(color);
                leftRenderer->setOpacity(opacity);
                pushToContainer(leftRenderer);
            }
        }

        addNewLine();
        handleTextRenderer(cutWords.c_str(), fontName, fontSize, color, opacity);
    }
    else
    {
        textRenderer->setColor(color);
        textRenderer->setOpacity(opacity);
        pushToContainer(textRenderer);
    }
}

void RichText::handleImageRenderer(const std::string& fileParh, const Color3B &color, GLubyte opacity)
{
    Sprite* imageRenderer = Sprite::create(fileParh);
    handleCustomRenderer(imageRenderer);
}

void RichText::handleCustomRenderer(cocos2d::Node *renderer)
{
    Size imgSize = renderer->getContentSize();
    _leftSpaceWidth -= imgSize.width;
    if (_leftSpaceWidth < 0.0f)
    {
        addNewLine();
        pushToContainer(renderer);
        _leftSpaceWidth -= imgSize.width;
    }
    else
    {
        pushToContainer(renderer);
    }
}

void RichText::addNewLine()
{
    _leftSpaceWidth = _customSize.width;
    _elementRenders.push_back(new Vector<Node*>());
}

void RichText::formarRenderers()
{
    if (_ignoreSize)
    {
        float newContentSizeWidth = 0.0f;
        float newContentSizeHeight = 0.0f;

        Vector<Node*>* row = (_elementRenders[0]);
        float nextPosX = 0.0f;
        for (ssize_t j=0; j<row->size(); j++)
        {
            Node* l = row->at(j);
            l->setAnchorPoint(Vec2::ZERO);
            l->setPosition(nextPosX, 0.0f);
            _elementRenderersContainer->addChild(l, 1);
            Size iSize = l->getContentSize();
            newContentSizeWidth += iSize.width;
            newContentSizeHeight = MAX(newContentSizeHeight, iSize.height);
            nextPosX += iSize.width;
        }
        _elementRenderersContainer->setContentSize(Size(newContentSizeWidth, newContentSizeHeight));
    }
    else
    {
        float newContentSizeHeight = 0.0f;
        float *maxHeights = new float[_elementRenders.size()];

        for (size_t i=0; i<_elementRenders.size(); i++)
        {
            Vector<Node*>* row = (_elementRenders[i]);
            float maxHeight = 0.0f;
            for (ssize_t j=0; j<row->size(); j++)
            {
                Node* l = row->at(j);
                maxHeight = MAX(l->getContentSize().height, maxHeight);
            }
            maxHeights[i] = maxHeight;
            newContentSizeHeight += maxHeights[i];
        }


        float nextPosY = _customSize.height;
        float realWidth = 0 ;  //@cxx
        for (size_t i=0; i<_elementRenders.size(); i++)
        {
            Vector<Node*>* row = (_elementRenders[i]);
            float nextPosX = 0.0f;
            nextPosY -= (maxHeights[i] + _verticalSpace);

            for (ssize_t j=0; j<row->size(); j++)
            {
                Node* l = row->at(j);
                l->setAnchorPoint(Vec2::ZERO);
                l->setPosition(nextPosX, nextPosY);
                _elementRenderersContainer->addChild(l, 1);
                nextPosX += l->getContentSize().width;
            }

            if( realWidth < nextPosX ) //@cxx
            {
                realWidth = nextPosX ;//@cxx
            }
        }

        float realHeight = _customSize.height - nextPosY;   //@cxx

        //富文本真实宽高
        this->xxrealSize.height = realHeight;               //@cxx
        this->xxrealSize.width = realWidth ; //_contentSize.width;      //@cxx

        _elementRenderersContainer->setContentSize(_contentSize);
        delete [] maxHeights;
    }

    size_t length = _elementRenders.size();
    for (size_t i = 0; i<length; i++)
    {
        Vector<Node*>* l = _elementRenders[i];
        l->clear();
        delete l;
    }    
    _elementRenders.clear();

    if (_ignoreSize)
    {
        Size s = getVirtualRendererSize();
        this->setContentSize(s);
    }
    else
    {
        this->setContentSize(_customSize);
    }
    updateContentSizeWithTextureSize(_contentSize);
    _elementRenderersContainer->setPosition(_contentSize.width / 2.0f, _contentSize.height / 2.0f);
}

//获得富文本大小
Size RichText::xxgetRealSize()//@cxx
{
    //this->xxrealSize =  this->getContentSize();
    this->formatText();   //需要手动调用
    return this->xxrealSize;
}

//下帧drawScene时调用(基类调过来),这里是富文本渲染入口
void RichText::adaptRenderers()
{
    this->formatText();
}

void RichText::pushToContainer(cocos2d::Node *renderer)
{
    if (_elementRenders.size() <= 0)
    {
        return;
    }
    _elementRenders[_elementRenders.size()-1]->pushBack(renderer);
}

void RichText::setVerticalSpace(float space)
{
    _verticalSpace = space;
}

void RichText::setAnchorPoint(const Vec2 &pt)
{
    Widget::setAnchorPoint(pt);
    _elementRenderersContainer->setAnchorPoint(pt);
}

Size RichText::getVirtualRendererSize() const
{
    return _elementRenderersContainer->getContentSize();
}

void RichText::ignoreContentAdaptWithSize(bool ignore)
{
    if (_ignoreSize != ignore)
    {
        _formatTextDirty = true;
        Widget::ignoreContentAdaptWithSize(ignore);
    }
}

std::string RichText::getDescription() const
{
    return "RichText";
}

}

NS_CC_END

3,getSubStringOfUTF8String这个截取字符串的接口要修改,它的返回值不对。

std::string Helper::getSubStringOfUTF8String(const std::string& str, std::string::size_type start, std::string::size_type length)
{
    if (length==0)
    {
        return "";
    }
    std::string::size_type c, i, ix, q, min=std::string::npos, max=std::string::npos;
    for (q=0, i=0, ix=str.length(); i < ix; i++, q++)
    {
        if (q==start)
        {
            min = i;
        }
        if (q <= start+length || length==std::string::npos)   //结束是以start位置开始,所以截取是min->max-min
        {
            max = i;
        }

        c = (unsigned char) str[i];

        if      (c<=127) i+=0;
        else if ((c & 0xE0) == 0xC0) i+=1;
        else if ((c & 0xF0) == 0xE0) i+=2;
        else if ((c & 0xF8) == 0xF0) i+=3;
        else return "";//invalid utf8
    }
    if (q <= start+length || length == std::string::npos)
    {
        max = i;
    }
    if (min==std::string::npos || max==std::string::npos)
    {
        return "";
    }
    return str.substr(min,max-min);  //@cxx  原来是:  return str.substr(min,max);
}

4,在CCDevice.h中新增计算字体大小的接口,具体实现和平台相关,这里我只实现的ios平台。

static bool CalculateTextSize(const char * text, const char * fontName, float size, float &width, float &height ) ; //@cxx

5,ios平台CalculateTextSize的实现

//@cxx begin
static CGSize _my_calculateStringSize(NSString *str, id font, CGSize *constrainSize)
{
    CGSize textRect = CGSizeZero;
    textRect.width = constrainSize->width > 0 ? constrainSize->width
    : 0x7fffffff;
    textRect.height = constrainSize->height > 0 ? constrainSize->height
    : 0x7fffffff;


    CGSize dim;
    if(s_isIOS7OrHigher){
        NSDictionary *attibutes = @{NSFontAttributeName:font};
        dim = [str boundingRectWithSize:textRect options:(NSStringDrawingOptions)(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) attributes:attibutes context:nil].size;
    }
    else {
        dim = [str sizeWithFont:font constrainedToSize:textRect];
    }

    dim.width = (dim.width);
    dim.height = (dim.height);

    return dim;
}

//  计算字体大小
bool Device::CalculateTextSize(const char * text, const char * fontName, float size,  float &width, float &height )
{
    //float constrainWidth, float constrainHeight ,
    bool ret = false ;
    CGSize dim , constrainSize ;
    dim.width = 0.0f ;
    dim.height = 0.0f;
    constrainSize.width = 0.0f ; //constrainWidth ;
    constrainSize.height = 0.0f ;// constrainHeight ;
    do
    {
        CC_BREAK_IF(! text );

        NSString * str          = [NSString stringWithUTF8String:text];
        NSString * fntName      = [NSString stringWithUTF8String:fontName];

        fntName = [[fntName lastPathComponent] stringByDeletingPathExtension];

        // create the font
        id font = [UIFont fontWithName:fntName size:size];

        if (font)
        {
            dim = _my_calculateStringSize(str, font, &constrainSize);
        }
        else
        {
            if (!font)
            {
                font = [UIFont systemFontOfSize:size];
            }

            if (font)
            {
                dim = _my_calculateStringSize(str, font, &constrainSize);
            }
        }

        if (font)
        {
            ret = true ;
        }
    }while(false);

    width = dim.width ;
    height = dim.height ;

    return ret;
}
//@cxx  end

测试示例

auto _richText = RichText::create();
_richText->ignoreContentAdaptWithSize(false);
_richText->setContentSize(Size(100, 100));

auto str1 = "是减肥了快iii速的减肥了快SD卡路附近ffm国恢复共和国fkdsjfkldsj假了jjiij经济ii的快速减肥了mshfjksdhKSDFHJKDSJFKLlfj。、里的时刻福建路口的.sdfdsjflkjlksdjfl JlkdsjflkdsfjkldsjflkdsjfkljLjkd是福建代理商福建路口的";

RichElementText* re1 = RichElementText::create(1, Color3B::WHITE, 255, str1, "Marker Felt", 20);

_richText->pushBackElement(re1);
_richText->setPosition(Vec2(visibleSize.width / 2, visibleSize.height / 2 + 100));
this->addChild(_richText);

系统默认的对齐效果图:
这里写图片描述

修改后的对齐效果图:
这里写图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Cocos2dx-- 聊天系统之富文本(RichText)与字体对齐 的相关文章

  • Android studio的cMake编译生成.so库并调用

    第一步 添加工具 在SDK Tools中勾选安装CMake LLDB NDK 其中的LLDB是调试本地代码的工具 可以调试C 代码 第二步 创建一个最简单的官方demo File gt New gt NewProject 选中最下方的Inc
  • cocos2d中的anchorPoint

    cocos2d中的anchorPoint 将该图片放置到屏幕左下方 CCSprite sprite CCSprite sprite Default png addChild sprite 生成的精灵放置在 0 0 也就是屏幕左下角 但是精灵
  • Cocos2d-android游戏引擎

    什么是游戏引擎 游戏引擎是指一些已编写好的可编辑游戏系统或者一些交互式实时图像应用程序的核心组件 这些系统为游戏设计者提供各种编写游戏所需的各种工具 其目的在于让游戏设计者能容易和快速地做出游戏程式而不用由零开始 Cocos2d家族 coc
  • 关于visual studio中的$(ConfigurationName)疑问

    关于visual studio中的 ConfigurationName 疑问 2012 12 02 16 09 15 转载 标签 it 分类 程序员之路 关于vs中的各种路径的值de查看方法 来源 http social msdn micr
  • cocos2dx:瓦片地图加载失败及黑线问题

    问题 1 瓦片地图加载失败 运行时 获取瓦片地图的层失败 调试发现 获取的层是一个 NULL 遇到这个问题 我第一反应是图片路径有问题 但经过检查发现 路径没有问题 然我就怀疑 是我的代码有问题 然而并没有 调试无果 我就把目光转向瓦片地图
  • Cocos2d-x 3.9教程:10.使用CocosStudio的UI编辑器从UI文件中加载布局和控件

    Cocos2d x 3 9教程 10 使用CocosStudio的UI编辑器从UI文件中加载布局和控件 1 1 使用CocosStudio的UI编辑器 1 1 1 安装和启动 从官网上下载2015年11月18日版本 Cocos studio
  • 浅解cocos2d-x中的CCSprite绘制原理

    cocos2d x版本为2 0 4 此画图调用的是opengl es 2 0版本 支持三角形画图 故必须有一个顶点数组 此定义定义在CCSprite h中 ccV3F C4B T2F Quad m sQuad 而这个顶点数组的定义为 4 c
  • Cocos2d-x android无法解析cocos2dx库

    我从 macOS xcode 4 5 开始 我尝试过教程 使用cocos2dx完成macOSX的构建 问题发生在android源中 没有描述cocos2dxActivity的内容 所以 org cocos2dx lib不是其他文件 安卓没有
  • Android.mk - 构建目录中的所有源文件

    我正在使用 Android NDK 构建我的 cocos2dx 项目 在 Android mk 中 有一个 LOCAL SRC FILES 的定义 其中列出了每个 cpp 文件 每当我添加新的源文件时 我也需要将它添加到那里 它看起来像这样
  • 如何向 Outlook 发送富文本格式的电子邮件?

    通过分配 text html 内容类型字符串以 HTML 格式发送电子邮件 到 Outlook 非常有效 如下所示 using MailMessage message new MailMessage message From new Mai
  • 如何创建android cocos2dx启动画面?

    这是我的代码 我不知道如何创建启动屏幕以及它将如何直接显示在我的菜单屏幕中 所有 h必须连接到BaseScreen 并且BaseScreen将是cocos2d层中连接的那个 请帮助我的代码 唯一出现在我的模拟器中的是我在 HelloWorl
  • 将富文本粘贴到 Flash 中?

    粘贴到 Flash 时是否可以捕获富文本 使用 Flex TextEditArea 我可以在 Flash 本身中粘贴格式丰富的文本 但如果我尝试从外部源 例如网页 Microsoft Word 等 粘贴 它会以纯文本形式出现 反之亦然 如果
  • 在 Cocos2d-x 中创建 InAppPurchase [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我是 Cocos2d x 的新手 我需要为 Cocos2d x iOS 游戏 CPP 创建 InAppPurchase 任何人都可以帮助我
  • Cocos 2d-x 中带有贝塞尔曲线的圆角矩形

    是否可以使用 DrawNode 对象绘制一个圆角矩形 我认为使用贝塞尔曲线是可能的 但我做了一些尝试 但我认为我无法处理它 查看 API 我只发现这两个函数 绘制四边形贝塞尔曲线 const Vec2 origin const Vec2 c
  • 如何制作双向平台box2d主体?

    我使用 box2d 创建了平台 我想要 box2d 身体检测而不是动态检测 Box2d 形状将执行以下操作 在某些条件下检测碰撞 在某些情况下不检测碰撞 两种条件都适用于同一 box2d 对象中的不同条件 任何想法都会有很大帮助 提前致谢
  • Cocos2d-x - 如何将CCLayer的一部分设置为透明?

    我是新手cocos2d x我需要你的帮助 我需要使图层的触摸部分透明 如何使图层的一部分透明 我曾想过使用 ClippingNode 但我找不到示例或文档 我使用C 谢谢 在所有cocos2d x版本中添加的TestCpp项目中 您可以找到
  • TRichEdit 支持 Unicode 吗?

    我正在尝试编写一个包装类TRichEdit可以将 RTF 编码和解码为明文 这是我到目前为止所写的 type TRTF class private FRichEdit TRichEdit procedure SetText const AT
  • 是否可以从 Visual Studio 复制代码并将格式化代码粘贴到 OneNote 中?

    有没有办法从 Visual Studio C 复制代码并将其粘贴到 OneNote 中 而不会丢失格式 我能够做到这一点 但前提是我从 VS 复制 粘贴到 Word 从 Word 复制 然后粘贴到 OneNote 这是一个默认情况下似乎被禁
  • 将我现有的富文本 UI 与 CKEditor API 结合使用

    我有一个现有的富文本 UI 我想将其与 CKEditor 一起使用 基本上 我希望 CKEditor 能够处理应用样式 格式 过滤和规范化插入内容的复杂部分 我现有的 UI 需要驱动交互并根据选择显示状态 即 选择粗体文本应反映在 UI 中
  • 如何使用 Cygwin 打开 RTTI?

    当我的Android NDK C 本机代码编译时 出现以下错误 错误 fno rtti 不允许使用 dynamic cast 有人告诉我打开RTTI 但我不知道该怎么做 我需要修改吗Application mk或者是什么 my Applic

随机推荐