how to create sprite frame animations

how to create sprite frame animations
Dr.KiranArora Profile Pic
Published Date:27-10-2017
Your Website URL(Optional)
Visual Effects and Animations In this chapter, you’ll learn how to create sprite frame animations, how to design particle effects, and how to apply shader effects via the Effect node, which is essentially a sprite’s effects list. Sprite Frame Animations A common way to animate sprites is by cycling through a series of images. This is called a sprite frame animation. In essence, it’s the same as changing a sprite’s texture every so often. The term sprite frame refers to an extra class, CCSpriteFrame, provided by Cocos2D, which has a reference to the texture plus extra information to address the sprite as an area within the texture. Often, the texture is in fact a Sprite Sheet texture, and the CCSpriteFrame class contains information where a specific image can be found within the texture. Creating a Sprite Frame Animation In the SpriteSheets/Global Sprite Sheet, you should find images named player-anim1.png through player-anim3.png. If they aren’t there, check the Graphics archive that came with the book. Inside the Global folder, you will find those images, drag and drop them from Finder onto the SpriteSheets/Global Sprite Sheet to add them. You can also use your own series of images as long as they have the same dimensions as the existing player.png. Now when you select all three player-anim.png images in the SpriteSheets/Global Sprite Sheet and right-click to bring up the context menu, you’ll see the same menu item highlighted in Figure 12-1. But don’t click on this menu item just yet. 343344 CHAPTER 12: Visual Effects and Animations Figure 12-1. “Create Keyframes from Selection” creates Sprite Frame animation keyframes on the currently selected sprite node Because Create Keyframes from Selection is a context menu item, you’d expect it to apply at any time—but apply to what? In fact, this menu item works only if you have an open CCB file and have selected a sprite node. The menu item will do nothing if the selected node isn’t a sprite node, or if you have multiple sprite nodes or no sprite nodes selected. There’s no feedback in those cases whatsoever. You’ll just notice that the command didn’t add any keyframes. So open the PlayerSoftBody.ccb in the Prefabs folder, and then select the root node labeled CCSprite as seen in Figure 12-1. Make sure the Timeline Cursor is moved to the far left. Then select the three player-anim.png images, right-click to bring up the context menu, and select Create Keyframes from Selection. You’ll notice that three sprite frame keyframes have been added to the Timeline. If you play this animation, you should see the player close his eye lids. Caution At the time of this writing, SpriteBuilder had an issue with keyframes on a CCB’s root node: A root node’s sprite frame keyframes could not be selected. I had to manually add each sprite frame animation keyframe one by one, moving the Timeline Cursor into the desired keyframe position before issuing the Create Keyframes from Selection command on an individual player-anim.png image. I assume the issue will be fixed by the time you read this book; but if it is not, at least now you know how to work around it. CHAPTER 12: Visual Effects and Animations 345 Since the Create Keyframes from Selection command creates a very fast sequence of keyframes and will almost never match the desired animation speed, SpriteBuilder provides a way to evenly space a selection of keyframes. In order to select multiple keyframes, you can either click on them with the Shift key held down or simply click with your mouse on an empty area on the Timeline (where the keyframes are) and start dragging. This will draw a selection rectangle that will select all keyframes inside the rectangle when you let go of the mouse button. With the three sprite frame animation keyframes selected, select the Animation ➤ Stretch Selected Keyframes menu item as seen in Figure 12-2. Figure 12-2. Spacing keyframes equally can be done via the Stretch Selected Keyframes command This will bring up a small dialog where you can enter a Stretch Factor value. Enter 3.0 as the value and click Done. The keyframes should now be further apart. Since the player is closing his eye lids in the animation, it should also open them again a short while later. Move the Timeline Cursor to the position where the player should open its eyes again, perhaps half a second after the last sprite frame keyframe. With the CCSprite root node still selected, select player-anim1.png and player-anim2.png in the SpriteSheets/Global Sprite Sheet. Or if you still have all three selected, you can also just deselect player-anim3.png by clicking on it with the Cmd key held down. Either way, player-anim1.png and player-anim2.png should be selected. Then right-click one of the selected images and run the Create Keyframes from Selection command once more. Now those two keyframes are in the wrong order. Select them both, and then run Animation ➤ Reverse Selected Keyframes (as shown in Figure 12-2) to reverse their order. Running this animation will now have the player close its eye lids and open its eyes shortly thereafter. For reference, Figure 12-3 shows the approximate result for this sprite frame animation with a total of five sprite frame keyframes.346 CHAPTER 12: Visual Effects and Animations Figure 12-3. Being the model for an entire SpriteBuilder book can be grueling, tiring work The first and fifth (last) keyframe should be the image of the player as you know it, with eyes wide open. The second and fourth keyframe should use the sprite frame with the eyes half closed. The third (middle) keyframe should use the sprite frame with the player’s eyes fully closed. Played together, this will make the player blink, and the entire animation runs for just about half a second. Now click on the Timeline Duration control, and change the length of the animation to about 3 seconds. This affects how often the player will blink. If you let the Timeline run for 10 seconds, the player will blink only every 10 seconds. If you change it down to just a second, the player will blink very frequently. Caution After changing the Timeline Duration, verify that none of the sprite frame keyframes have been cut off. The blinking animation shouldn’t run much longer than half a second. If you change the Timeline Duration to less than half a second, this may irreversibly remove excess keyframes—namely, those whose timestamp would now be greater than the Timeline’s duration. Finally, click on the Timeline Chain drop-down menu, and select Default Timeline. This will have the Timeline loop indefinitely in the game. Now if you try this out in the game. . . there won’t be an animation playing. The sprite frame keyframes don’t have any effect yet because the SoftBodyPlayer.ccb uses a custom class to perform custom rendering. CHAPTER 12: Visual Effects and Animations 347 Adding Sprite Frame Animations to SoftBodyDrawNode SoftBodyPlayer.ccb uses a custom class called SoftBodyDrawNode. This CCSprite subclass uses the initially assigned spriteFrame property of CCSprite to initialize the vertex and texture coordinates for the sprites. However, it doesn’t currently update the texture coordinates when the spriteFrame property changes. Thus, the sprite frame animation currently has no effect. To fix this, you’ll first have to add an ivar that marks the point in time at which the player has been initialized. This _didLoad flag is important because initially CCBReader will assign at least one CCSpriteFrame to the sprite’s spriteFrame property, whose setter you’re going to override in order to call the updateTextureCoordinates method every time the sprite frames change. But the initial spriteFrame assignments should not trigger the updateTextureCoordinates method, as its values may not be set up and initialized yet. Add the ivar highlighted in Listing 12-1 to the SoftBodyDrawNode implementation in SoftBodyDrawNode.m. Listing 12-1. The _didLoad flag is used to determine whether the node has been fully initialized implementation SoftBodyDrawNode // existing ivars omitted for brevity ... BOOL _didLoad; Then update the didLoadFromCCB method. Add the highlighted line in Listing 12-2 to the end of the method. This will mark the node as being fully set up for our intents and purposes. Listing 12-2. The node is considered initialized by the time the didLoadFromCCB method returns -(void) didLoadFromCCB self setup; _didLoad = YES; The key change here is to override the spriteFrame property setter method, which is aptly named setSpriteFrame:. It follows the common naming scheme for property setters (set with an uppercase first letter of property name, receiving a parameter of property type) and getters (same as the property name, taking no parameters and returning the property type). Every time the Timeline animation changes the spriteFrame property, you’ll need to run the updateTextureCoordinates method in order to point it to the new area within the Sprite Sheet texture to draw from. If that isn’t done, it will simply keep on drawing the sprite frame that was set initially. Add the setSpriteFrame: method of Listing 12-3 to SoftBodyDrawNode.m, preferably at the very bottom just above the end line.348 CHAPTER 12: Visual Effects and Animations Listing 12-3. Overriding the spriteFrame property setter to update texture coordinates -(void) setSpriteFrame:(CCSpriteFrame )spriteFrame super setSpriteFrame:spriteFrame; if (_didLoad) self updateTextureCoordinates; The _didLoad flag prevents the updateTextureCoordinates method from being run before didLoadFromCCB. This is important because the setup method called in Listing 12-2 needs to run before any call to updateTextureCoordinates; otherwise, the _vertices pointer’s memory would not have been allocated, resulting in a crash. Of course, setSpriteFrame: does get called at least once before didLoadFromCCB, by CCBReader. At some point, CCBReader has to assign the sprite’s initial spriteFrame as set up in SpriteBuilder, and any assignments issued by CCBReader itself need not update the texture coordinates. Now you can build and run the game, and you’ll see the player blink its eyes about every three seconds, or whatever duration you set for the default Timeline in SoftBodyPlayer.ccb. Comparing Sprite Frames You may also want to override the setSpriteFrame: method in other CCSprite subclasses if you want to run code when specific frames are being displayed but you don’t want to (or can’t) use the Callbacks keyframes to do so. You can get and store sprite frames in ivars (or arrays or dictionaries) which, when passed into the setSpriteFrame: method, should run specific selectors. For instance, this can be used to synchronize sound effects or speech to start with a specific sprite frame. Note This is a theoretical example. You needn’t add the following code to the project. Assuming that _triggerFrame is a CCSpriteFrame ivar (it must be declared without the __weak keyword), you can assign it in didLoadFromCCB of the CCSprite subclass in which you want to monitor an animation to play a sound effect when a specific sprite frame is set. Listing 12-4 shows you how it’s done. Take note that, as with all resources, you have to specify the relative path to the file. Listing 12-4. Obtaining a sprite frame reference for a given animation image -(void) didLoadFromCCB _triggerFrame = CCSpriteFrame frameWithImageNamed: "SpriteSheets/Anims/facepalm42.png"; CHAPTER 12: Visual Effects and Animations 349 The frameWithImageNamed: method will return the cached image if it has already been loaded. This will be the case if the image is in the same Sprite Sheet as the sprite frame that the sprite initially uses. That would be the sprite frame that’s assigned to the sprite in SpriteBuilder. The frameWithImageNamed: method and similar “look up by name” methods perform at least a string comparison. More likely, they’ll also run some name-mangling code in order to locate the image resource, which could theoretically be found in a number of different locations. Therefore, it’s recommended to avoid running frameWithImageNamed: and similar methods while the gameplay is underway. Loading resources at runtime is a common source of short, intermittent drops in frame rate (appropriately nicknamed hiccups). With a strong reference to the sprite frame in question assigned to _triggerFrame, you can now override setSpriteFrame: and compare the incoming spriteFrame parameter with the one referenced by _triggerFrame. If both are equal, that’s when you can fire a method to run any code that’s supposed to be synchronized with specific sprite frames. In Listing 12-5, that would play a sound effect specific to the animation. Listing 12-5. Running a method when the new spriteFrame matches a specific sprite frame -(void) setSpriteFrame:(CCSpriteFrame )spriteFrame super setSpriteFrame:spriteFrame; if (_triggerFrame isEqual:spriteFrame) self playFacepalmSoundEffect; To compare the two sprite frames, the isEqual: method is used. While in this case a direct pointer comparison _triggerFrame == spriteFrame would have worked too, it is better style to use isEqual: because many Objective-C objects can’t be compared through their pointer values alone. This potential pitfall is best explained by example: you can create two instances of CCColor, both using the same init method and parameters (initWithWhite:1.0 alpha:1.0), yet you’ll have two different objects occupying two different memory addresses. The pointer equality test using the equality operator == will evaluate to NO (false), but using isEqual: gives CCColor the chance to compare its properties. Assuming the isEqual: method is properly implemented, it will determine that all of its properties are identical—in which case, isEqual: returns YES (true) even though both may be two separate objects. 350 CHAPTER 12: Visual Effects and Animations Particle Effects Particle effects are possibly the best known type of visual effect, at least in 2D games. In SpriteBuilder and Cocos2D, they’re referred to as a particle system, which is the equivalent of the better known and more descriptive term particle emitter. The CCParticleSystem node is a node that emits particles. Henceforth, I shall use emitter when I refer to a particle system. It better describes what the node does. Limitations of Particle Effects The thing with particles is that they can be rendered more efficiently than if you were to use the same number of sprites with the same behavior. The downside to that is that you have absolutely no access or control over individual particles except for the parameters provided by the emitter. For instance, you can’t access, remove, or otherwise modify specific particles. You can’t even identify or obtain references to individual particles, nor can you run actions on them. While the particle system node itself can have physics enabled, there’s little use in that: individual particles will not collide with other physics bodies or other particles. Only the emitter node as a whole can have a collision shape and can be moved about by the physics engine. Unless the particle effect is designed to (roughly) contain all emitted particles within the physics shape, this probably won’t be too useful. A ring of particles with a circle physics shape is likely the best possible use case. Particle effects are also a major source of performance issues. Particle emitters with a total particles count of over 100 are likely using far too many particles. A three-digit particle count should definitely ring an alarm bell and be put under tight scrutiny. A large particle count may be justifiable for a special effect designed to be used in a specific scene, perhaps as the only particle effect or where the scene isn’t performance critical. Also, using a lot of very small particles with a small particle texture can still work well. A common mistake is to design particle effects with hundreds of allowed particles only to realize that this emitter will sink the frame rate to rock bottom even on high-end devices. Another common mistake is having a particle effect that runs (mostly) fine except for specific older devices, with the iPhone 4 being a particularly common candidate due to its underpowered graphics hardware. Always be prepared to remove an effect, or have a backup effect with fewer particles for such cases. Test your particle effects early on a device, and if you can, test them specifically on the slowest device you have access to. Particle textures have to be square images. Any nonsquare texture will be scaled and therefore stretched to match the nearest square size. In general, particle textures should be rather nondescript, like a cloud or gradient pattern. Particle effects typically look best if the particle texture has little discernible detail. Exceptions are very specific particle effects with few individual particles, like dropping leaves or cartoon stars circling around a knocked-out character’s head. CHAPTER 12: Visual Effects and Animations 351 Each particle emitter can only emit particles using a single texture. If you need to combine multiple textures into the same particle effect, you’ll have to create multiple emitter nodes and decide whose particles should be drawn over or under the other emitter’s particles. The same goes for effects that should have more complex behavior, such as an effect where most particles should orbit the emitter’s position but occasionally some of them should shoot out and away from the center. This requires two emitters. Editing Particle System Parameters For the particle-emitter example, you’ll be adding a fire glow to the menu background. Open MainMenuBackground.ccb in the UserInterface folder. From the Node Library View, drag and drop a Particle System (emitter) node onto the stage. Then drag and move it in the Timeline so that it is between the M_monsters and M_frontsmoke nodes. (See Figure 12-4.) Figure 12-4. The CCParticleSystem node should be above the M_frontsmoke image With the CCParticleSystem node selected, switch to the Item Properties tab and set the position of the emitter node to 0x-200. New particles should appear close to the bottom of the background images. I will explain each particle-emitter property. As you go over each particle-emitter property, you should apply the values shown in Figure 12-5 and Figure 12-6 to the newly added Particle System node.352 CHAPTER 12: Visual Effects and Animations Figure 12-5. Particle System values common to both radial and gravity particle emittersCHAPTER 12: Visual Effects and Animations 353 Figure 12-6. Mode-specific properties and the particle texture Feel free to use other values as you see fit if you don’t care much about the end result, which is supposed to look like hot plasma moving upward, generating a nice lighting effect on the monsters and in the clouds at the top. If the effect is done right, you’ll find that the final effect is very hard to discern as an actual particle effect. It could almost be mistaken for a much more complex shader effect. The only control you have over a particle emitter is the particle spawn parameters. And there are plenty of them. Figure 12-5 contains just the functions and parameters common to both radial and gravity particle emitters. The Start Particles and Stop Particles buttons allow you to start and stop emitting particles within SpriteBuilder. These buttons do not alter the emitter’s behavior in the game; they exist only to stop emitters from emitting particles in the editor. A particle emitter can be in one of two modes, radial or gravity. The radial mode enables you to create an effect where the particles swirl around the position of the emitter, while the gravity mode enables you to let particles fly away in any direction, curved or straight, with or without gravity. Note that this gravity is set per emitter and is completely independent from the physics world’s gravity. Changing the emitter mode will drastically alter the behavior of the particles and allow you to use one of the two sets of mode properties shown in Figure 12-6. 354 CHAPTER 12: Visual Effects and Animations The Position var property determines where a particle spawns. If this property is set to 0x0, the particle will spawn at exactly the same position as the emitter node. With x set to 250, each new particle will randomize its initial position within a range of plus/minus 250 points. If the particle emitter’s position is at 250x0, the particles are allowed to spawn between 0 to 500 along the x axis. This type of randomized plus/minus variation is used by many other particle-emitter properties, indicated either by the keyword var or by the ± symbol. The Emit rate determines how many particles will be spawned per second. The Duration determines how long (in seconds) the emitter will emit particles before it stops. A Duration of –1 means the emitter will never stop to emit particles. The Total particles value determines how many particles can be alive at most. It is absolutely crucial to keep this number as low as possible to still achieve the desired effect. The tweaking involved to create the same effect or a similar effect that uses fewer particles than the original effect is often time well spent. Life refers to the duration (in seconds) a particle remains visible. While alive, a particle counts toward the Total particles count. For this and all following properties, the value field to the right of the plus/minus sign refers to a variance that is randomly added to or subtracted from the value to the left. In this case, the default lifetime for every particle is six seconds, plus a random value in the range of –2.0 and 2.0. This means each particle will have a random lifetime between four to eight seconds. Tip Life, emit rate, and total particles influence each other. If you want an emitter that shoots out a stream of particles and then pauses, you’ll simply have to ensure that the lifetime and emit rate are such that the emitted particles reach the total particle count before some of the particles’ lives end. With an emit rate of 10 particles per second and a lifetime of 3 seconds, you’ll have 30 particles living within 3 seconds. Now if you set the total particle count to 15, the emitter will emit particles for 1.5 seconds and then stop emitting new particles for another 1.5 seconds. After 3 seconds, it will emit new particles for another 1.5 seconds and then pause another 1.5 seconds. Accordingly, if you want the particle effect to emit a continuous, uninterrupted stream of particles, the total particle count must be large enough and the lifetime and/or emit rate may need to be reduced. Start size and End size refer to the size of particles when they are spawned and when their lifetime ends, respectively. The values are linearly interpolated during the lifetime of the particle. Given that particle textures are square, the dimensions refer to both particle width and height. In this example, ignoring the variation values for a moment, the particles start out at 150x150 and after 6 seconds, the moment they disappear, their size will be 300x300. That’s pretty big for particle effects, but that size can be effective for creating large-scale effects using relatively few individual particles. Start spin and End spin determine both the rotation of the particles at the start and end of their lifetime as well as the speed of rotation. The rotation speed is determined by the difference between Start spin and End spin, which is linearly interpolated over the particle’s lifetime. If Start spin was 0 and End spin was 360, the particles would rotate one revolution over their lifetime. Naturally, this rotation will be faster if the lifetime is 1 second rather than 10 seconds. CHAPTER 12: Visual Effects and Animations 355 The Angle sets the initial direction the particles take, in degrees and in counter-clockwise direction. An angle of 0 degrees means the particles move to the right; an angle of 90 degrees means the particles move upward. Start color and End color determine the color and transparency that particles begin and end their lives with. The colors are interpolated linearly over the lifetime of a particle. If you want the particles to fade out smoothly toward the end, make sure to set the Opacity in the color wheel dialog to 0% for the End color. If you want to avoid the particle having to change its initial color over its lifetime, use black as the End color. Most commonly, particles are set up to end with the color black at 0% opacity to create a nice and smooth fade-out effect. Blend src and Blend dst are the same settings as for Sprite nodes. They affect how the particles blend with the background. Unlike most other nodes that support blending, particles default to additive blending. Basically, this means that particles brighten the already existing background colors. Most combinations of src and dst blend values just create more or less black rectangles. Besides the two basic modes—Normal and Additive—I found that Dst Color for src with Dst Alpha for dst create a very subtle blending effect that is well suited to enhancing a scene’s lighting as particles move about. The reset on visibility toggle check box, if enabled, means that the particle emitter will remove all existing particles when its visible state is changed by code. If the box is unchecked, the emitter will keep spawning but not render particles while its visible state is set to NO. Tip You can create a particle emitter, uncheck the reset on visibility toggle check box, and keep the particle emitter running for a few seconds to allow it to spawn some of the initial particles. You can then use a fade action or play a Timeline that changes the opacity of the emitter node from 0 to 1, fading it into view. This is commonly needed where the particle emitter should not be seen building up its particles but instead should start out “fully developed.” Figure 12-6 shows the mode-specific properties of the CCParticleSystem node. The Gravity mode properties are applied only when the particle emitter is in Gravity mode, and the Radial mode properties are effective only when the particle emitter is in Radial mode. Gravity affects each particle. You can use this, for example, to accelerate particles upward by setting a positive Y value or to create a spring where particles start moving upward but eventually turn around and fall back down. Gravity is specified in points, and it is simply added to the particle’s position every frame. Again, this gravity is applied only to that particular Particle System node’s particles, and it has no correlation with the gravity of the CCPhysicsNode. Speed determines the speed of motion of particles, in points per second. Speed is initially in the direction given by the Angle property, but it can change over the lifetime of a particle due to gravity, tangential acceleration, and radial acceleration. 356 CHAPTER 12: Visual Effects and Animations The property labeled Tang. acc refers to tangential acceleration, while Radial acc stands for radial acceleration. Both contribute to rotational spin for particles. By increasing the radial acceleration value alone, you’ll notice that particles will speed up and move away from the emitter’s position the longer they live. Add tangential acceleration to the mix and particles will spiral outward from the emitter’s position. With tangential acceleration, you can make emitters look like the ones in radial mode except that you can’t prevent the particles from speeding up. Thus, inevitably, they’ll be moving away from the emitter position. To create truly orbiting particles, you have to set the particle emitter to radial mode. Then you can edit the Start radius and End radius to determine the radius of the orbit of the particles, either moving outward or inward. Or set both Start radius and End radius to the same radius, only adjusting the variance, to create a ringlike effect. The Rotate property is the angle (in degrees) that the particles will move around the emitter’s position every second. You will see the particles orbiting from Start radius to End radius only if you specify a decent Rotate value and the particle lifetime is long enough. Tip You may find it easier to design certain effects by leaving all variation values at zero initially. The variation values are the property fields to the right of the plus/minus sign. Also, try to focus on editing one aspect of the particle effect at a time. And do edit particle effects in a stage that at least resembles a possible use case. If you test a particle effect against a simple color (or gradient) background, you can’t really judge what the effect looks like in the game. Particle effects can look very different depending on the background they blend with. You may want to design the particle effect in a Node CCB and then (temporarily) add various test-scene CCBs as the background node for the particle CCB. This allows you to quickly toggle through possible particle emitter backgrounds by using the visibility property. The test scenes would be specifically made to look like a typical use case in the game. Finally, the Texture property is just like the Sprite frame property of sprite nodes. SpriteBuilder comes with five built-in particle textures that you’ll find in the ccbResources folder with names starting with ccbParticle. They are sufficient for many uses, but of course you can use your own particle textures. Be sure to design the particle textures as square images. Though particles can use any texture size allowed by a device, it is strongly recommended that you use the smallest possible texture. The size of a particle texture can significantly affect the effect’s performance. In most cases, particles blend really well even when using a very low resolution texture. Figure 12-7 shows what the result of the particle effect might look like if you applied the same values or similar values as in Figure 12-5 and Figure 12-6 to the Particle System node.CHAPTER 12: Visual Effects and Animations 357 Figure 12-7. The monsters are glowing red hot thanks to the particle effect The effect is most visible on the monsters, which seem to be glowing hot. Yet you can’t make out individual particles and they blend perfectly with the background, which makes this effect worth seeing in the game. Preferably you’ll check this out on a device since the Simulator now renders this scene with maybe 15 frames per second (fps) at most. Shader Effects Cocos2D’s latest feature is shader effects, typically in the form of the Effect node, which applies a given shader effect to all of its children. Sprites can also have one or more shader effects applied to them without the need for a separate Effect node. The user interface and available shaders and their parameters are the same for both. Adding an Effect Node To try out the Effect node, open MainScene.ccb and then drag and drop an Effect node from the Node Library View onto the stage. The Effect node, much like the Color node, has an implied size of 100x100 points. Since the Effect node applies its effect to its children, this also means that it will draw only the children within its frame, determined by the Effect node’s Content size property.358 CHAPTER 12: Visual Effects and Animations Tip An Effect node without any effects can be used like a clipping node, where any content outside the Effect node’s rectangle will simply not be drawn (clipped). You could make use of that for a split-screen view by dividing the screen into two Effect nodes, appropriately positioned and sized. Then whatever you draw in one Effect node will not overlap into the area of the other Effect node. There are many uses for this. For instance, a minimap overlay could use a large image for the entire map, but it’s added to an Effect node so that it will draw only a small portion of the map in a corner of the screen. In this case, the Effect node should be a full-screen effect. Select the CCEffectNode in the Timeline, and change its position to 0x0. Then change the Content size types to %, with both values set to 100. This stretches the size of the effect to the size of the screen. Next, drag and drop the CCEffectNode in the Timeline so that it becomes the topmost node in the list. Then drag the existing background node onto the CCEffectNode so that the background node becomes a child node of the CCEffectNode. See the Timeline in Figure 12-8 for reference. Figure 12-8. Multiple effects applied to the menu background give it an entirely different look CHAPTER 12: Visual Effects and Animations 359 Now any effect added to the CCEffectNode will be applied to the entire background node. In this case, the entire MainMenuBackground.ccb will have the shader effects applied to it, including the recently added particle effect. The results will look something like in Figure 12-8. A darker, scarier, and pixellated version of the background. To create this effect, select the CCEffectNode in the Timeline and switch to the Item Properties tab. You’ll notice the CCEffectNode section at the bottom of the Item Properties tab shown in Figure 12-8. With the + button, you will open a context menu from which you can choose one effect to add to the list. At the time of this writing, there are a total of 10 effects, as seen in Figure 12-9. Figure 12-9. Adding an effect To create the effect seen in Figure 12-8, add Pixellate, Hue, Brightness, and Saturation effects. The order in which you add these effects doesn’t matter, although it may make a difference for other effect combinations. The Pixellate effect should have a value of 5, Hue a value of –64, Brightness a value of –0.2, and Saturation a value of –0.4. Feel free to alter the values as you see fit. You can also add additional effects if you want. Note In the SpriteBuilder version I used, you can add the same effect multiple times. This does not make sense for most effects. For instance, using Pixellate multiple times will make a difference only if each effect uses a different pixellation value (say: 3, 5, and 8), and the result will look barely any different from using a single Pixellate effect with a value of 8 in this example. There may be some use for applying the same effect multiple times, but no matter how hard I tried, I couldn’t find or even imagine a possible use case. This may change once more effects are added in the future. 360 CHAPTER 12: Visual Effects and Animations If you want to remove an effect, you have to select it in the list by clicking on its name or an empty area not used by any controls. Once the effect is highlighted, click the – button to remove it. Caution I found myself frequently hitting Backspace to remove a selected effect. Alas, this will in fact remove theCCEffectNode and all of its children. Fortunately, you just need to issue Edit ➤ Undo (Cmd+Z) to bring back the Effect node and its children. You should publish, build, and run the game. You may see that the effects have a noticeable, negative effect on the performance, even in the menu. The animations won’t look smooth. Of course, this varies with the device you are testing on. It wouldn’t be unheard of if an iPhone 6 runs these effects at 60 fps while an iPhone 4 struggles to render just 10 frames per second. Not to mention the iOS Simulator—it uses a software renderer, and emulating shader effects is particularly slow. Therefore, it’s rather common to see a dramatic drop in performance on the Simulator once one or more effects are visible on the scene. Available Effects The currently available effects are roughly divided into three groups:  Brightness, Contrast, Saturation, and Hue only change the color of individual pixels and can be found in almost any imaging program. All of these effects use just a single value and should be self-explanatory. But even if you don’t know what the effect does, just add it and move the slider to see what it does.  Pixellate, Blur, and Bloom alter the look of the rendered content. You’ve already seen Pixellate, which basically scales down its content, turning it into pixel art. The Blur effect smooths the content, making it look less sharp. Bloom is an effect where bright areas bleed into surrounding darker areas, making them appear to glow. You can alter its Blur Radius and the Intensity, while the Luminance Threshold determines how bright an area needs to be before the bloom effect is applied.  Refraction, Reflection, and Glass are complex effects requiring a Normal Map, which is an image where each pixel’s RGB values are considered the normal vectors. In layman’s terms, the Normal Map image alters how light is supposed to refract or reflect from the surface. All three effects also use an Environment reference, which is one or more nodes that should be seen reflected in the Effect node. (See Figure 12-10.)CHAPTER 12: Visual Effects and Animations 361 Figure 12-10. The glass effect distorts the background like a lens while slightly reflecting the Environment node on its surface The Effect node is very powerful, but the more complex effects require some understanding of graphics and shader programming to grasp the meaning and to imagine the resulting effects of the various parameters. The programming interface of CCEffectNode and CCEffect and related classes hasn’t been made available to the public while I’m writing this and is still a work in progress. Of course, you’ll eventually find these classes documented in the Cocos2D Developer Library Reference (also known as a class reference), and you can always peek into the header files CCEffect.h and CCEffectNode.h. Shader-Effects Best Practices As with any effect, creating good shader effects is mostly a matter of using images that work well with the effect. I had it easy with a well-designed menu screen that works well with both particle and shader effects. Imagine if you had only flat-colored dummy graphics—it wouldn’t look nearly as good. Effects in themselves can’t work magic. You have to provide good input for shaders and particle effects to generate good output. While it’s tempting to start designing effects early, the development of effects should really be deferred until the project has all of the features and most of the artwork. By that time, you have established that the game runs well and there’s spare performance to be taken up by effects.

Advise: Why You Wasting Money in Costly SEO Tools, Use World's Best Free SEO Tool Ubersuggest.