Cocos2d-x Sprite笔记

本文详细介绍了Cocos2d-x中Sprite的创建过程,包括`create`、`init`、`setPosition`等方法的使用。讲解了如何加载纹理、设置锚点、更新顶点坐标以及在场景中的位置变换。特别指出,`init`后,Sprite的纹理坐标、索引和位置都已确定。`visit`方法用于传递和应用变换矩阵,并调用子节点的`draw`方法。然而,当前实现存在每次render时更新顶点数据的效率问题。
摘要由CSDN通过智能技术生成

1.create

auto sprite = Sprite::create("HelloWorld.png");
Sprite* Sprite::create(const std::string& filename)
{
    Sprite *sprite = new (std::nothrow) Sprite();
    if (sprite && sprite->initWithFile(filename))
    {
        sprite->autorelease();
        return sprite;
    }
    CC_SAFE_DELETE(sprite);
    return nullptr;
}
Sprite::Sprite(void)
: _batchNode(nullptr)
, _textureAtlas(nullptr)
, _shouldBeHidden(false)
, _texture(nullptr)
, _spriteFrame(nullptr)
, _insideBounds(true)
{
}

2.init

bool Sprite::initWithFile(const std::string& filename)
{
    if (filename.empty())
    {
        CCLOG("Call Sprite::initWithFile with blank resource filename.");
        return false;
    }

    _fileName = filename;
    _fileType = 0;

    Texture2D *texture = _director->getTextureCache()->addImage(filename);
    if (texture)
    {
        Rect rect = Rect::ZERO;
        rect.size = texture->getContentSize();
        return initWithTexture(texture, rect);
    }

    // don't release here.
    // when load texture failed, it's better to get a "transparent" sprite then a crashed program
    // this->release();
    return false;
}

1)_director->getTextureCache()->addImage(filename):TextureCache用于管理texture的加载(另开一个线程)
2)rect.size = texture->getContentSize():用texture content size(像素为单位,window.size也是以像素为单位)作为Sprite的size,如果是一张1024X768的图片,则rect = (0,0,1024,768),这个rect会用来生成Sprite的顶点坐标,比如这个Rect的右上角对应的顶点坐标是(1024 / window.size.w, 768 / window.size.h)

bool Node::init()
{
    return true;
}
bool Sprite::initWithTexture(Texture2D *texture, const Rect& rect, bool rotated)
{
    bool result = false;
    if (Node::init())
    {
        _batchNode = nullptr;

        _recursiveDirty = false;
        setDirty(false);

        _opacityModifyRGB = true;

        _blendFunc = BlendFunc::ALPHA_PREMULTIPLIED;

        _flippedX = _flippedY = false;

        // default transform anchor: center
        setAnchorPoint(Vec2(0.5f, 0.5f));

        // zwoptex default values
        _offsetPosition.setZero();

        // clean the Quad
        memset(&_quad, 0, sizeof(_quad));

        // Atlas: Color
        _quad.bl.colors = Color4B::WHITE;
        _quad.br.colors = Color4B::WHITE;
        _quad.tl.colors = Color4B::WHITE;
        _quad.tr.colors = Color4B::WHITE;

        // update texture (calls updateBlendFunc), set program but not set vertex attrib and uniform
        setTexture(texture);
        // set _quad, _texcoord
        setTextureRect(rect, rotated, rect.size);

        // by default use "Self Render".
        // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render"
        setBatchNode(nullptr);
        result = true;
    }

    _recursiveDirty = true;
    setDirty(true);

    return result;
}

0)_quad.bl.colors = Color4B::WHITE:默认4个角的颜色为白色
1)_flippedX = _flippedY = false:不需要flip,因为TexCoords按照未flip生成的(y轴向下,OpenGL坐标系y轴向上)
2)setAnchorPoint(Vec2(0.5f, 0.5f)):除了layer类,其他Node类锚点默认在正中间
3)_offsetPosition.setZero():Node的content size可能和texture size不一样,这样就会产生offset,一般offset都是0。因为使用texture的content size来设置Node的content size的,两者相等,所以没有offset。
4)setTexture(texture):设置texture,获取GLProgramState,加载编译所有的program,如果texture为nullptr,用一张白色的图片作为texture

void Sprite::setTexture(Texture2D *texture)
{
    setGLProgramState(GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP, texture));

    // If batchnode, then texture id should be the same
    CCASSERT(! _batchNode || (texture &&  texture->getName() == _batchNode->getTexture()->getName()), "CCSprite: Batched sprites should use the same texture as the batchnode");
    // accept texture==nil as argument
    CCASSERT( !texture || dynamic_cast<Texture2D*>(texture), "setTexture expects a Texture2D. Invalid argument");

    if (texture == nullptr)
    {
        // Gets the texture by key firstly.
        texture = _director->getTextureCache()->getTextureForKey(CC_2x2_WHITE_IMAGE_KEY);

        // If texture wasn't in cache, create it from RAW data.
        if (texture == nullptr)
        {
            Image* image = new (std::nothrow) Image();
            bool isOK = image->initWithRawData(cc_2x2_white_image, sizeof(cc_2x2_white_image), 2, 2, 8);
            CC_UNUSED_PARAM(isOK);
            CCASSERT(isOK, "The 2x2 empty texture was created unsuccessfully.");

            texture = _director->getTextureCache()->addImage(image, CC_2x2_WHITE_IMAGE_KEY);
            CC_SAFE_RELEASE(image);
        }
    }

    if (!_batchNode && _texture != texture)
    {
        CC_SAFE_RETAIN(texture);
        CC_SAFE_RELEASE(_texture);
        _texture = texture;
        updateBlendFunc();
    }
}

5)setTextureRect(rect, rotated, rect.size):setTexCoords(左上为(0,0), 左下为(0.1),load image不flip,TexCoords实现flip)和setPosition(position没有变,左下为(0,0))

void Sprite::setTextureRect(const Rect& rect, bool rotated, const Size& untrimmedSize)
{
    _rectRotated = rotated;

    setContentSize(untrimmedSize);
    setVertexRect(rect);
    setTextureCoords(rect);

    float relativeOffsetX = _unflippedOffsetPositionFromCenter.x;
    float relativeOffsetY = _unflippedOffsetPositionFromCenter.y;

    // issue #732
    if (_flippedX)
    {
        relativeOffsetX = -relativeOffsetX;
    }
    if (_flippedY)
    {
        relativeOffsetY = -relativeOffsetY;
    }

    _offsetPosition.x = relativeOffsetX + (_contentSize.width - _rect.size.width) / 2;
    _offsetPosition.y = relativeOffsetY + (_contentSize.height - _rect.size.height) / 2;

    // rendering using batch node
    if (_batchNode)
    {
        // update dirty_, don't update recursiveDirty_
        setDirty(true);
    }
    else
    {
        // self rendering

        // Atlas: Vertex
        float x1 = 0.0f + _offsetPosition.x;
        float y1 = 0.0f + _offsetPosition.y;
        float x2 = x1 + _rect.size.width;
        float y2 = y1 + _rect.size.height;

        // Don't update Z.
        _quad.bl.vertices.set(x1, y1, 0.0f);
        _quad.br.vertices.set(x2, y1, 0.0f);
        _quad.tl.vertices.set(x1, y2, 0.0f);
        _quad.tr.vertices.set(x2, y2, 0.0f);
    }

    _polyInfo.setQuad(&_quad);
}
void Node::setContentSize(const Size & size)
{
    if (! size.equals(_contentSize))
    {
        _contentSize = size;

        _anchorPointInPoints.set(_contentSize.width * _anchorPoint.x, _contentSize.height * _anchorPoint.y);
        _transformUpdated = _transformDirty = _inverseDirty = _contentSizeDirty = true;
    }
}
void Sprite::setVertexRect(const Rect& rect)
{
    _rect = rect;
}
void Sprite::setTextureCoords(const Rect& rectInPoint)
{
    Texture2D *tex = _batchNode ? _textureAtlas->getTexture() : _texture;
    if (tex == nullptr)
    {
        return;
    }

    auto rectInPixels = CC_RECT_POINTS_TO_PIXELS(rectInPoint);

    float atlasWidth = (float)tex->getPixelsWide();
    float atlasHeight = (float)tex->getPixelsHigh();

    float left, right, top, bottom;

    if (_rectRotated)
    {
#if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
        left    = (2*rectInPixels.origin.x+1)/(2*atlasWidth);
        right   = left+(rectInPixels.size.height*2-2)/(2*atlasWidth);
        top     = (2*rectInPixels.origin.y+
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值