• Cocos2d-x之Sprite


    |   版权声明:本文为博主原创文章,未经博主允许不得转载。

      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);
    }
    

    重要函数:

     

  • 相关阅读:
    Redis学习——(1)Redis安装与配置
    Ubuntu14.04安装Apache2+SVN+Trac
    Ubuntu14.04配置文件Apache2.conf
    Ubuntu系统用户忘记密码
    java中无符号类型的处理[转]
    Golang 切片(slice)扩容机制源码剖析
    无线网络:无线城域网和无线广域网
    vue项目 镜像重置的命令
    批量下载阿里云rpm包
    HttpClient psot和get请求
  • 原文地址:https://www.cnblogs.com/geore/p/5797983.html
Copyright © 2020-2023  润新知