Three ways to make unit streamers or "ghosts"

If you've ever played games such as Fruit Ninja, Blek, Jetpack Joyride, or Tiny Wings, you've surely seen this effect. There's a position on the screen that generates something similar to stars, a slashing effect, smoke clouds, or a line following the finger.

Sample project – ghosts

Go to the code repository and open the Ghosts project under the Sample Projects folder. If you run it, you will see just three labels as buttons that lead to mostly blank screens that don't really do anything. That's where you come in.

Here, you're going to learn how to make the effects that you just read. There are three general ways to go about making something like this. Let's go over each method, starting with the easiest and ending with the hardest.

Method 1 – particle systems

Particle systems are basically sprites that are created en masse, such as a firework effect, a gushing water fountain, or a flickering candle. The difference between using a particle system and creating the sprites yourself is that particle systems generally allow only moving, scaling, rotation, and color changes. But for simple effects such as a smoke cloud, a particle system works just fine.

Tip

If you wish to create your own particles for this sample project or any project of your own, as mentioned in Chapter 1, Refreshing Your Cocos2d Knowledge, Particle Designer is a great tool for this purpose. You can manually create them in the code, but it's a lot easier and more efficient to create them visually using an editor such as Particle Designer.

With the Ghosts project opened in Xcode, open the ParticleExampleScene.h file and add a CCParticleSystem variable to the list:

CCParticleSystem *smokeParticle;

Then open ParticleExampleScene.m and add the particle system to the screen in the init method:

smokeParticle = [CCParticleSystem 
  particleWithFile:@"SmokeParticle.plist"];
[self addChild:smokeParticle];

The particle system used in the preceding code was created using Particle Designer, as mentioned at the beginning of this book. It uses a simple cloud-shaped image and has certain properties set to create the effect of fading out.

Finally, in the updateParticleSource method, set the particle system's source position so that as you drag your finger around the screen, the smoke starts in a different position:

smokeParticle.sourcePosition = startPosition;

If you run the project at this point, you'll see that the smoke is constantly being generated, even after you take your finger off the screen. Although this doesn't mean much for this sample project, imagine you want a particle being displayed only if a user is in midair, or while a combo move is being performed. That being said, we need a way to stop and start the particle streaming on demand (in this case, when the user places or removes their finger).

Although Cocos2d does not have a method to begin a particle system, it's very easy to add such a method. So, look up the project for stopSystem. In the CCParticleSystemBase.h file (which should be the first result in the search), add the following code above the stopSystem declaration:

-(void)startSystem;

Then, in the CCParticleSystemBase.m file (the next result in the search), add this method so that you can start the particle system on demand:

-(void)startSystem
{
  _active = YES;
  _elapsed = _duration;
  _emitCounter = 0;
}

Now go back to ParticleExampleScene.m, and in the init method, right after you've added the smoke particle to the scene, call the stopSystem method so that it's not on the screen when the scene first starts:

[smokeParticle stopSystem];

Add the stopSystem method to the touchEnded method so that the particle system stops spawning new particles and lets the old particles die out:

-(void)touchEnded:(CCTouch *)touch withEvent:(CCTouchEvent *)event
{
	isStreaming = NO;
	[smokeParticle stopSystem];
}

Finally, add a method call to the newly created startSystem method in the touchBegan method so that the particles begin streaming when a finger is on the screen:

[smokeParticle startSystem];

Running the project at this point will allow you to see the starting and stopping of a particle system that has already been created.

Tip

You may be wondering how to adapt this for your own project. Once you have the particle system added to the screen, it's basically just a matter of updating the particle system's source position with the "start position." For example, you could have a rocket flying across the screen, and the rocket's position could be the start position.

Now let's move on to a very similar-looking style that takes a little more code, but allows greater manipulation with the overall look of the game.

Method 2 – sprites or nodes

Although a particle system requires less code to get a similar effect, there are more things you can do when you create the sprite yourself and handle everything that happens to it. For example, you can make the sprite change color several times, set up crazy movement patterns, change images altogether, or apply other CCAction actions that the particle system can't do.

Tip

One example of something that a particle system can't do is shake mechanics. A simple way you can do this is by queuing up a sequence of CCMove actions to go in the various directions you want (generally, no more than a few points in any direction), and using a variable for the duration so that you can increase or decrease the speed based on the situation.

With the Ghosts project opened in Xcode, open the SpriteExampleScene.m file and add the following block of code to the spawnStreamer method:

CCSprite *heart = [CCSprite spriteWithImageNamed:@"heart.png"];
heart.color = [CCColor redColor];
heart.position = startPosition;
[self addChild:heart];

CCActionScaleTo *shrink = [CCActionScaleTo actionWithDuration:0.5 scale:0];
CCActionCallBlock *block = [CCActionCallBlock actionWithBlock:^{
  [self removeChild:heart];
}];

[heart runAction:[CCActionSequence actions:shrink, block, nil]];

This code will spawn a red heart (the image is white, but we've colored it red), shrink it down to a scale of 0 in half a second, and then remove it from the scene so that it doesn't create lag after running for a while.

If you run the project and drag you finger around the screen, you'll see some beautiful hearts being created in a fluid manner. And that's it! The only reason it was mentioned that you'd probably have to use more code is that, the more you want to do with your streamer (ghost, phantom, or whatever), the more code it will take to get the effect you want.

So say, for example, you want to make the sprites move along a Bézier curve, spin 360 degrees, and finally shrink down and disappear, while at the same time changing to a green heart. The code will look something like this:

CCSprite *heart = [CCSprite spriteWithImageNamed:@"heart.png"];
heart.color = [CCColor redColor];
heart.position = startPosition;
[self addChild:heart];
  
CCActionTintTo *tint = [CCActionTintTo actionWithDuration:0.5 color:[CCColor greenColor]];
  
ccBézierConfig bezConfig;
bezConfig.controlPoint_1 = ccp(0,100);
bezConfig.controlPoint_2 = ccp(100,100);
bezConfig.endPosition = ccp(100,0);
CCActionBézierTo *move = [CCActionBézierBy actionWithDuration:0.5 Bézier:bezConfig];
  
CCActionRotateBy *rotate = [CCActionRotateBy actionWithDuration:0.5 angle:360];
  
CCActionScaleTo *shrink = [CCActionScaleTo actionWithDuration:0.5 scale:0];
CCActionCallBlock *remove = [CCActionCallBlock actionWithBlock:^{
  [self removeChild:heart];
}];
  
[heart runAction:tint];
[heart runAction:[CCActionSequence actions:move, rotate, shrink, remove, nil]];

Tip

If you wish to implement something like this within your own project, the key requirement is the isStreaming Boolean and the check within the update method. Everything else is straightforward and very similar to the particle method of changing the startPosition.

Finally, let's tackle the most unique method of all—the constant line that both Fruit Ninja and Blek have implemented.

Method 3 – constant line

Constant line is the most advanced version of streamers. It's not really a particle, and therefore, it can't be made as a sprite creation either. Instead, we're going to use CCMotionStreak to create a slashing effect. CCMotionStreak is fairy simple to implement, as it only needs a position, an image, and a color.

With the Ghosts project opened in Xcode, open ConstantLineExampleScene.h and add a CCMotionStreak object to the list:

{
  CGSize winSize;
  CGPoint startPosition;
  
  CCMotionStreak *streak;
}

Then, in ConstantLineExampleScene.m, create the streak and add it to the scene in the init method:

streak = [CCMotionStreak streakWithFade:0.35 minSeg:1 width:15 color:[CCColor yellowColor] textureFilename:@"blade.png"];
[self addChild:streak];

Here we're using the yellow color and the file named blade.png. You can use whichever image you want, but since we want a blade slashing effect, we're going to use the image that is shaped like a diamond to give the beginning and end a pointed edge.

Next, in the touchBegan method, set the CCMotionStreak object's position, and reset it so that when the users touch down again, it doesn't connect the two lines (unless that's what you want; in that case, you should not reset it):

streak.position = startPosition;
[streak reset];

Finally, in the touchMoved method, set the position so that every time the finger is dragged, the motion streak glides to the next position:

streak.position = startPosition;

And that's it! If you run the project, go to the line example, and drag a finger around, you'll see the nice slashing effect. If you want to make the line bigger (or smaller), simply adjust the width in the initialization of CCMotionStreak. The same applies to the color, image, or even duration. However, it's not recommended to set the duration too high, as the motion streak might be a bit delayed.

Tip

The key point to remember if you want to implement this style of streamer/ghost in your project is that CCMotionStreak relies on a position of something. So, if you want a streak on a spaceship, you have to update the motion streak's position in the update function, like this:

-(void)update:(CCTime)delta
{
  streak.position = ship.position;
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.12.156