static CCSprite* createMaskSprite(CCLayerColor* base, const std::vector<CCRect>& cutoutList) { CCSize winSize = CCDirector::sharedDirector()->getWinSize(); // CCRenderTexture* rt = CCRenderTexture::create(winSize.width, winSize.height); // use a low-precision format CCRenderTexture* rt = CCRenderTexture::create(winSize.width, winSize.height, kTexture2DPixelFormat_RGBA8888); rt->setAnchorPoint(ccp(0, 0)); rt->setPosition(ccp(0, 0)); ccBlendFunc cutoutBlend = {GL_DST_ALPHA, GL_ZERO}; // render to texture rt->begin(); base->visit(); CCSprite* s = CCSprite::create("ui/1x1_b.png"); s->setAnchorPoint(ccp(0, 0)); s->setOpacity(0); for(const CCRect& cutout : cutoutList) { s->setPosition(cutout.origin); s->setScaleX(cutout.size.width * contentScale()); s->setScaleY(cutout.size.height * contentScale()); s->setBlendFunc(cutoutBlend); s->visit(); } rt->end(); // render to texture done std::string randName = std::string("mask_image_") + boost::lexical_cast<std::string>(rand()); CCImage* img = rt->newCCImage(false); img->autorelease(); CCTexture2D* tex = CCTextureCache::sharedTextureCache()->addUIImage(img, randName.c_str()); CCSprite *mask = CCSprite::createWithTexture(tex); mask->setFlipY(true); mask->setAnchorPoint(ccp(0, 0)); mask->setPosition(ccp(0, 0)); return mask; }
CCTexture2D* Util::getGrayTexture(CCTexture2D* texture){ typedef enum { RED = 0, GREEN = 1, BLUE = 2, ALPHA = 3 } PIXELS; CCSize textSize = texture->getContentSize(); CCSprite *temporarySprite = CCSprite::createWithTexture(texture); //就这么一小句搞了我半天了,不过能出来也值了 temporarySprite->setAnchorPoint(ccp(0,0)); CCRenderTexture *rt = CCRenderTexture::create(textSize.width, textSize.height); rt->begin(); temporarySprite->visit(); rt->end(); CCImage *image = rt->newCCImage(); unsigned char* pixels = image->getData(); int len = image->getDataLen(); uint32_t *p = (uint32_t *)pixels; for(int i=0;i<len;i++){ uint8_t *rgbaPixel = (uint8_t *) &p[i]; //uint32_t gray = 0.3 * rgbaPixel[RED] + 0.59 * rgbaPixel[GREEN] + 0.11 * rgbaPixel[BLUE]; uint32_t gray = 1.2*rgbaPixel[RED] + 1.0*rgbaPixel[GREEN] + 0.0*rgbaPixel[BLUE]; // set the pixels to gray rgbaPixel[RED] = gray; rgbaPixel[GREEN] = gray; rgbaPixel[BLUE] = gray; } CCTexture2D* newtexture = new CCTexture2D(); newtexture->autorelease(); newtexture->initWithImage(image); image->release(); return newtexture; }
CCSprite * BSAddStrokeToLabel(cocos2d::CCLabelTTF * label, float size, cocos2d::ccColor3B color, GLubyte opacity) { CCPoint originalPos = label->getPosition(); ccColor3B originalColor = label->getColor(); GLubyte originalOpacity = label->getOpacity(); bool originalVisibility = label->isVisible(); ccBlendFunc originalBlend = label->getBlendFunc(); label->setColor(color); label->setOpacity(opacity); ccBlendFunc bf = {GL_SRC_ALPHA, GL_ONE}; label->setBlendFunc(bf); CCPoint bottomLeft = ccp(label->getTexture()->getContentSize().width * label->getAnchorPoint().x + size, label->getTexture()->getContentSize().height * label->getAnchorPoint().y + size); CCRenderTexture* rt = CCRenderTexture::create(label->getTexture()->getContentSize().width + size * 2, label->getTexture()->getContentSize().height + size * 2); /* 在原始位置绘制文字,用于镂空用 */ label->setPosition(bottomLeft); rt->begin(); label->visit(); rt->end(); CCImage * originText = rt->newCCImage(); glBlendEquation(GL_BLEND_EQUATION_ALPHA); /* 在各个方向上移动文字,重叠得到未镂空的描边 */ rt->begin(); /* Bresenham's circle algorithm */ int radis = 3 * size; for (int x = 0, y = radis, d = 3 - 2 * radis; x <= y; ++x) { float xx = x / 3.0F, yy = y / 3.0F; label->setPosition(ccp(bottomLeft.x + xx, bottomLeft.y + yy)); label->visit(); label->setPosition(ccp(bottomLeft.x - xx, bottomLeft.y + yy)); label->visit(); label->setPosition(ccp(bottomLeft.x + xx, bottomLeft.y - yy)); label->visit(); label->setPosition(ccp(bottomLeft.x - xx, bottomLeft.y - yy)); label->visit(); label->setPosition(ccp(bottomLeft.x + yy, bottomLeft.y + xx)); label->visit(); label->setPosition(ccp(bottomLeft.x - yy, bottomLeft.y + xx)); label->visit(); label->setPosition(ccp(bottomLeft.x + yy, bottomLeft.y - xx)); label->visit(); label->setPosition(ccp(bottomLeft.x - yy, bottomLeft.y - xx)); label->visit(); if (d < 0) { d = d + 4 * x + 6; } else { d = d + 4 * (x - y) + 10; y --; } } rt->end(); /* TODO: ugly workaround. rendertexture多次绘制颜色叠加,需要取色值大的那个,需要通过glBlendEquation(GL_MAX)实现。 * see http://stackoverflow.com/questions/2143690/is-it-possible-to-achieve-maxas-ad-opengl-blending */ CCImage * strokedText = rt->newCCImage(); unsigned char * pStorke = strokedText->getData(); unsigned char * pErase = originText->getData(); for (int i = 0; i < strokedText->getDataLen(); ++i) { if ((unsigned int) pErase[i * 4] != 0) { *(unsigned int *) &pStorke[i * 4] = 0; } else if ((unsigned int) pStorke[i * 4] != 0) { unsigned char * pixel = &pStorke[i * 4]; (*pixel++) = color.r; (*pixel++) = color.g; (*pixel++) = color.b; *pixel = opacity; } } originText->release(); /* 用RenderTexture构造一个Sprite,以实现支持透明度 FadeIn FadeOut */ CCTexture2D * texture2D = new CCTexture2D(); texture2D->initWithImage(strokedText); strokedText->release(); CCSprite * sprite = CCSprite::createWithTexture(texture2D); texture2D->release(); label->setPosition(originalPos); label->setColor(originalColor); label->setBlendFunc(originalBlend); label->setVisible(originalVisibility); label->setOpacity(originalOpacity); sprite->setPosition(ccp(label->getTexture()->getContentSize().width / 2, label->getTexture()->getContentSize().height / 2)); label->addChild(sprite, -1); return sprite; }
CCSprite* CCColorUtil::graylightWithCCSprite(CCSprite* oldSprite,bool isLight) { //CCSprite转成CCimage CCPoint ptOldAnchor = oldSprite->getAnchorPoint(); CCPoint ptOld = oldSprite->getPosition(); oldSprite->setAnchorPoint(ccp(0,0)); oldSprite->setPosition(ccp(0,0)); CCRenderTexture *outTexture = CCRenderTexture::create((int)oldSprite->getContentSize().width*1,(int)oldSprite->getContentSize().height*1); outTexture->begin(); oldSprite->visit(); outTexture->end(); oldSprite->setAnchorPoint(ptOldAnchor); oldSprite->setPosition(ptOld); CCImage* finalImage = outTexture->newCCImage(); unsigned char *pData = finalImage->getData(); int iIndex = 0; if(isLight) { for (int i = 0; i < finalImage->getHeight(); i ++) { for (int j = 0; j < finalImage->getWidth(); j ++) { // highlight int iHightlightPlus = 50; int iBPos = iIndex; unsigned int iB = pData[iIndex]; iIndex ++; unsigned int iG = pData[iIndex]; iIndex ++; unsigned int iR = pData[iIndex]; iIndex ++; //unsigned int o = pData[iIndex]; iIndex ++; //原来的示例缺少 iB = (iB + iHightlightPlus > 255 ? 255 : iB + iHightlightPlus); iG = (iG + iHightlightPlus > 255 ? 255 : iG + iHightlightPlus); iR = (iR + iHightlightPlus > 255 ? 255 : iR + iHightlightPlus); // iR = (iR < 0 ? 0 : iR); // iG = (iG < 0 ? 0 : iG); // iB = (iB < 0 ? 0 : iB); pData[iBPos] = (unsigned char)iB; pData[iBPos + 1] = (unsigned char)iG; pData[iBPos + 2] = (unsigned char)iR; } } }else{ for (int i = 0; i < finalImage->getHeight(); i ++) { for (int j = 0; j < finalImage->getWidth(); j ++) { // gray int iBPos = iIndex; unsigned int iB = pData[iIndex]; iIndex ++; unsigned int iG = pData[iIndex]; iIndex ++; unsigned int iR = pData[iIndex]; iIndex ++; //unsigned int o = pData[iIndex]; iIndex ++; //原来的示例缺少 unsigned int iGray = 0.3 * iR + 0.4 * iG + 0.2 * iB; pData[iBPos] = pData[iBPos + 1] = pData[iBPos + 2] = (unsigned char)iGray; } } } CCTexture2D *texture = new CCTexture2D; texture->initWithImage(finalImage); CCSprite* newSprite = CCSprite::createWithTexture(texture); delete finalImage; texture->release(); return newSprite; }
CCRect GameUtil::getFitRect(CCSprite* pSprite) { // 원본의 원래위치 백업 CCPoint ptOrg = pSprite->getPosition(); // 원본 스프라이트 위치를 Center로 설정 pSprite->setPosition(ccp(pSprite->getContentSize().width/2, pSprite->getContentSize().height/2)); // CCImage를 만들기 위해서 RenderTexture 생성 CCRenderTexture * rtNew = CCRenderTexture::create((int)pSprite->getContentSize().width, (int)pSprite->getContentSize().height); rtNew->begin(); pSprite->visit(); rtNew->end(); // CCImage 생성 CCImage *pImage = rtNew->newCCImage(); int width = pImage->getWidth(); int height = pImage->getHeight(); int bytesPerComponent = pImage->getBitsPerComponent() / 8; // 기본값 8bit bool bAlpha = pImage->hasAlpha(); int nRGBA = 4; if (!bAlpha) nRGBA = 3; // 픽셀 데이터 (RGBA 순서, 각각 bytesPerComponent 크기만큼) unsigned char* pData = pImage->getData(); int index = 0; int l=5000; // left int r=0; // right int t=5000; // top int b=0; // bottom unsigned char* ptr; for (int x=0; x<width; x++) { for (int y=0; y<height; y++) { index = (y*width + x) * bytesPerComponent * nRGBA; ptr = pData + index; if (0 != ptr[0] || 0 != ptr[1] || 0 != ptr[2]) { l = min(l, x); // left r = max(r, x); // right t = min(t, y); // top b = max(b, y); // bottpm } } } // 좌표계 보정 (픽셀데이터는 좌상단을 0,0 으로 하기때문에) int b2 = pSprite->getContentSize().height - t; int t2 = pSprite->getContentSize().height - b; CC_SAFE_DELETE(pImage); // 원래 위치로 설정 pSprite->setPosition(ptOrg); CCRect rc; rc.origin.x = l; rc.origin.y = t2; rc.size.width = r - l; rc.size.height = b2 - t2; return rc; }
CCSprite* GameUtil::fitSprite(CCSprite* pSprite) { // 원본의 원래위치 백업 CCPoint ptOrg = pSprite->getPosition(); // 원본 스프라이트 위치를 Center로 설정 pSprite->setPosition(ccp(pSprite->getContentSize().width/2, pSprite->getContentSize().height/2)); // CCImage를 만들기 위해서 RenderTexture 생성 CCRenderTexture * rtNew = CCRenderTexture::create((int)pSprite->getContentSize().width, (int)pSprite->getContentSize().height); rtNew->begin(); pSprite->visit(); rtNew->end(); // CCImage 생성 CCImage *pImage = rtNew->newCCImage(); int width = pImage->getWidth(); int height = pImage->getHeight(); int bytesPerComponent = pImage->getBitsPerComponent() / 8; // 기본값 8bit bool bAlpha = pImage->hasAlpha(); int nRGBA = 4; if (!bAlpha) nRGBA = 3; // 픽셀 데이터 (RGBA 순서, 각각 bytesPerComponent 크기만큼) unsigned char* pData = pImage->getData(); int index = 0; int l=5000; // left int r=0; // right int t=0; // top int b=5000; // bottom unsigned char* ptr; for (int x=0; x<width; x++) { for (int y=0; y<height; y++) { index = (y*width + x) * bytesPerComponent * nRGBA; ptr = pData + index; if (0 != ptr[0] || 0 != ptr[1] || 0 != ptr[2]) { l = min(l, x); // left r = max(r, x); // right t = max(t, y); // top b = min(b, y); // bottom } } } // 좌표계 보정 (픽셀데이터는 좌상단을 0,0 으로 하기때문에) int b2 = pSprite->getContentSize().height - t; int t2 = pSprite->getContentSize().height - b; CC_SAFE_DELETE(pImage); // 원래 위치로 설정 pSprite->setPosition(ptOrg); // 스프라이트로 생성 CCSprite* pCrop = CCSprite::createWithTexture(pSprite->getTexture()); pCrop->setTextureRect(CCRect(l, b2, r-l, t2-b2)); pCrop->setPosition(ccp(pCrop->getContentSize().width/2, pCrop->getContentSize().height/2)); pCrop->setFlipY(true); // 크기에 꼭 맞는 새로운 RenderTexture를 만든다. CCRenderTexture * rtNew2 = CCRenderTexture::create(r-l, t2-b2); rtNew2->begin(); pCrop->visit(); rtNew2->end(); // 크기에 꼭 맞는 새로운 Sprite를 만든다. CCSprite *retSprite = CCSprite::createWithTexture(rtNew2->getSprite()->getTexture()); retSprite->setFlipY(true); rtNew2->release(); pCrop->release(); return retSprite; }