01219245/cocos2d/Actions
- This is part of 01219245.
In this short tutorial, we shall not create a new game, but we will learn a few useful techniques for making our game more engaging.
เนื้อหา
Actions
Using a combination of states and update method is very useful when we want to (micro) manage our objects. However, sometimes, we just want to tell object to do something like jumping or falling and do not want to keep track of these action.
For example, when our flappy dot dies, we want it to fall down to the ground. If we use states, we might want to add code to move the sprite downwards slighly in update method and to keep track that the dot reaches the ground. It will be easier if you can just tell the dot to fall down, and then stop worrying about it as the object shall move accordingly by itself (or by some magics). In Cocos2d-html5, there is a mechanism for performing that kind of work, called actions (See reference here, type action in to the search box). (Read an overview for C++ version in Cocos2d-x here.)
We shall learn how to use actions by examples.
Falling dot
We shall let the player falls. In this case, we use cc.MoveTo (ref) action to tell the object to move to a specific location. After we create the action, we can tell the object to perform an action simply by calling method runAction.
Add method fall to class Player:
fall: function() {
var pos = this.getPosition();
var fallAction = cc.MoveTo.create( 0.5, new cc.Point( pos.x, 0 ) );
this.runAction( fallAction );
}
This action tell the Player to move to the ground (where y co-ordinate = 0) in 0.5 seconds. You can call this method fall at an appropriate location in GameLayer (e.g., after the Player hits the pillars).
Flapping dot: animations and combining actions
We shall make the dot animate. The associated action is cc.Animate (ref), which an be created with cc.Animation (ref). (Note the action is cc.Animate, the animation data is created in cc.Animation object.)
Create another 40x40 image for the player animation. Save it as images/dot2.png. The image below shows example images for dot.png and the new dot2.png.
To make an animation we shall repeatedly shows the first image and switch to the second image. To do so we create an cc.Animation and add these two images with appropriate time between the animation frame. The code is shown below. You can add this code to method Player.ctor.
var animation = new cc.Animation.create();
animation.addSpriteFrameWithFile( 'images/dot.png' );
animation.addSpriteFrameWithFile( 'images/dot2.png' );
animation.setDelayPerUnit( 0.2 );
var movingAction = cc.Animate.create( animation );
this.runAction( movingAction );
Try to run the game. The player will move once.
To make the player moves many times, we can call method setLoops in the cc.Animation object. However, if we want the player to move forever, we can create a special action.
Cocos2d-html5 provides a set of actions that combines other actions. These are, for example, cc.Sequence, cc.Repeat, and cc.RepeatForever. In this case, we will use cc.RepeatForever.
To create an action for our animation that runs forever, we use the previous <cc>cc.Animate action to create cc.RepeatForever action like this:
var movingAction = cc.RepeatForever.create( cc.Animate.create( animation ) );
Try and see our player moves.
Moving after the game starts
Our player starts moving before we even start the game. This might not be good. Let's make it start and stop at appropriate times.
Let's start by cleaning our code a bit. The code for creating an animate action in the constructor is long and is not in the same abstraction level as the other code; let's extract it and create a new method:
createAnimationAction: function() {
var animation = new cc.Animation.create();
animation.addSpriteFrameWithFile( 'images/dot.png' );
animation.addSpriteFrameWithFile( 'images/dot2.png' );
console.log( animation.getDelayPerUnit() );
animation.setDelayPerUnit( 0.2 );
return cc.RepeatForever.create( cc.Animate.create( animation ) );
}
We want to start and stop the animation, so let's save the action as the player's property. Put this Player.ctor in Player.ctor (replace the part where we create movingAction with a method call):
this.movingAction = this.createAnimationAction();
We also remove the call the this.runAction.
We will start the animation when the player starts, so let's add this to Player.start method:
this.runAction( this.movingAction );
Also, we will stop when the player stops. We can add this line to Player.stop method:
this.stopAction( this.movingAction );
Spritesheets
It is hard to maintain a lot of files in the resource. A typical approach for animation sprite frames is to pack them into a single image file. We will learn how to do this in this section.
Two concepts: Sprite and SpriteFrame
There are two related concepts (two classes) that we have to understand, or at least be able to distinguish them: Sprite and SpriteFrame.
The objects that Cocos2d-html5 draws on the screen must be cc.Node objects. Class cc.Sprite inherits from cc.Node so that its objects can be drawn on the screen. A cc.Sprite can be moved, scaled, rotated and transformed. What is actually drawn on the screen, in case of a cc.Sprite, is a cc.SpriteFrame. A cc.SpriteFrame is a rectangular section of an image (called texture). (Note that it can also be the whole image.)
Let's review what we have done previously.
When we create a cc.Sprite from an image file, we call:
this.initWithFile("images/ship.png");
This will implicitely create a cc.SpriteFrame for this sprite.
When we create an cc.Animation, recall that we add a cc.SpriteFrame with statements like:
animation.addSpriteFrameWithFile( 'images/dot.png' );
We then apply this animation (which contains many cc.SpriteFrames) to animate a single cc.Sprite.
In summary, the object that is drawn on the screen is a cc.Sprite, and the images are cc.SpriteFrames.
Sound effects
Follow these steps:
- Create the media files. You can use .wav, .mp3, or .ogg files. Put the files in a separate directory, e.g., effects.
- Add the effect files to resource.js preload the resource. E.g., (don't forget the commas)
//effect {src: 'effects/fall.mp3' }
- Get the AudioEngine and call it. You can call playEffect (ref)
cc.AudioEngine.getInstance().playEffect( 'effects/fall.mp3' );
cr call playMusic (ref):
cc.AudioEngine.getInstance().playMusic( 'someofyourmusicfile' );
You can even loop the effects or musics by setting loop parameter to true; e.g.,
cc.AudioEngine.getInstance().playMusic( 'someofyourmusicfile', true );