理解精灵的含义
学会创建一个精灵
掌握对精灵的控制
了解九宫格精灵及其应用
Sprite在2D游戏场景设计中指的就是像素图可以移动可以控制
1、通过图片路径创建精灵
Sprite* sprite = Sprite::create(“要加载的图片文件目录的相对路径”);
1、该方式创建的精灵以静态图的形式呈现
2、图片大小与原大小一致
3、如果图片显示大小超出屏幕范围,则只显示屏幕内的部分
4、如果精灵大小小于图片大小。则会按比例进行缩放图片,导致
图片变形。(长度和宽度的比例与原图长宽比不同,会导致图片变形)
SpriteDemo.h
#pragma once
#include"cocos2d.h"
USING_NS_CC;
class SpriteScene:public Scene
{
public:
CREATE_FUNC(SpriteScene);
virtual bool init();
};
SpriteDemo.cpp
bool SpriteScene::init()
{
if(!Scene::init())return false;
//创建一个精灵
Sprite* sprite = Sprite::create("要加载的图片文件目录的相对路径");
//图片太大会显示在屏幕外边,所以需要进行一个缩放,图片锚点默认在图片正中心
//sprite ->setContentSize(Size(100*100));//这样处理图片大小会变形
sprite ->setScale(0.3f);//需要进行整体缩放,缩放到原来的多少倍
sprite ->setPosition(Vec2(Director::getInstance()->getVisibleSize() / 2));
this->addChild(sprite);
return true;
}
创建完成后要去AppDelegate.cpp 调用
2、使用图集创建一个精灵
如果读取图片过多,会导致内存奔溃,使用后,需要及时清理缓存
通常图片没有达到一定数量是不会清理的,不清理的话在创建精灵
的时候去读取图片就会非常快,如果每次读取都去加载一次因为是
大图,所以会非常卡顿。一般是做场景切换的时候会去清理缓存。
string path = "plist文件的相对路径";
//通过plist文件路径将图片读取到精灵帧缓存
auto cache = SpriteFrameCache::getInstance()->addSpriteFrameWithFile(path);
//通过指定名称的精灵帧创建精灵
auto sprite = Sprite::createWithSpriteFrameName("1");
做序列帧动画的时候和做资源优化的时候会用到图集。
比如有很多张图片,有很多透明的边缘,我们想把边缘裁掉,
我们可以把很多张图片拼合在一起,拼合的时候裁剪,
最后做成一张大图,可以节省磁盘空间,也可以加快渲染的效率。
图集的产生会用到cocos2d官方提供的工具TexturePacker创建图集文件
TexturePacker集成了cocos2d生成图集的功能
会生成以下两个文件:
plist文件 、png大图;
plist文件就是xml文件,存放的每张图片的一个键值对,还包含了在大图中的偏移位置
以及精灵的大小,键是根据每张图片名称生成的可以有后缀。
SpriteDemo.h
#pragma once
#include"cocos2d.h"
USING_NS_CC;
class SpriteScene:public Scene
{
public:
CREATE_FUNC(SpriteScene);
virtual bool init();
};
SpriteDemo.cpp
bool SpriteScene::init()
{
if(!Scene::init())return false;
//创建一个精灵
Sprite* sprite = Sprite::create("要加载的图片文件目录的相对路径");
//图片太大会显示在屏幕外边,所以需要进行一个缩放,图片锚点默认在图片正中心
//sprite ->setContentSize(Size(100*100));//这样处理图片大小会变形
sprite ->setScale(0.3f);//需要进行整体缩放,缩放到原来的多少倍
sprite ->setPosition(Vec2(Director::getInstance()->getVisibleSize() / 2));
this->addChild(sprite);
//隐藏此精灵
sprite->setVisible(false);
//通过图集创建精灵
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("plist文件相对路径");
//这个 1 是对应plist文件中的文件名 键
Sprite* vampireSprite = Sprite::createWithSpriteFrameName("1");
this->addChild(vampireSprite);
vampireSprite ->setPosition(sprite->getPosition());
//吸血鬼动画实例
auto cache = SpriteFrameCache::getInstance();
//cococs2d的Vector与C++的不一样,是记录cocos2d对象的指针
Vectorimages;
//8张图片
for(int i = 1;i<=8;i++)
{
//Value()是cocos2d专门提供基本类型转换的 这里文件名是字符串所以用asString()
images.pushBack(cache->getSpriteFrameByName(Value(i).asString()));//每一帧都是一个精灵
}
Animation* _animation = Animation::createWithFrames(images,1.f/8);//每张图片间隔时间0.25m
//播放一次,停下来的就是最后一张图片
//vampireSprite ->runAction(Animate::create(_animation));
//一直播放
vampireSprite ->runAction(RepeatForever::create(Animate::create(_animation)));
return true;
}
3、使用贴图创建一个精灵
贴图又称为纹理(读取到图片的数据存入内存)
//贴图缓存
auto textureCache = TextureCache::getInstance();
//读取贴图,在缓存中添加
auto cache = textureCache->addImage("图片文件相对路径");
//通过贴图创建一个精灵
Sprite*sprite = Sprite::createWithTexture(cache);
//裁切贴图
sprite ->setTextureRect(Rect(0,0,480,320));
SpriteDemo.cpp
bool SpriteScene::init()
{
if(!Scene::init())return false;
//创建一个精灵
Sprite* sprite = Sprite::create("要加载的图片文件目录的相对路径");
//图片太大会显示在屏幕外边,所以需要进行一个缩放,图片锚点默认在图片正中心
//sprite ->setContentSize(Size(100*100));//这样处理图片大小会变形
sprite ->setScale(0.3f);//需要进行整体缩放,缩放到原来的多少倍
sprite ->setPosition(Vec2(Director::getInstance()->getVisibleSize() / 2));
this->addChild(sprite);
//隐藏此精灵
sprite->setVisible(false);
//通过图集创建精灵
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("plist文件相对路径");
//这个 1 是对应plist文件中的文件名 键
Sprite* vampireSprite = Sprite::createWithSpriteFrameName("1");
this->addChild(vampireSprite);
vampireSprite ->setPosition(sprite->getPosition());
vampireSprite ->setVisible(false);//隐藏
//通过纹理创建一个精灵
//png支持透明,jpg不支持,如果一张图片转成jpg格式就会添加一个背景色
//jpg比png占的磁盘空间更小,但是在读取到内存解析的时候png更快
auto cache = TextureCache::getInstance()->addImage("图片相对路径");
Sprite* textureSprite = Sprite::createWithTexture(cache);
this->addChild(textureSprite);
textureSprite ->setPosition(sprite->getPosition());
//0,0,前边是图片坐标,480,320是图片长宽
//如果裁切位置是240,160那么裁切出来的是图片右下角
textureSprite ->setTextureRect(Rect(0,0,480,320));//裁切
return true;
}
4、多边形精灵
对图片空白的地方进行裁切后构成多边形,算法越好裁切的就越多,
空白的地方就越少。裁切后需要着色的像素点就会变少。
读取图片生成多边形 注意: 1、图片格式只能为png图片,不支持其他格式的图片; 2、生成时会占用CPU,消耗系统性能
auto info = AutoPolygon::generatePolygon("图片相对路径",Rect(0,0,437,437));
根据多边形数据创建多边形精灵
auto sprite = Sprite::create(info);
SpriteDemo.cpp
bool SpriteScene::init()
{
if(!Scene::init())return false;
//创建一个精灵
Sprite* sprite = Sprite::create("要加载的图片文件目录的相对路径");
//图片太大会显示在屏幕外边,所以需要进行一个缩放,图片锚点默认在图片正中心
//sprite ->setContentSize(Size(100*100));//这样处理图片大小会变形
sprite ->setScale(0.3f);//需要进行整体缩放,缩放到原来的多少倍
sprite ->setPosition(Vec2(Director::getInstance()->getVisibleSize() / 2));
this->addChild(sprite);
//隐藏此精灵
sprite->setVisible(false);
//通过图集创建精灵
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("plist文件相对路径");
//这个 1 是对应plist文件中的文件名 键
Sprite* vampireSprite = Sprite::createWithSpriteFrameName("1");
this->addChild(vampireSprite);
vampireSprite ->setPosition(sprite->getPosition());
vampireSprite ->setVisible(false);//隐藏
//通过纹理创建一个精灵
//png支持透明,jpg不支持,如果一张图片转成jpg格式就会添加一个背景色
//jpg比png占的磁盘空间更小,但是在读取到内存解析的时候png更快
auto cache = TextureCache::getInstance()->addImage("图片相对路径");
Sprite* textureSprite = Sprite::createWithTexture(cache);
this->addChild(textureSprite);
textureSprite ->setPosition(sprite->getPosition());
//0,0,前边是图片坐标,480,320是图片长宽
//如果裁切位置是240,160那么裁切出来的是图片右下角
textureSprite ->setTextureRect(Rect(0,0,480,320));//裁切
//创建一个多边形精灵3.x的版本才有的
//RGBA8888这个格式就是png
auto polygonInfo = AutoPolygon::generatePolygon("图片相对路径",Rect(0,0,437,437));
Sprite* _sprite = Sprite::create(polygonInfo);
_sprite ->setPosition(sprite->getPosition());
this->addChild(_sprite);
return true;
}
| 创建精灵的方式 | 优点 | 缺点 |
|---|---|---|
| 通过图片路径创建 | 不需要清理缓存 | 图片过大,直接读取会卡顿 |
| 通过图集创建 | 图片加载速度快 | 内存占用较大,切换场景时需要清理缓存 |
| 通过贴图创建 | 图片加载速度快 | 内存占用较大,切换场景时需要清理缓存 |
| 通过多边形数据创建 | 渲染速度快 | 读取图片生成多边形信息会消耗更多CPU性能 |
游戏中常见的几种对精灵的控制
对精灵控制的演示:
1、实现精灵旋转效果
2、实现精灵淡入效果
3、实现精灵水平翻转
4、实现精灵在屏幕中自动移动
SpriteDemo.h
#pragma once
#include"cocos2d.h"
USING_NS_CC;
class SpriteScene:public Scene
{
public:
CREATE_FUNC(SpriteScene);
virtual bool init();
private:
Sprite* _sprite;
float _angel;
int _opacity;//淡入,对应到阿尔法通道,对透明度操作的
float _scaleX;
float _minScaleX;
};
SpriteDemo.cpp
bool SpriteScene::init()
{
if(!Scene::init())return false;
//创建一个精灵
Sprite* sprite = Sprite::create("要加载的图片文件目录的相对路径");
//图片太大会显示在屏幕外边,所以需要进行一个缩放,图片锚点默认在图片正中心
//sprite ->setContentSize(Size(100*100));//这样处理图片大小会变形
sprite ->setScale(0.3f);//需要进行整体缩放,缩放到原来的多少倍
sprite ->setPosition(Vec2(Director::getInstance()->getVisibleSize() / 2));
this->addChild(sprite);
//隐藏此精灵
sprite->setVisible(false);
//通过图集创建精灵
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("plist文件相对路径");
//这个 1 是对应plist文件中的文件名 键
Sprite* vampireSprite = Sprite::createWithSpriteFrameName("1");
this->addChild(vampireSprite);
vampireSprite ->setPosition(sprite->getPosition());
vampireSprite ->setVisible(false);//隐藏
//通过纹理创建一个精灵
//png支持透明,jpg不支持,如果一张图片转成jpg格式就会添加一个背景色
//jpg比png占的磁盘空间更小,但是在读取到内存解析的时候png更快
auto cache = TextureCache::getInstance()->addImage("图片相对路径");
Sprite* textureSprite = Sprite::createWithTexture(cache);
this->addChild(textureSprite);
textureSprite ->setPosition(sprite->getPosition());
//0,0,前边是图片坐标,480,320是图片长宽
//如果裁切位置是240,160那么裁切出来的是图片右下角
textureSprite ->setTextureRect(Rect(0,0,480,320));//裁切
//创建一个多边形精灵3.x的版本才有的
//RGBA8888这个格式就是png
auto polygonInfo = AutoPolygon::generatePolygon("图片相对路径",Rect(0,0,437,437));
_sprite = Sprite::create(polygonInfo);
_sprite ->setPosition(sprite->getPosition());
this->addChild(_sprite);
//实现精灵旋转效果
//将图片先缩小
_sprite ->setScale(0.3f);
//_angel = 0;
//_sprite ->setRotation(_angel );
//开启一个调度器
//this->schedule([&](float dlt)
//{
//_angel +=1.f;
//if(_angel > 360)
//{
//_angel = _angel - 360;
//}
//_sprite ->setRotation(_angel );
//},0.02f,"schedule");
//实现精灵淡入效果
//_opacity = 0;
//精灵默认透明度是255,所以需要先初始化
//_sprite ->setOpacity(_opacity);
//this->schedule([&](float dlt)
//{
//if(_opacity>= 255)
//{
//调度器用完需要注销,不然就会像线程的死循环
//this->unschedule("schedule");
//return;
//}
//_opacity+=5;
//_sprite ->setOpacity(_opacity);
//},0.02f,"schedule");
//实现精灵水平翻转(X轴)
//_scaleX = _sprite->getScaleX();
//_minScaleX = -_sprite->getScaleX();
//this->schedule([&](float dlt)
//{
//if(_minScaleX > _scaleX)
//{
//this->unschedule("schedule");
//return;
//}
//_scaleX -= 0.01f;
//_sprite ->setScaleX(_scaleX);
//},0.02f,"schedule");
//控制精灵移动
this->schedule([&](float dlt)
{
//游戏角色锚点一般在底部中心
//宽度需要乘以一个系数_sprite ->getScale(),不然缩小后的图片在原始图片的范围情况下不会到边
if(_sprite ->getPositionX() + _sprite ->getContentSize().width /2 * _sprite ->getScale() > Director::getInstance()->getVisibleSize().width
|| _sprite ->getPositionX() - _sprite ->getContentSize().width /2 * _sprite ->getScale()< 0)
{
this->unschedule("schedule");
return;
}
_sprite ->setPositionX(_sprite ->getPositionX() + 1.f);
},0.02f,"schedule");
return true;
}
九宫格古代称为"洛书"
Scale9Sprite类继承自Sprite所以也是精灵
对图片的拉伸,长宽比例会改变,但是不会
发生拉伸的形变。特点就是四个角不会变,
四条边会被拉伸。需要确定中心区域,
中心区域确定后就可以确定四个角,只改变中心区域
创建九宫格精灵
auto sprite = Scale9Sprite::create("图片相对路径");
设置九宫格中心区域
//22,22是相对整个图形的坐标位置,56,56是传入的整个中心区域的大小,长和宽 sprite ->setCapInsets(Rect(22,22,56,56));
Scale9Demo.h
#pragma once
#include"cocos2d.h"
USING_NS_CC;
#include"ui/UIScale9Sprite.h"
using namespace ui;
class Scale9SpriteScene:public Scene
{
public:
CREATE_FUNC(Scale9SpriteScene);
virtual bool init();
};
bool SpriteScene::init()
{
if(!Scene::init())return false;
//如果图片背景和颜色都是黑色,那么我们需要添加白色背景,方便观察
auto layer = LayerColor::create(Color4B::WHITE);
this->addChild(layer);
//创建九宫格精灵的演示实例
Scale9Sprite* sprite = Scale9Sprite::create("图片相对路径");
this->addChild(sprite);
//设置精灵坐标位置在屏幕正中心
sprite->setAnchorPoint(Vec2::ANCHOR_MIDDLE);
sprite->setPosition(Vec2(Director::getInstance()->getVisibleSize() / 2));
//设置九宫格精灵的中心区域
sprite->setCapInsets(Rect(20,20,1,1));
//改变图形大小
sprite->setContentSize(Size(200,200));
//改变图形形状为矩形
sprite->setContentSize(Size(300,200));
//后边创建的精灵会盖在前边的九宫格精灵下面,所以这里隐藏九宫格的
//sprite->setVisible(false);
//创建一个用于对比的精灵
//Sprite*_sprite = Sprite::create("图片相对路径");
//this->addChild(_sprite );
//_sprite ->setColor(Color3B::RED);
//设置精灵坐标位置在屏幕正中心
//_sprite ->setAnchorPoint(Vec2::ANCHOR_MIDDLE);
//_sprite ->setPosition(Vec2(Director::getInstance()->getVisibleSize() / 2));
//_sprite ->setContentSize(Size(200,200));
return true;
}
九宫格精灵VS精灵
性能参数对比
| 对比参数 | 九宫格精灵 | 精灵 |
|---|---|---|
| 图片资源占用磁盘大小 | 小 | 大 |
| 消耗CPU性能 | 小 | 小 |
| 占用内存 | 小 | 一般 |
| 渲染速度 | 一般 | 一般 |
九宫格精灵应用范围
常用于发布包(apk release)大小要求的情况,用于压缩图片大小。
演示示例:对话框自适应文字内容
要求:
文字显示内容不确定,对话框需要根据文字内容大小进行自适应匹配
bool SpriteScene::init()
{
if(!Scene::init())return false;
//如果图片背景和颜色都是黑色,那么我们需要添加白色背景,方便观察
auto layer = LayerColor::create(Color4B::WHITE);
this->addChild(layer);
//创建九宫格精灵的演示实例
Scale9Sprite* sprite = Scale9Sprite::create("图片相对路径");
this->addChild(sprite);
//设置精灵坐标位置在屏幕正中心
sprite->setAnchorPoint(Vec2::ANCHOR_MIDDLE);
sprite->setPosition(Vec2(Director::getInstance()->getVisibleSize() / 2));
//设置九宫格精灵的中心区域
sprite->setCapInsets(Rect(20,20,1,1));
//改变图形大小
sprite->setContentSize(Size(200,200));
//改变图形形状为矩形
sprite->setContentSize(Size(300,200));
//读取文字内容
auto data = FileUtils::getInstance()->getValueMapFromFile("plist文件相对路径");
if(!data.empty())
{
std::string content = data.at("1000").asString();
Label* _label = Label::create(content,"方正姚体",24);
_label ->setAnchorPoint(Vec2::ANCHOR_BOTTOM_LEFT);
//九宫格包裹了内容,内部标签距离上下左右都有20的距离
//Vec2(20,20)这个外边距的长度正好是中心区域sprite->setCapInsets(Rect(20,20,1,1));20,20的长宽
_label ->setPosition(Vec2(20,20));
//把标签直接添加到九宫格上,因为二者都是精灵
sprite->addChild(_label);
//控制宽度
if(_label->getContentSize().width>300)
{
_label->setDimensions(300,0);//宽度300像素换行
}
//Size(40,40)设置个外边距
sprite->setContentSize(_label->getContentSize() + Size(40,40));
}
return true;
}



