cocos2dx:如何将按钮的三张图片节省为一张
2013-12-10 13:07
274 查看
在创建按钮的时候,按钮有三个状态:1、正常;2、被点击;3、不可用。 最常见的用法是,美术会做三个状态的按钮。 但是这样会不会太浪费? 因为这三个按钮只是颜色上有区别而已,而玩家最常见的其实就是正常和不可用状态下的按钮,而第二种状态的按钮其实并不特别关注。 cocos2dx里的精灵支持着色上的改变,于是,对于区分要求不是特别高的“被点击”的按钮,就可以用setColor方法来改变。看过精灵类源代码的使用者都能发现这个方法,这个方法很常用。 示例1:pSpirit->setColor(ccGRAY);//ccGRAY是引擎预定义的颜色常量。 示例2:pSpirit->setColor(ccc3(128,128,128));//ccc3是宏,里面的三个参数就是颜色的RBG了,可以自己调试颜色,或者让美术提供参数。 于是这样就可以节省一个“被点击”的按钮图片了,这通常能够为整个安装包缩减10K以上的体积,积少成多——在所有的地方都这样子节省吧,美术也能减少工作量哦。 但是,“不可用”的按钮怎么办呢?使用setColor的方法进行实验,发现不管如何设置,都不能达到那种“变灰”的那种味道。 为了节省资源和人力,其实可以给按钮构造方法的“disabled”参数传入一个NULL,但是这样做的结果就是,这个按钮调用setEnable()方法后,不会出现不可用的状态。 通过寻找资料,笔者找到一份网友写好的代码,实验之后可以正常使用:GraySprite.h
// Created by rekoo on 13-7-23.
#ifndef __goddess__GraySprite__
#define __goddess__GraySprite__
#include "cocos2d.h"
#include "cocos-ext.h"
USING_NS_CC;
USING_NS_CC_EXT;
class
GraySprite :
public
CCSprite
{
public
:
GraySprite();
~GraySprite();
bool
initWithTexture(CCTexture2D* texture,
const
CCRect& rect);
void
draw();
void
initProgram();
void
listenBackToForeground(CCObject *obj);
static
GraySprite* create(
const
char
*pszFileName);
};
#endifGraySprite.cpp
// Created by rekoo on 13-7-23.
#include "GraySprite.h"
GraySprite::GraySprite()
{
}
GraySprite::~GraySprite()
{
}
GraySprite* GraySprite::create(
const
char
*pszFileName)
{
GraySprite* pRet =
new
GraySprite();
if
(pRet && pRet->initWithFile(pszFileName))
{
pRet->autorelease();
}
else
{
CC_SAFE_DELETE(pRet);
}
return
pRet;
}
void
GraySprite::listenBackToForeground(CCObject *obj)
{
setShaderProgram(NULL);
initProgram();
}
bool
GraySprite::initWithTexture(CCTexture2D* texture,
const
CCRect& rect)
{
if
( CCSprite::initWithTexture(texture, rect) )
{
CCSize s = getTexture()->getContentSizeInPixels();
this
->initProgram();
return
true
;
}
return
false
;
}
void
GraySprite::initProgram()
{
const
GLchar * pfrag = "#ifdef GL_ES \n \
precision mediump
float
; \n \
#endif \n\
uniform sampler2D u_texture; \n \
varying vec2 v_texCoord; \n \
varying vec4 v_fragmentColor; \n \
void
main(
void
) \n \
{ \n \
float
alpha = texture2D(u_texture, v_texCoord).a; \n \
float
grey = dot(texture2D(u_texture, v_texCoord).rgb, vec3(0.299,0.587,0.114)); \n \
gl_FragColor = vec4(grey, grey, grey,alpha); \n \
} ";
CCGLProgram* pProgram =
new
CCGLProgram();
pProgram->initWithVertexShaderByteArray(ccPositionTextureColor_vert, pfrag);
setShaderProgram(pProgram);
pProgram->release();
CHECK_GL_ERROR_DEBUG();
getShaderProgram()->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
getShaderProgram()->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color);
getShaderProgram()->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);
CHECK_GL_ERROR_DEBUG();
getShaderProgram()->link();
CHECK_GL_ERROR_DEBUG();
getShaderProgram()->updateUniforms();
}
void
GraySprite::draw()
{
ccGLEnableVertexAttribs(kCCVertexAttribFlag_PosColorTex );
ccBlendFunc blend = getBlendFunc();
ccGLBlendFunc(blend.src, blend.dst);
getShaderProgram()->use();
getShaderProgram()->setUniformsForBuiltins();
ccGLBindTexture2D( getTexture()->getName());
#define kQuadSize sizeof(m_sQuad.bl)
long
offset = (
long
)&m_sQuad;
int
diff = offsetof( ccV3F_C4B_T2F, vertices);
glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (
void
*) (offset + diff));
diff = offsetof( ccV3F_C4B_T2F, texCoords);
glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (
void
*)(offset + diff));
diff = offsetof( ccV3F_C4B_T2F, colors);
glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (
void
*)(offset + diff));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
CC_INCREMENT_GL_DRAWS(1);
} 可以看到这个类继承了精灵类,并写了自己的构造方法,还重写了父类的draw方法。 这个类该怎么使用呢? 普通的写法就是,把“不可用”状态下的按钮精灵使用这个类进行创建,这样就会是一个灰色的精灵,因为它是精灵类的子类,所以它可以直接用在MenuItem构造方法里的参数里——于是,第三个按钮图片也省下来了。 但是这个类有局限性,纹理打包技术是cocos2dx里经常会使用到的,很多图片都会使用纹理打包,而这些纹理,它并没有对应的构造方法,有的也是父类的,关键性的initProgram方法没法调用到。 那么,我们有几个方案: 方案1、修改这个类,让它重写精灵类的各种构造初始化方法; 方案2、类型转换。 方案1的工作量有些大,几乎把精灵类重新写了一遍,说不定还是直接去修改精灵类源码比较好。 然后我们来看看方案2: 示例: ((GraySprite*)pSprite)->initProgram(); 这样,就能够把一个精灵灰度化了,而且除了灰度,精灵本身没有改变什么。 想想看这个功能,还能够使用在什么地方吧——
相关文章推荐
- Android图片加载方案——如何保证图片清晰度同时,最大限度节省内存使用量
- 如何用一张图片做背景图,并且图片自适应div的大小
- 安卓中如何把一张图片加工成圆形
- 如何使用图片按钮作为重置(reset)表单按钮
- 网页上如何实现点击一张图片弹出QQ聊天窗口?
- 如何给对话框添加背景图片及图片按钮CBUttonST
- file manager中查看图片时切换上一张/下一张时如何将非image格式的文件过滤掉
- JAVA Eclipse如何设置点击按钮切换图片
- iPhone 如何使用UIImageView播放动画,并停留在之后一张图片并添加播放结束时的事件
- android 通知栏如何更新图片、按钮
- 如何使带背景图片的Button按钮中的文字居中偏上显示
- 将一张图片做成文件选择按钮
- html中如何把图片变成按钮
- JAVA Eclipse如何设置点击按钮切换图片
- 在程序中如何把两张图片合成为一张图片
- c#WINFORM中如何为动态生成的按钮加背景图片
- [WinForm每日一贴] 如何实现UltraGrid中的图片按钮效果
- 如何通过一张图片找到你的位置?
- cocos2dx-js RenderTexture 将多张图片合并成一张图片
- 如何实现文字加透明背景显示在一张图片的底部的效果