如何更改CCTexture2D颜色 [英] How to Change CCTexture2D Color

查看:208
本文介绍了如何更改CCTexture2D颜色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个多边形,我使用纹理和glDrawArray(使用本教程中描述的方法: http://www.raywenderlich.com/32954/how-to-create-a-game-like-tiny -wings-with-cocos2d-2-x-part-1 )。



我想要能够使用纯色填充我的多边形是在游戏过程中随机产生的。为了使用本教程中的技术,我需要动态创建一个只是纯色的纹理(例如,我可能想生成一个1x1红色方块,并使用它来填充我的多边形)。



有一种方法可以改变cocos2d中纹理的颜色,类似于使用改变sprite的颜色[mySprite changeColor :ccRed] ?所以如果我有我的初始纹理,说一个1x1的白色方块,有一种方式,我可以改变该纹理为一个1x1红色方块?



我已经尝试使用CCRenderTexture (如本教程中所述: http://www.raywenderlich.com/33266/how-to-create-dynamic-textures-with-ccrendertexture-in-cocos2d-2-x )但是,因为我会填充许多多边形,这个方法证明是很慢的。



我也尝试使用下面的代码来创建我的纹理:

  //用实心红填充
GLubyte buffer [3] = {255,0,0};

CCTexture2D * texture = [[CCTexture2D alloc] initWithData:buffer pixelFormat:kCCTexture2DPixelFormat_RGB888 pixelsWide:1 pixelsHigh:1 contentSize:m];

虽然上面的工作相当不错,但它仍然比从CCSprite抓取纹理更慢。基本上,我正在寻找一种尽可能高效地生成动态纹理的方法。



这是我用来填充我的多边形的代码:

  GLubyte buffer [3] = {arc4random()%256,arc4random()%256,arc4random 

CGSize size;
size.width = 2; size.height = 2;

CCTexture2D * texture = [[CCTexture2D alloc] initWithData:buffer pixelFormat:kCCTexture2DPixelFormat_RGB888 pixelsWide:1 pixelsHigh:1 contentSize:size];

ccTexParams params = {GL_LINEAR,GL_LINEAR,GL_REPEAT,GL_REPEAT};
[texture setTexParameters:& params];

ccGLBindTexture2D([texture name]);

glVertexAttribPointer(kCCVertexAttrib_Position,2,GL_FLOAT,GL_FALSE,0,array); //其中array是定义多边形的点的数组
glVertexAttribPointer(kCCVertexAttrib_TexCoords,2,GL_FLOAT,GL_FALSE,0,array);
glDrawArrays(GL_TRIANGLE_STRIP,0,(GLsizei)4);

[texture dealloc];

任何帮助。



这里是一个很棒的博客文章,使用CCMutableTextures http://www.cocos2d-iphone.org/pixel-based-destructible-ground- with-cocos2d /



这是我的开源项目 https://github.com/crebstar/PWNDestructibleTerrain



这是一个开源项目,我一直在夏天制作可破坏的地形环境。我刚刚发布的repo没有物理(即将到来),但提供了一个接口围绕可变纹理的精灵。这是相当原始的,因为我开始工作一个月前,但它演示了如何使用CCMutableTexture类。



大约两年前,Lam Hoang Pham发布CCMutableTexture类作为开源。我建立在他的图书馆周围,提供更多的绘图实用程序和各种其他小功能。使用CCMutableTexture类的一个警告是你不能使用PVR的,必须使用UIImage来提供纹理。我没有注意到这种方法的许多性能问题。主要的问题是你不能使用spritesheet。



这里有一些使用它的例子:

  // from the GAME LAYER 
[destTerrainSystem drawCircle:ccp(300,100)withRadius:30.0f withColor:ccc4(0,0,0,0)
[destTerrainSystem drawSquare:ccp(500,100)withRadius:30.0f withColor:ccc4(0,0,0,0)];


// IN DESTTERRAIN
- (void)drawCircle:(CGPoint)circleOrigin withRadius:(float)radius withColor:(ccColor4B)color {

int localXOrigin = circleOrigin.x - self.position.x;
int localYOrigin = self.contentSize.height - (circleOrigin.y - self.position.y);

CCMutableTexture2D * terrainTexture =(CCMutableTexture2D *)[self texture];

[terrainTexture drawCircle:ccp(localXOrigin,localYOrigin)withRadius:radius withColor:color];

if([delegate shouldApplyAfterEachDraw] || self.applyAfterDraw)[terrainTexture apply];

} // end drawCircle

- (void)drawSquare:(CGPoint)squareOrigin withRadius:(float)radius withColor:(ccColor4B)color {

int localXOrigin = squareOrigin.x - self.position.x;
int localYOrigin = self.contentSize.height - (squareOrigin.y - self.position.y);

CCMutableTexture2D * terrainTexture =(CCMutableTexture2D *)[self texture];

[terrainTexture drawSquare:ccp(localXOrigin,localYOrigin)withRadius:radius withColor:color];

if([delegate shouldApplyAfterEachDraw] || self.applyAfterDraw)
[terrainTexture apply];
} // end drawSquare


// IN CCMUTABLETEXTURE
- (void)drawCircle:(CGPoint)circleOrigin withRadius:(float)radius withColor:(ccColor4B)颜色{
/ *
画一个圆。这里有一些重叠,但它是相当高效
* /
int x = radius;
int y = 0;
int radiusError = 1 - x;

while(x> = y){

//下半部分
[self drawHorizo​​ntalLine:(x + circleOrigin.x):(circleOrigin.x - x):(y + circleOrigin.y)withColor:color];

//上半部
[self drawHorizo​​ntalLine:(x + circleOrigin.x):(circleOrigin.x - x):(circleOrigin.y - y)withColor:color];

// left side
[self drawVerticalLine:(x + circleOrigin.y)endY:(circleOrigin.y - x)atX:( - y + circleOrigin.x)withColor:color] ;

//右侧
[self drawVerticalLine:(x + circleOrigin.y)endY:(circleOrigin.y - x)atX:(y + circleOrigin.x)withColor:color];

y ++;

if(radiusError< 0){
radiusError = radiusError +((2 * y)+1);
} else {
x--; //注释掉这个值来绘制一个正方形
radiusError = radiusError +(2 *(y - x + 1));
} // end if

} // end while

//缓存已更改的col值
for(int col = circleOrigin.x - radius; col <= circleOrigin.x + radius; col ++){
if(col< 0 || col> = size_.width)
[alteredColumns addObject:[NSNumber numberWithInt:col]];
} // end for

} // end draw circle

CCMutableTexture维护像素阵列中的纹理模型(行主存储)。然后,您可以访问,更改和轮询每个像素的属性。修改数组后,您可以通过调用apply应用更改。这允许一些灵活性和性能调整,因为应用可以是昂贵的调用。



还有很多你可以做...但这应该是一个很好的起点。两个链接都有关于如何使用CCMutableTexture的示例代码。



希望这有助于


I have a polygon that I fill using a texture and glDrawArray (using the method described in this tutorial: http://www.raywenderlich.com/32954/how-to-create-a-game-like-tiny-wings-with-cocos2d-2-x-part-1).

I want to be able to fill my polygon using a solid color, which is generated at random during gameplay. To do this using the technique from the tutorial, I need to dynamically create a texture that is just a solid color (for example, I might want to generate a 1x1 red square and use that to fill my polygons).

Is there a way to change the color of a texture in cocos2d, similar to how you would change the color of a sprite using [mySprite changeColor:ccRed]? So if I had my initial texture, say a 1x1 white square, is there a way I can change that texture to a 1x1 red square?

I have already tried using CCRenderTexture (as described in this tutorial: http://www.raywenderlich.com/33266/how-to-create-dynamic-textures-with-ccrendertexture-in-cocos2d-2-x) but, as I will be filling numerous polygons, this method proves to be quite slow.

I have also tried using the following code to create my texture:

// fill with solid red   
GLubyte buffer[3] = {255, 0, 0};

CCTexture2D *texture = [[CCTexture2D alloc] initWithData:buffer pixelFormat:kCCTexture2DPixelFormat_RGB888 pixelsWide:1 pixelsHigh:1 contentSize:m];

While the above works fairly well, it is still slower than just grabbing the texture from a CCSprite. Basically, I am looking for a way to generate a dynamic texture as efficiently as possible.

Here is the code I am using to fill my polygons:

    GLubyte buffer[3] = {arc4random()%256,arc4random()%256,arc4random()%256};

    CGSize size;
    size.width = 2; size.height = 2;

    CCTexture2D *texture = [[CCTexture2D alloc] initWithData:buffer pixelFormat:kCCTexture2DPixelFormat_RGB888 pixelsWide:1 pixelsHigh:1 contentSize:size];

    ccTexParams params = {GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT};
    [texture setTexParameters:&params];

    ccGLBindTexture2D([texture name]);

    glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, array); //where array is an array of points defining a polygon
    glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, 0, array);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)4);

    [texture dealloc];

Any help is appreciated.

解决方案

Maybe what you are looking for is a mutable texture?

Here is a great blog post which utilizes CCMutableTextures http://www.cocos2d-iphone.org/pixel-based-destructible-ground-with-cocos2d/

Here is my open source project https://github.com/crebstar/PWNDestructibleTerrain

This is an open source project I've been working on over the Summer to create destructible terrain environments. The repo I just posted is without physics (soon to come), but provides an interface that wraps around mutable textures for sprites. It is fairly primitive as I started working on it a month ago, but it demonstrates how to use the CCMutableTexture class.

Around two or so years ago, Lam Hoang Pham released the CCMutableTexture class as open source. I built upon and around his library to provide more drawing utility and various other small features. The one caveat with using the CCMutableTexture class is you cannot use PVR's and must use a UIImage to provide the texture. I haven't noticed many performance issues with this method. The main problem would be you can't use a spritesheet.

Anyways here are some examples of how it is used:

 // FROM THE GAME LAYER
 [destTerrainSystem drawCircle:ccp(300,100) withRadius:30.0f withColor:ccc4(0, 0, 0, 0)];
 [destTerrainSystem drawSquare:ccp(500,100) withRadius:30.0f withColor:ccc4(0, 0, 0, 0)];


 // IN DESTTERRAIN
 -(void) drawCircle:(CGPoint)circleOrigin withRadius:(float)radius withColor:(ccColor4B)color {

int localXOrigin = circleOrigin.x - self.position.x;
int localYOrigin = self.contentSize.height - (circleOrigin.y - self.position.y);

CCMutableTexture2D * terrainTexture = (CCMutableTexture2D *) [self texture];

[terrainTexture drawCircle:ccp(localXOrigin, localYOrigin) withRadius:radius withColor:color];

if ([delegate shouldApplyAfterEachDraw] || self.applyAfterDraw) [terrainTexture apply];

} // end drawCircle

-(void) drawSquare:(CGPoint)squareOrigin withRadius:(float)radius withColor:(ccColor4B)color {

int localXOrigin = squareOrigin.x - self.position.x;
int localYOrigin = self.contentSize.height - (squareOrigin.y - self.position.y);

CCMutableTexture2D * terrainTexture = (CCMutableTexture2D *) [self texture];

[terrainTexture drawSquare:ccp(localXOrigin, localYOrigin) withRadius:radius withColor:color];

if ([delegate shouldApplyAfterEachDraw] || self.applyAfterDraw) 
    [terrainTexture apply];
} // end drawSquare


// IN CCMUTABLETEXTURE
-(void) drawCircle:(CGPoint)circleOrigin withRadius:(float)radius withColor:(ccColor4B)color {
/*
 Draws a circle. There is some overlap here but it is fairly efficient
 */
int x = radius;
int y = 0;
int radiusError = 1 - x;

while (x >= y) {

    // Bottom half
    [self drawHorizontalLine:(x + circleOrigin.x) :(circleOrigin.x - x) :(y + circleOrigin.y) withColor:color];

    // Top half
    [self drawHorizontalLine:(x + circleOrigin.x) :(circleOrigin.x - x) :(circleOrigin.y - y) withColor:color];

    // left side
    [self drawVerticalLine:(x + circleOrigin.y) endY:(circleOrigin.y - x) atX:(-y + circleOrigin.x) withColor:color];

    // right side
    [self drawVerticalLine:(x + circleOrigin.y) endY:(circleOrigin.y - x) atX:(y + circleOrigin.x) withColor:color];

    y++;

    if (radiusError < 0) {
        radiusError = radiusError +  ((2 * y) +1);
    } else {
        x--; // Comment this out to draw a square
        radiusError = radiusError + (2 * (y - x + 1));
    } // end if

} // end while

// Cache the altered col values
for (int col = circleOrigin.x - radius; col <= circleOrigin.x + radius; col++) {
    if (col < 0 || col >= size_.width) continue;
    [alteredColumns addObject:[NSNumber numberWithInt:col]];
} // end for

} // end draw circle

The CCMutableTexture maintains a model of the texture in an array of pixels (row major storage). You can then access, change, and poll for the property of each pixel. After you have modified the array, you can then apply the changes by calling apply. This allows for some flexibility and performance tweaking as apply can be an expensive call.

There is a lot more you can do... But this should be a good starting point. Both links have example code on how to use the CCMutableTexture.

Hope this helps

这篇关于如何更改CCTexture2D颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆