创建方法
1.Sprite* Sprite::createWithTexture(Texture2D *texture)
2.Sprite* Sprite::createWithTexture(Texture2D *texture, const Rect& rect, bool rotated)
3.Sprite* Sprite::create(const std::string& filename)
4.Sprite* Sprite::create(const std::string& filename, const Rect& rect)
5.Sprite* Sprite::createWithSpriteFrame(SpriteFrame *spriteFrame)
6.Sprite* Sprite::createWithSpriteFrameName(const std::string& spriteFrameName)
实例
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 //load bg.plist 2 SpriteFrameCache::getInstance() ->addSpriteFramesWithFile("bg/bg.plist"); 3 SpriteFrameCache::getInstance() ->addSpriteFramesWithFile("game/shoot.plist"); 4 5 // creat bg 6 Sprite *bgsprite = Sprite::createWithSpriteFrameName("background.png"); 7 bgsprite->setAnchorPoint(Vec2::ZERO); 8 this->addChild(bgsprite); 9 10 //creat player 11 _playersprite = Sprite::createWithSpriteFrameName("hero1.png"); 12 _playersprite->setPosition(Size(visibleSize.width/2,visibleSize.height/2)); 13 this->addChild(_playersprite);
方法void Sprite::updateTransform(void CCASSERT(_batchNode, "updateTransform is only valid when Sprite is being rendered using an SpriteBatchNode");
// recalculate matrix only if it is dirty if( isDirty() ) { // If it is not visible, or one of its ancestors is not visible, then do nothing: if( !_visible || ( _parent && _parent != _batchNode && static_cast<Sprite*>(_parent)->_shouldBeHidden) ) { _quad.br.vertices = _quad.tl.vertices = _quad.tr.vertices = _quad.bl.vertices = Vec3(0,0,0); _shouldBeHidden = true; } else { _shouldBeHidden = false; if( ! _parent || _parent == _batchNode ) { _transformToBatch = getNodeToParentTransform(); } else { CCASSERT( dynamic_cast<Sprite*>(_parent), "Logic error in Sprite. Parent must be a Sprite"); Mat4 nodeToParent = getNodeToParentTransform(); Mat4 parentTransform = static_cast<Sprite*>(_parent)->_transformToBatch; _transformToBatch = parentTransform * nodeToParent; } // // calculate the Quad based on the Affine Matrix // Size size = _rect.size; float x1 = _offsetPosition.x; float y1 = _offsetPosition.y; float x2 = x1 + size.width; float y2 = y1 + size.height; float x = _transformToBatch.m[12]; float y = _transformToBatch.m[13]; float cr = _transformToBatch.m[0]; float sr = _transformToBatch.m[1]; float cr2 = _transformToBatch.m[5]; float sr2 = -_transformToBatch.m[4]; float ax = x1 * cr - y1 * sr2 + x; float ay = x1 * sr + y1 * cr2 + y; float bx = x2 * cr - y1 * sr2 + x; float by = x2 * sr + y1 * cr2 + y; float cx = x2 * cr - y2 * sr2 + x; float cy = x2 * sr + y2 * cr2 + y; float dx = x1 * cr - y2 * sr2 + x; float dy = x1 * sr + y2 * cr2 + y; _quad.bl.vertices = Vec3( RENDER_IN_SUBPIXEL(ax), RENDER_IN_SUBPIXEL(ay), _positionZ ); _quad.br.vertices = Vec3( RENDER_IN_SUBPIXEL(bx), RENDER_IN_SUBPIXEL(by), _positionZ ); _quad.tl.vertices = Vec3( RENDER_IN_SUBPIXEL(dx), RENDER_IN_SUBPIXEL(dy), _positionZ ); _quad.tr.vertices = Vec3( RENDER_IN_SUBPIXEL(cx), RENDER_IN_SUBPIXEL(cy), _positionZ ); } // MARMALADE CHANGE: ADDED CHECK FOR nullptr, TO PERMIT SPRITES WITH NO BATCH NODE / TEXTURE ATLAS if (_textureAtlas) { _textureAtlas->updateQuad(&_quad, _atlasIndex); } _recursiveDirty = false; setDirty(false); } // MARMALADE CHANGED // recursively iterate over children /* if( _hasChildren ) { // MARMALADE: CHANGED TO USE Node* // NOTE THAT WE HAVE ALSO DEFINED virtual Node::updateTransform() arrayMakeObjectsPerformSelector(_children, updateTransform, Sprite*); }*/ Node::updateTransform(); } // draw void Sprite::draw(Renderer *renderer, const Mat4 &transform, bool transformUpdated) { // Don't do calculate the culling if the transform was not updated _insideBounds = transformUpdated ? renderer->checkVisibility(transform, _contentSize) : _insideBounds; if(_insideBounds) { _quadCommand.init(_globalZOrder, _texture->getName(), getGLProgramState(), _blendFunc, &_quad, 1, transform); renderer->addCommand(&_quadCommand); #if CC_SPRITE_DEBUG_DRAW _customDebugDrawCommand.init(_globalZOrder); _customDebugDrawCommand.func = CC_CALLBACK_0(Sprite::drawDebugData, this); renderer->addCommand(&_customDebugDrawCommand); #endif //CC_SPRITE_DEBUG_DRAW } } #if CC_SPRITE_DEBUG_DRAW void Sprite::drawDebugData() { Director* director = Director::getInstance(); CCASSERT(nullptr != director, "Director is null when seting matrix stack"); Mat4 oldModelView; oldModelView = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform); // draw bounding box Vec2 vertices[4] = { Vec2( _quad.bl.vertices.x, _quad.bl.vertices.y ), Vec2( _quad.br.vertices.x, _quad.br.vertices.y ), Vec2( _quad.tr.vertices.x, _quad.tr.vertices.y ), Vec2( _quad.tl.vertices.x, _quad.tl.vertices.y ), }; DrawPrimitives::drawPoly(vertices, 4, true); director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, oldModelView); } #endif //CC_SPRITE_DEBUG_DRAW // Node overrides void Sprite::addChild(Node *child, int zOrder, int tag) { CCASSERT(child != nullptr, "Argument must be non-nullptr"); if (_batchNode) { Sprite* childSprite = dynamic_cast<Sprite*>(child); CCASSERT( childSprite, "CCSprite only supports Sprites as children when using SpriteBatchNode"); CCASSERT(childSprite->getTexture()->getName() == _textureAtlas->getTexture()->getName(), ""); //put it in descendants array of batch node _batchNode->appendChild(childSprite); if (!_reorderChildDirty) { setReorderChildDirtyRecursively(); } } //CCNode already sets isReorderChildDirty_ so this needs to be after batchNode check Node::addChild(child, zOrder, tag); } void Sprite::reorderChild(Node *child, int zOrder) { CCASSERT(child != nullptr, "child must be non null"); CCASSERT(_children.contains(child), "child does not belong to this"); if( _batchNode && ! _reorderChildDirty) { setReorderChildDirtyRecursively(); _batchNode->reorderBatch(true); } Node::reorderChild(child, zOrder); } void Sprite::removeChild(Node *child, bool cleanup) { if (_batchNode) { _batchNode->removeSpriteFromAtlas((Sprite*)(child)); } Node::removeChild(child, cleanup); } void Sprite::removeAllChildrenWithCleanup(bool cleanup) { if (_batchNode) { for(const auto &child : _children) { Sprite* sprite = dynamic_cast<Sprite*>(child); if (sprite) { _batchNode->removeSpriteFromAtlas(sprite); } } } Node::removeAllChildrenWithCleanup(cleanup); } void Sprite::sortAllChildren() { if (_reorderChildDirty) { std::sort(std::begin(_children), std::end(_children), nodeComparisonLess); if ( _batchNode) { for(const auto &child : _children) child->sortAllChildren(); } _reorderChildDirty = false; } } // // Node property overloads // used only when parent is SpriteBatchNode // void Sprite::setReorderChildDirtyRecursively(void) { //only set parents flag the first time if ( ! _reorderChildDirty ) { _reorderChildDirty = true; Node* node = static_cast<Node*>(_parent); while (node && node != _batchNode) { static_cast<Sprite*>(node)->setReorderChildDirtyRecursively(); node=node->getParent(); } } } void Sprite::setDirtyRecursively(bool bValue) { _recursiveDirty = bValue; setDirty(bValue); for(const auto &child: _children) { Sprite* sp = dynamic_cast<Sprite*>(child); if (sp) { sp->setDirtyRecursively(true); } } } // XXX HACK: optimization #define SET_DIRTY_RECURSIVELY() { \ if (! _recursiveDirty) { \ _recursiveDirty = true; \ setDirty(true); \ if (!_children.empty()) \ setDirtyRecursively(true); \ } \ } void Sprite::setPosition(const Vec2& pos) { Node::setPosition(pos); SET_DIRTY_RECURSIVELY(); } void Sprite::setPosition(float x, floatvoid Sprite::setRotation(float rotation) void Sprite::setRotationSkewX(float fRotationX) void Sprite::setRotationSkewY(float fRotationY)
//倾斜
void Sprite::setSkewX(float sx) void Sprite::setSkewY(floatvoid Sprite::setScaleX(float scaleX) void Sprite::setScaleY(float scaleY) void Sprite::setScale(float fScale) void Sprite::setScale(float scaleX, float scaleY) void Sprite::setPositionZ(float fVertexZ) { Node::setPositionZ(fVertexZ); SET_DIRTY_RECURSIVELY(); } void Sprite::setAnchorPoint(const Vec2& anchor) { Node::setAnchorPoint(anchor); SET_DIRTY_RECURSIVELY(); } void Sprite::ignoreAnchorPointForPosition(bool value) { CCASSERT(! _batchNode, "ignoreAnchorPointForPosition is invalid in Sprite"); Node::ignoreAnchorPointForPosition(value); } void Sprite::setVisible(bool bVisible) { Node::setVisible(bVisible); SET_DIRTY_RECURSIVELY(); } void Sprite::setFlippedX(bool flippedX) { if (_flippedX != flippedX) { _flippedX = flippedX; setTextureRect(_rect, _rectRotated, _contentSize); } } bool Sprite::isFlippedX(void) const { return _flippedX; } void Sprite::setFlippedY(bool flippedY) { if (_flippedY != flippedY) { _flippedY = flippedY; setTextureRect(_rect, _rectRotated, _contentSize); } } bool Sprite::isFlippedY(void) const { return _flippedY; } // // RGBA protocol // void Sprite::updateColor(void) { Color4B color4( _displayedColor.r, _displayedColor.g, _displayedColor.b, _displayedOpacity ); // special opacity for premultiplied textures if (_opacityModifyRGB) { color4.r *= _displayedOpacity/255.0f; color4.g *= _displayedOpacity/255.0f; color4.b *= _displayedOpacity/255.0f; } _quad.bl.colors = color4; _quad.br.colors = color4; _quad.tl.colors = color4; _quad.tr.colors = color4; // renders using batch node if (_batchNode) { if (_atlasIndex != INDEX_NOT_INITIALIZED) { _textureAtlas->updateQuad(&_quad, _atlasIndex); } else { // no need to set it recursively // update dirty_, don't update recursiveDirty_ setDirty(true); } } // self render // do nothing } void Sprite::setOpacityModifyRGB(bool modify) { if (_opacityModifyRGB != modify) { _opacityModifyRGB = modify; updateColor(); } } bool Sprite::isOpacityModifyRGB(void) const { return _opacityModifyRGB; } // Frames void Sprite::setSpriteFrame(const std::string &spriteFrameName) { SpriteFrameCache *cache = SpriteFrameCache::getInstance(); SpriteFrame *spriteFrame = cache->getSpriteFrameByName(spriteFrameName); CCASSERT(spriteFrame, "Invalid spriteFrameName"); setSpriteFrame(spriteFrame); } void Sprite::setSpriteFrame(SpriteFrame *spriteFrame) { _unflippedOffsetPositionFromCenter = spriteFrame->getOffset(); Texture2D *texture = spriteFrame->getTexture(); // update texture before updating texture rect if (texture != _texture) { setTexture(texture); } // update rect _rectRotated = spriteFrame->isRotated(); setTextureRect(spriteFrame->getRect(), _rectRotated, spriteFrame->getOriginalSize()); } void Sprite::setDisplayFrameWithAnimationName(const std::string& animationName, ssize_t frameIndex) { CCASSERT(animationName.size()>0, "CCSprite#setDisplayFrameWithAnimationName. animationName must not be nullptr"); Animation *a = AnimationCache::getInstance()->getAnimation(animationName); CCASSERT(a, "CCSprite#setDisplayFrameWithAnimationName: Frame not found"); AnimationFrame* frame = a->getFrames().at(frameIndex); CCASSERT(frame, "CCSprite#setDisplayFrame. Invalid frame"); setSpriteFrame(frame->getSpriteFrame()); } bool Sprite::isFrameDisplayed(SpriteFrame *frame) const { Rect r = frame->getRect(); return (r.equals(_rect) && frame->getTexture()->getName() == _texture->getName() && frame->getOffset().equals(_unflippedOffsetPositionFromCenter)); } SpriteFrame* Sprite::getSpriteFrame() const { return SpriteFrame::createWithTexture(_texture, CC_RECT_POINTS_TO_PIXELS(_rect), _rectRotated, CC_POINT_POINTS_TO_PIXELS(_unflippedOffsetPositionFromCenter), CC_SIZE_POINTS_TO_PIXELS(_contentSize)); } SpriteBatchNode* Sprite::getBatchNode() { return _batchNode; } void Sprite::setBatchNode(SpriteBatchNode *spriteBatchNode) { _batchNode = spriteBatchNode; // weak reference // self render if( ! _batchNode ) { _atlasIndex = INDEX_NOT_INITIALIZED; setTextureAtlas(nullptr); _recursiveDirty = false; setDirty(false); float x1 = _offsetPosition.x; float y1 = _offsetPosition.y; float x2 = x1 + _rect.size.width; float y2 = y1 + _rect.size.height; _quad.bl.vertices = Vec3( x1, y1, 0 ); _quad.br.vertices = Vec3( x2, y1, 0 ); _quad.tl.vertices = Vec3( x1, y2, 0 ); _quad.tr.vertices = Vec3( x2, y2, 0 ); } else { // using batch _transformToBatch = Mat4::IDENTITY; setTextureAtlas(_batchNode->getTextureAtlas()); // weak ref } } // Texture protocol void Sprite::updateBlendFunc(void) { CCASSERT(! _batchNode, "CCSprite: updateBlendFunc doesn't work when the sprite is rendered using a SpriteBatchNode"); // it is possible to have an untextured sprite if (! _texture || ! _texture->hasPremultipliedAlpha()) { _blendFunc = BlendFunc::ALPHA_NON_PREMULTIPLIED; setOpacityModifyRGB(false); } else { _blendFunc = BlendFunc::ALPHA_PREMULTIPLIED; setOpacityModifyRGB(true); } } std::string Sprite::getDescription() const { int texture_id = -1; if( _batchNode ) texture_id = _batchNode->getTextureAtlas()->getTexture()->getName(); else texture_id = _texture->getName(); return StringUtils::format("<Sprite | Tag = %d, TextureID = %d>", _tag, texture_id ); }