| 版权声明:本文为博主原创文章,未经博主允许不得转载。
Sprite是Cocos2d-x游戏开发者最常用的类,用图片把精灵(Sprite)显示在屏幕上。
在游戏开发中,经常会遇到精灵(Sprite)这个术语。精灵是一个图像,可以在屏幕上独立的移动,一个精灵可能是玩家角色,子弹,敌人或者是大的背景图片。一般情况下,精灵来自开发者所准备的PNG或PVRTC或JPG图像。一旦图像载入内存,就会将精灵转换成纹理图CCTexture,从而被CPU用于在屏幕上渲染;Cocos2d中的精灵和其他游戏引擎中的精灵相似,它可以移动,旋转,缩放,执行动画,并接受其他转换Cocos2dx的Sprite由Texure,frame和animation组成,由openes负责渲染。
主要的类关系如下: 简单过程可描述为:用Texture2D加载图片,可以用Texture2D生成对应的SpriteFrame(精灵帧),将SpriteFrame添加到Animation生成动画数据,用Animation生成Animate(就是最终的动画动作),最后用Sprite执行这个动作。创建精灵的几种方式:直接创建,纹理来创建精灵,精灵帧来创建精灵;
精灵类的主要公共函数:
精灵类的六种创建方法:
static Sprite* create(const char *pszFileName); 使用一个图片名称创建一个精灵,这种适用于静态的精灵创建,如添加背景 static Sprite* create(const char *pszFileName, const Rect& rect); 使用一个文件名称和一个矩形框创建一个精灵 static Sprite* createWithTexture(Texture2D *pTexture); 使用texture创建一个sprite,纹理创建 static Sprite* createWithTexture(Texture2D *pTexture, const Rect&& rect); 使用texture和一个矩形框来创建一个sprite static Sprite* createWithSpriteFrame(SpriteFrame *pSpriteFrame); 使用一个精灵帧来创建一个精灵 static Sprite* createWithSpriteFrameName(const char *pszSpriteFrameName); 使用精灵帧名称来创建一个精灵
实例:
第一种创建:图片名称创建
void SpriteTest::Test1() { Sprite* sprite = Sprite::create("GameMainMenu.png"); sprite->setPosition(Vec2(origin.x + visible.width / 2, origin.y + visible.height / 2)); float xs = visible.width / sprite->getContentSize().width; float ys = visible.height / sprite->getContentSize().height; sprite->setScale(xs, ys); this->addChild(sprite); }
第二种创建:文件名称和一个矩形框创建
void SpriteTest::Test2() { Rect r = Rect(1, 91, 110, 83); //矩形框的位置坐标 sprite = Sprite::create("Mouse_1.png", r); sprite->setPosition(Vec2(origin.x + visible.width / 4, origin.y + visible.height / 4)); this->addChild(sprite); }
第三种创建:纹理创建
void SpriteTest::Test3() { //取得一个.png图片的纹理 texture = Director::getInstance()->getTextureCache()->addImage("ThorHammer.png"); sprite = Sprite::createWithTexture(texture); sprite->setPosition(Vec2(origin.x + visible.width / 4, origin.y + visible.height / 2.5)); this->addChild(sprite); }
第四种创建:texture和一个矩形框来创建
void SpriteTest::Test4() { //加载一张包含多张小图片的大图片 texture = Director::getInstance()->getTextureCache()->addImage("MainBottom.png"); //框出大图片中的一张小图片 Rect r = Rect(1, 305, 558, 150); sprite = Sprite::createWithTexture(texture); //设置位置 sprite->setPosition(Vec2(origin.x + visible.width / 2, origin.y + visible.height - 1.5*(visible.height / 3))); sprite->setScale(0.3, 0.3); this->addChild(sprite); }
第五种创建:一个精灵帧来创建
void SpriteTest::Test5() { SpriteFrameCache::getInstance()->addSpriteFramesWithFile("Hammer.plist"); SpriteFrame* frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("GoldenHammer.png"); sprite = Sprite::createWithSpriteFrame(frame); sprite->setPosition(Vec2(origin.x + visible.width / 2, origin.y + visible.height / 2)); this->addChild(sprite); }
第六种创建:精灵帧名称来创建
void SpriteTest::Test6() { SpriteFrameCache::getInstance()->addSpriteFramesWithFile("Hammer.plist"); sprite = Sprite::createWithSpriteFrameName("StarHammer .png"); sprite->setPosition(Vec2(origin.x + visible.width / 2, origin.y + visible.height / 3)); this->addChild(sprite); }
完整代码:
.h file #ifndef _SPRITETEST_SCENE_H_ #define _SPRITETEST_SCENE_H_ #include "cocos2d.h" class SpriteTest : public cocos2d::Layer { private: cocos2d::Size visible; cocos2d::Vec2 origin; cocos2d::Sprite* sprite; cocos2d::Texture2D* texture; public: static cocos2d::Scene* createScene(); virtual bool init(); void Test1(); void Test2(); void Test3(); void Test4(); void Test5(); void Test6(); CREATE_FUNC(SpriteTest); }; #endif // _SPRITETEST_SCENE_H_ .cpp file #include "SpriteTest.h" USING_NS_CC; Scene* SpriteTest::createScene() { auto scene = Scene::create(); auto layer = SpriteTest::create(); scene->addChild(layer); return scene; } bool SpriteTest::init() { if (!Layer::init()) { return false; } visible = Director::getInstance()->getVisibleSize(); origin = Director::getInstance()->getVisibleOrigin(); Test1(); this->Test2(); Test3(); this->Test4(); Test5(); Test6(); return true; } //第一种创建: 通过.png图片来创建精灵 void SpriteTest::Test1() { Sprite* sprite = Sprite::create("GameMainMenu.png"); sprite->setPosition(Vec2(origin.x + visible.width / 2, origin.y + visible.height / 2)); float xs = visible.width / sprite->getContentSize().width; float ys = visible.height / sprite->getContentSize().height; sprite->setScale(xs, ys); this->addChild(sprite); } //第二种创建: 通过在一张大图片中框出一个矩形图片来创建精灵 void SpriteTest::Test2() { Rect r = Rect(1, 91, 110, 83); //矩形框的位置坐标 sprite = Sprite::create("Mouse_1.png", r); sprite->setPosition(Vec2(origin.x + visible.width / 4, origin.y + visible.height / 4)); this->addChild(sprite); } //第三种创建: 通过纹理来创建精灵 void SpriteTest::Test3() { //取得一个.png图片的纹理 texture = Director::getInstance()->getTextureCache()->addImage("ThorHammer.png"); sprite = Sprite::createWithTexture(texture); sprite->setPosition(Vec2(origin.x + visible.width / 4, origin.y + visible.height / 2.5)); this->addChild(sprite); } //使用一个纹理和一个矩形框创建一个精灵 void SpriteTest::Test4() { //加载一张包含多张小图片的大图片 texture = Director::getInstance()->getTextureCache()->addImage("MainBottom.png"); //框出大图片中的一张小图片 Rect r = Rect(1, 305, 558, 150); sprite = Sprite::createWithTexture(texture); //设置位置 sprite->setPosition(Vec2(origin.x + visible.width / 2, origin.y + visible.height - 1.5*(visible.height / 3))); sprite->setScale(0.3, 0.3); this->addChild(sprite); } //使用一个精灵帧创建一个精灵 void SpriteTest::Test5() { SpriteFrameCache::getInstance()->addSpriteFramesWithFile("Hammer.plist"); SpriteFrame* frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("GoldenHammer.png"); sprite = Sprite::createWithSpriteFrame(frame); sprite->setPosition(Vec2(origin.x + visible.width / 2, origin.y + visible.height / 2)); this->addChild(sprite); } //使用精灵帧名称创建一个精灵 void SpriteTest::Test6() { SpriteFrameCache::getInstance()->addSpriteFramesWithFile("Hammer.plist"); sprite = Sprite::createWithSpriteFrameName("StarHammer .png"); sprite->setPosition(Vec2(origin.x + visible.width / 2, origin.y + visible.height / 3)); this->addChild(sprite); }
SpriteBatchNode简介:
在游戏开发中当屏幕上的精灵太多时,程序性能将急剧下降,这是因为每当添加一个精灵时,GPU都会重新渲染一次,这样性能很低.当有多个精灵出现时,例如:游戏中的子弹,可以使用SpriteBatchNode批量加载一次,从而提高了程序的性能。
通过源码分析,我们看到SpriteBatchNode还是通过TestureCache来加载图片的
bool SpriteBatchNode::initWithFile(const char*fileImage,
unsigned int capacity)
{
Texture2D* ptexture2d =
TextureCache::sharedTextureCache()->addImage(fileImage);
return initWithTexture(ptexture2d, capacity);
}
和SpriteFrameCache不同的是,SpriteFrameCache通常用来实现动画,但是在3.0的版本中不建议使用,只要sprite来自一张大图就行
实例源码:
.h files #ifndef _SPRITEBATCHNODETEST_SCENE_H_ #define _SPRITEBATCHNODETEST_SCENE_H_ #include "cocos2d.h" class SpriteBatch : public cocos2d::Layer { private: cocos2d::Size visible; cocos2d::Vec2 origin; cocos2d::SpriteBatchNode* batch; cocos2d::Sprite* mole; public: static cocos2d::Scene* createScene(); virtual bool init(); //初始化Batch,通过这个函数来添加多个地鼠 void initBatch(); //添加地鼠,从batch取得,然后在当前的这个点出添加一个地鼠(点事通过触屏事件得到) void addMole(cocos2d::Vec2 point); //添加一个触屏事件,当我们点击屏幕时,在我们点击的位置添加一个地鼠 virtual bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event); CREATE_FUNC(SpriteBatch); }; #endif // _SPRITEBATCHNODETEST_SCENE_H_ .cpp files #include "SpriteBatchNodeTest.h" USING_NS_CC; Scene* SpriteBatch::createScene() { auto scene = Scene::create(); auto layer = SpriteBatch::create(); scene->addChild(layer); return scene; } bool SpriteBatch::init() { if (!Layer::init()) { return false; } visible = Director::getInstance()->getVisibleSize(); origin = Director::getInstance()->getVisibleOrigin(); initBatch(); //注册监听器 auto l = EventListenerTouchOneByOne::create(); l->onTouchBegan = CC_CALLBACK_2(SpriteBatch::onTouchBegan, this); //注册事件 _eventDispatcher->addEventListenerWithSceneGraphPriority(l, this); return true; } void SpriteBatch::initBatch() { //首先初始化,创建地鼠对象,添加50个地鼠到layer中 batch = SpriteBatchNode::create("Rat4.png", 50); //将batch添加到当前的Layer中 this->addChild(batch); } void SpriteBatch::addMole(cocos2d::Vec2 point) { //创建一个地鼠的精灵,此精灵为纹理,且取自batch中的地鼠纹理 mole = Sprite::createWithTexture(batch->getTexture()); //将地鼠显示在单击屏幕的地方 mole->setPosition(point); //最后将此精灵添加到Layer中 this->addChild(mole); } bool SpriteBatch::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event) { //首先,取得鼠标点击屏幕的那个点 cocos2d::Vec2 point = touch->getLocationInView(); //将获取的point这个点,转换成坐标 point = Director::getInstance()->convertToGL(point); //每点击一次屏幕,就调用addMole()一次 addMole(point); return false; }
SpriteFrameCache
SpriteFrameCache是精灵帧的缓存类,提供了一些管理精灵帧Sprite的方法,SpriteFrameCache是单例类,实例化方法如下:
static SpriteFrameCache* getInstance(void);
其他重要的方法: static void purgeShareSpriteFrameCache(void); 清除缓存 void addSpriteFramesWithFile(const char* plist); 从plist配置文件中添加多个精灵帧SpriteFrame void addSpriteFramesWithFile(const char* plist, const char* fileName); 使用plist和纹理文件创建多个精灵帧(新增纹理时使用,该纹理和plist关联在一起) void addSpriteFramesWithFile(const char* pszPlist, cocos2d::Texture2D* texture); 使用plist和纹理文件创建多个精灵帧(新增纹理时使用,该纹理和plist关联在一起) void addSpriteFrame(cocos2d::SpriteFrame* frame,const char* frameName) 添加单帧精灵帧,并为精灵帧指定名称 void removeSpriteFrame(void); 删除精灵帧 void removeUnusedSpriteFrames(void) 删除未使用的精灵帧 void removeSpriteFramesFromFile(const char* plist); 根据plist删除精灵帧
SpriteFrame
在游戏的开发过程中,通常使用工具将多张图片放在同一张大的图片中来加载,这样可以提高性能,可以根据某个单个小图片放在大图片的矩形框中来显示这张小图片,精灵帧SpriteFrame就是用来封装这张小图片。
SpriteFrame的重要创建函数:
static SpriteFrame* create(const char* filename, const Rect& rect); 使用Texture(纹理)和矩形框创建精灵帧 static SpriteFrame* createWithTexture(Texture2D* pobTexture, const Rect& rect); 使用图片文件和矩形框来创建精灵帧
实例:
.h files #ifndef _SPRITEFRAMETEST_SCENE_H_ #define _SPRITEFRAMETEST_SCENE_H_ #include "cocos2d.h" class spriteFrame : public cocos2d::Layer { private: cocos2d::Vec2 origin; cocos2d::Size visible; cocos2d::Sprite* sprite; public: static cocos2d::Scene* createScene(); virtual bool init(); void Test_1(); void Test_2(); CREATE_FUNC(spriteFrame); }; #endif // _SPRITEFRAMETEST_SCENE_H_ .cpp files #include "SpriteFrameTest.h" USING_NS_CC; Scene* spriteFrame::createScene() { Scene* scene = Scene::create(); auto layer = spriteFrame::create(); scene->addChild(layer); return scene; } bool spriteFrame::init() { if (!Layer::init()) { return false; } visible = Director::getInstance()->getVisibleSize(); origin = Director::getInstance()->getVisibleOrigin(); Test_1(); this->Test_2(); return true; } void spriteFrame::Test_1() { Rect r = Rect(2, 2, 63, 72); auto frame = SpriteFrame::create("Hammer.bng", r); sprite = Sprite::createWithSpriteFrame(frame); sprite->setPosition(Vec2(origin.x + visible.width / 2, origin.y + visible.height / 2)); this->addChild(sprite); } void spriteFrame::Test_2() { SpriteFrameCache::getInstance()->addSpriteFramesWithFile("Mouse_3.plist"); SpriteFrame* frame = SpriteFrameCache::getInstance()->getSpriteFrameByName("Rat_1_2.png"); sprite = Sprite::createWithSpriteFrame(frame); sprite->setPosition(Vec2(origin.x + visible.width / 3, origin.y + visible.height / 3)); this->addChild(sprite); }
重要函数: