Cocos2d-x adds mask (mask) to Sprite)

Source: Internet
Author: User
Tags addchild

From: cocos2d-x adds a mask (mask) to Sprite)

Disclaimer (read only !) : The original translations of all tutorials provided by this blog are from the Internet and are only for learning and communication purposes. Do not conduct commercial communications. At the same time, do not remove this statement when reprinting. In the event of any dispute, it has nothing to do with the owner of this blog and the person who published the translation. Thank you for your cooperation!

Original article link: http://www.raywenderlich.com/4421/how-to-mask-a-sprite-with-cocos2d-1-0

Tutorial:

Sometimes, when you are playing a game, you may need to display a part of the genie (that is, adding a mask ).

One way is to use another image called mask. Set the middle of the mask image to white, and the white area to be visible to the mask image. Then the white area will be transparent.

Then, you can use the method provided in this tutorial to combine the mask graph and the source image, and then create the effect as shown in.

You will find that the method provided in this tutorial is very convenient and can use it to achieve many interesting results. For example, you can paste the dashboard or image box. So you can learn all this content from this tutorial!

This tutorial will teach you how to use cocos2d 1.0 to add a mask to a Sprite and use a very powerful class of ccrendertexture, which we have seen before when learning tinywings like games :)

The premise of this tutorial is that you should be familiar with cocos2d. If you are not clear about what cocos2d is, we recommend that you first learn other cocos2d tutorials on this blog.

Getting started

Start xcode, select file \ new project, select IOS \ cocos2d \ cocos2d, and click Next. Name the project maskedcal, click Next, select a folder to save, and click Create.

Next, download the resource files required for this project and drag them to your xcode Resource Group to ensure "Copy items into destination group's folder (if needed )"
Check and click Finish.

Before coding, let's start with jazz music. Open appdelegate. M and make the following changes:

// Add to top of file#import "SimpleAudioEngine.h" // At end of applicationDidFinishLaunching, replace last line with the following 2 lines:[[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"TeaRoots.mp3" loop:YES];[[CCDirector sharedDirector] runWithScene: [HelloWorldLayer sceneWithLastCalendar:0]];

Here, a video is played by Kevin
MacLeod made a very nice song, and then called a new method to load the scenario.

Next, open helloworldlayer. h and make the following changes:

// Add new instance variableint calendarNum; // Replace the +(CCScene*) scene declaration at the bottom with the following:+ (CCScene *) sceneWithLastCalendar:(int)lastCalendar;- (id)initWithLastCalendar:(int)lastCalendar;

In this scenario, we will randomly display a calendar image (from three options ). In this class, we save the serial number of the currently displayed calendar image and modify the initialization method to initwithlastcalendar. It receives an int parameter to identify the calendar image to be displayed. Later, you will see that this number will be randomly selected from 1-3.

Then, return to helloworldlayer. M and make the following changes:

// Replace +(CCScene *) scene with the following+(CCScene *) sceneWithLastCalendar:(int)lastCalendar // new{    CCScene *scene = [CCScene node];    HelloWorldLayer *layer = [[[HelloWorldLayer alloc]         initWithLastCalendar:lastCalendar] autorelease]; // new    [scene addChild: layer];        return scene;} // Replace init with the following-(id) initWithLastCalendar:(int)lastCalendar{    if( (self=[super init])) {         CGSize winSize = [CCDirector sharedDirector].winSize;         do {            calendarNum = arc4random() %3+1;        } while (calendarNum == lastCalendar);         NSString * spriteName = [NSString             stringWithFormat:@"Calendar%d.png", calendarNum];         CCSprite * cal = [CCSprite spriteWithFile:spriteName];         // BEGINTEMP        cal.position = ccp(winSize.width/2, winSize.height/2);                [self addChild:cal];        // ENDTEMP         self.isTouchEnabled = YES;    }    return self;} // Add new methods- (void)registerWithTouchDispatcher {    [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self         priority:0 swallowsTouches:YES];} - (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {    CCScene *scene = [HelloWorldLayer sceneWithLastCalendar:calendarNum];    [[CCDirector sharedDirector] replaceScene:        [CCTransitionJumpZoom transitionWithDuration:1.0 scene:scene]];    return TRUE;}

Here is just some basic cocos2d code used to randomly display a calendar image in the middle of the screen. It also contains some logic. When you click the screen, you can smoothly switch to another image.

Compile and run. Now you can see some random calendar pictures every time you click on the screen. They are all done by my lovely wife :)

Now, we have set up the program framework. Next, let's implement the mask effect!

 

Blend Mode)

If you open the art \ calendarmask.png image in the image editing software, it looks like this:

We will use this image to add a border for our calendar image, which is a border with a ripple effect, not a quadrilateral. The transparent part of the image is the mask effect, while the white area is the area that the calendar image will display.

To achieve this, we will use the OpenGL hybrid mode.

If you go back to the Tutorial "How to Use ccrendertexture to dynamically create Textures", we will discuss the OpenGL hybrid mode there. I mentioned a very convenient online tool that can be used to visualize and adjust the effect of the hybrid mode.

To achieve the desired effect, we need to adopt the following strategy:

  1. First, we will render the mask genie, set SRC color (that is, the mask genie) to gl_one, and set destination color (an empty buffer) to gl_zero. Therefore, the effect is simply to display the mask image.
  2. Next, we will render the calendar image genie. Set SRC color (calendar) to gl_dst_alpha. It means to see the current alpha value of the mask image. If it is 0 (completely transparent), it will display the mask. If it is 1 (completely opaque), the calendar image is displayed. (For more information, see this link ). Then put DST
    Color (the mask) is designed to be gl_zero. In this way, the previously rendered mask disappears.

Cool! You may think that we only need to render the mask genie first, then render the calendar genie, and specify the blendfunc of the two genie. However, this is actually not feasible!

The above-mentioned hybrid algorithm may cause problems when there are some Genie under the genie rendering-for example, there is an genie on the background image. This is because, here is a hypothesis. After completing step 1 above, only one image exists in the Imgae buffer, that is, the mask. (Of course, this assumption is incorrect, because you want to switch the calendar image, right ?)

Therefore, we need a way to create a clean "blackboard" and then perform Step 1 and 2 to create a mask texture. Fortunately, it is very convenient to use ccrendertexture.

Masking and ccrendertexture

Ccrendertexture is a class that enables rendering in the buffer outside the screen.

It is very convenient to use, mainly for the following reasons-you can use it to screenshot your game and efficiently cache user-rendered content, you can dynamically create a Sprite sheet at runtime, Or, just like in this tutorial, you can create a mask Sprite.

To use ccrendertexture, you need to take the following four steps:

  1. Create the ccrendertexture class, in pixels, and specify the width and height of the texture you want to draw.
  2. Call the begin method of ccrendertexture to initialize the rendering operation.
  3. Call the OpenGL function to draw the actual content-however, these OpenGL calls will eventually be drawn out of the screen without affecting the current rendering images in the game.
  4. Call the end method of ccrendertexture to end the painting operation. After you finish, the ccrendertexture has a Sprite attribute. You can use it as ccsprite.

Do not think step 2 is very strange-because you are using cocos2d, in 3rd, you do not need to manually call OpenGL functions. However, if you want to render a node, you can directly call the visit method of a node, such as [sprite visit], then this function will automatically send you some OpenGL function pointers to the graphic hardware for display.

One thing to note here is the coordinate problem. (0, 0) points are the position in the lower left corner of the rendered texture. Therefore, you must set the coordinates when using ccrendertexture.

Well, you may get bored. Programmers still like to read the code. Okay. Let's start coding!

Add a mask to the genie: the final implementation

Open helloworldlayer. M and add the following method to the init method:

- (CCSprite *)maskedSpriteWithSprite:(CCSprite *)textureSprite maskSprite:(CCSprite *)maskSprite {      // 1    CCRenderTexture * rt = [CCRenderTexture renderTextureWithWidth:maskSprite.contentSizeInPixels.width height:maskSprite.contentSizeInPixels.height];     // 2    maskSprite.position = ccp(maskSprite.contentSize.width/2, maskSprite.contentSize.height/2);    textureSprite.position = ccp(textureSprite.contentSize.width/2, textureSprite.contentSize.height/2);     // 3    [maskSprite setBlendFunc:(ccBlendFunc){GL_ONE, GL_ZERO}];    [textureSprite setBlendFunc:(ccBlendFunc){GL_DST_ALPHA, GL_ZERO}];     // 4    [rt begin];    [maskSprite visit];            [textureSprite visit];        [rt end];     // 5    CCSprite *retval = [CCSprite spriteWithTexture:rt.sprite.texture];    retval.flipY = YES;    return retval; }

Let's break down the following operations step by step:

  1. Use the size of the mask sprite to create the ccrendertexture
  2. Reset the location of the mask Genie and texture genie so that the lower left corner of them is (0, 0)
  3. As discussed earlier, set blendfunc for each genie.
  4. Call the ccrin method of ccrendertexture to start the rendering operation, then render the mask and texture genie in sequence, and finally call the end method.
  5. Create a new sprite Based on the sprite attribute of the ccrendertexture and flip y at the same time because the texture is inverted.

Now, we can use the above function to create the mask effect:

CCSprite * mask = [CCSprite spriteWithFile:@"CalendarMask.png"];        CCSprite * maskedCal = [self maskedSpriteWithSprite:cal maskSprite:mask];maskedCal.position = ccp(winSize.width/2, winSize.height/2);[self addChild:maskedCal];

Compile and run. Now, you can see an Genie With a mask effect.

 

Disadvantages of the ccrendertexture Method

For this simple tutorial, the method proposed here is still relatively OK, but this method also has some disadvantages, especially for complex projects:

  • Each time you apply a mask, an extra texture image is created in the memory.The amount of memory occupied by textures on the iPhone is very limited, so you should be very careful to minimize the number of texture images loaded in the memory. When you only add a mask to one image at a time, this method is good, but what if 100 images require a mask?
  • Rendering is time-consuming.The cost of using the ccrendertexture for rendering is very high, especially when the texture size increases. If you often use this method to draw, it will seriously affect the performance.

As I mentioned earlier, I have not found a better way to do this in opengles 1.0. However, by using OpenGL ES 2.0, we can use shader, which is much more efficient.

Where to go?

The complete source code of this tutorial is provided here.

We are looking forward to the next tutorial. In the next tutorial, we will use cococs2d 2.0 to write a customized shader to add a mask to the image.

Note: Due to my recent busy schedule, blog updates may be slow in the near future. Please forgive me.

I suggest you read a few books. First, of course, it is "Learn iPhone and iPad cocos2d game development" and "Learning cocos2d". This is also a classic and comprehensive book about cocos2d on the market. Then, you can learn about opengles and recommend two books, learning iOS game programming and oreilly. iphone.3d. Programming. may.2010. These books are downloaded on the Internet. I have read the two cocos2d books mentioned above and it feels good. If you have any questions during the reading process, please leave a message to discuss them with me. It is very important to learn about game development and mathematical physics. If you are familiar with mathematics and physics. Of course, OpenGL also requires a lot of mathematical knowledge.

Bytes ------------------------------------------------------------------------------------------------------
Because the tutorial is iOS platform, I on the Android platform reference example, with a cocos2d-x to achieve once, paste the main code:

Bool helloworld: Init () {// 1. super init first if (! Cclayer: Init () {return false;} ccsize S = ccdirector ctor: shareddirector ()-> getwinsize (); int calendarnum = 0; do {calendarnum = ccrandom_0_1 () * 2;} while (calendarnum = mlastcalendar); mlastcalendar = calendarnum; // STD: string name = "calendar"; STD: stringstream SS; SS <mlastcalendar; name + = ss. STR (); name + = ". PNG "; // load the sprite and set it to full screen ccsprite * sprite = ccsprite: Create (name. c_str (); SPR ITE-> setscalex (float) screen_width/sprite-> getcontentsize (). width); sprite-> setscaley (float) screen_height/sprite-> getcontentsize (). height); sprite-> setposition (CCP (S. width/2, S. height/2); // load the mask image ccsprite * masksprite = ccsprite: Create ("calendarmask.png"); masksprite-> setscalex (float) screen_width/masksprite-> getcontentsize (). width); masksprite-> setscaley (float) screen_height/masksprite -> Getcontentsize (). height); masksprite-> setposition (CCP (S. width/2, S. height/2); ccsprite * maskcal = maskedspritewithsprite (sprite, masksprite); maskcal-> setposition (CCP (S. width/2, S. height/2); addchild (maskcal); settouchenabled (true); Return true;} cocos2d: ccsprite * helloworld: equals (cocos2d: ccsprite * texturesprite, cocos2d :: ccsprite * masksprite) {// 1 int W = masksprite-> get Contentsize (). width * masksprite-> getscalex (); int H = masksprite-> getcontentsize (). height * masksprite-> getscaley (); ccrendertexture * RT = ccrendertexture: Drawing (W, H); // 2 masksprite-> setposition (CCP (masksprite-> getcontentsize (). width * masksprite-> getscalex ()/2, masksprite-> getcontentsize (). height * masksprite-> getscaley ()/2); texturesprite-> setposition (CCP (texture Sprite-> getcontentsize (). width * texturesprite-> getscalex ()/2, texturesprite-> getcontentsize (). height * texturesprite-> getscaley ()/2); // 3 ccblendfunc blendfunc; blendfunc. src = gl_one; blendfunc. DST = gl_zero; masksprite-> setblendfunc (blendfunc); blendfunc. src = gl_dst_alpha; // The current alpha value of the mask image. If it is 0 (completely transparent), the mask is displayed. If it is 1 (completely opaque) blendfunc. DST = gl_zero; // masksprite invisible texturesprite-> setblendfunc (blendfunc); // 4 RT-> begin (); masksprite-> visit (); texturesprite-> visit (); RT-> end (); // 5 ccsprite * retval = ccsprite: spritewithtexture (RT-> getsprite ()-> gettexture ()); retval-> setflipy (true); Return retval ;}

Complete cocos2d-x implementation code download

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.