Chapter 3 - How to Move a sprite

Version 11 (RongHong Huang, 2011-04-13 23:29)

1 1 RongHong Huang
h1. Chapter 3 - How to Move a sprite
2 2 RongHong Huang
3 7 RongHong Huang
We have added a hero to the scene in the last chapter [[Chapter 2 - How to Add a sprite]]. But the hero is so lonely that we should add some enemies to let him beat down.
4 8 RongHong Huang
The function void addTarget() will complete the work, the enemies will be added into the scene from right to left at random speed.
5 2 RongHong Huang
6 2 RongHong Huang
Declare void addTarget() in HelloWorldScene.h and add the following code to HelloWorldScene.cpp,
7 2 RongHong Huang
8 2 RongHong Huang
| <pre><code class="cplusplus">
9 2 RongHong Huang
// cpp with cocos2d-x
10 2 RongHong Huang
void HelloWorld::addTarget()
11 2 RongHong Huang
{
12 2 RongHong Huang
	CCSprite *target = CCSprite::spriteWithFile("Target.png", 
13 2 RongHong Huang
		CCRectMake(0,0,27,40) );
14 2 RongHong Huang
15 2 RongHong Huang
	// Determine where to spawn the target along the Y axis
16 2 RongHong Huang
	CCSize winSize = CCDirector::sharedDirector()->getWinSize();
17 2 RongHong Huang
	int minY = target->getContentSize().height/2;
18 9 RongHong Huang
	int maxY = winSize.height
19 9 RongHong Huang
                          -  target->getContentSize().height/2;
20 2 RongHong Huang
	int rangeY = maxY - minY;
21 2 RongHong Huang
	// srand( TimGetTicks() );
22 2 RongHong Huang
	int actualY = ( rand() % rangeY ) + minY;
23 2 RongHong Huang
24 2 RongHong Huang
	// Create the target slightly off-screen along the right edge,
25 2 RongHong Huang
	// and along a random position along the Y axis as calculated
26 2 RongHong Huang
	target->setPosition( 
27 2 RongHong Huang
		ccp(winSize.width + (target->getContentSize().width/2), 
28 2 RongHong Huang
		actualY) );
29 2 RongHong Huang
	this->addChild(target);
30 2 RongHong Huang
31 2 RongHong Huang
	// Determine speed of the target
32 2 RongHong Huang
	int minDuration = (int)2.0;
33 2 RongHong Huang
	int maxDuration = (int)4.0;
34 1 RongHong Huang
	int rangeDuration = maxDuration - minDuration;
35 1 RongHong Huang
	// srand( TimGetTicks() );
36 9 RongHong Huang
	int actualDuration = ( rand() % rangeDuration )
37 9 RongHong Huang
                                        + minDuration;
38 2 RongHong Huang
39 2 RongHong Huang
	// Create the actions
40 2 RongHong Huang
	CCFiniteTimeAction* actionMove = 
41 2 RongHong Huang
		CCMoveTo::actionWithDuration( (ccTime)actualDuration, 
42 2 RongHong Huang
		ccp(0 - target->getContentSize().width/2, actualY) );
43 2 RongHong Huang
	CCFiniteTimeAction* actionMoveDone = 
44 2 RongHong Huang
		CCCallFuncN::actionWithTarget( this, 
45 2 RongHong Huang
		callfuncN_selector(HelloWorld::spriteMoveFinished));
46 2 RongHong Huang
	target->runAction( CCSequence::actions(actionMove, 
47 2 RongHong Huang
		actionMoveDone, NULL) );
48 2 RongHong Huang
}
49 2 RongHong Huang
</code></pre> | <pre><code class="cplusplus">
50 2 RongHong Huang
// objc with cocos2d-iphone
51 2 RongHong Huang
-(void)addTarget 
52 2 RongHong Huang
{
53 2 RongHong Huang
  CCSprite *target = [CCSprite spriteWithFile:@"Target.png"
54 2 RongHong Huang
                                rect:CGRectMake(0, 0, 27, 40)];
55 2 RongHong Huang
56 2 RongHong Huang
  // Determine where to spawn the target along the Y axis
57 2 RongHong Huang
  CGSize winSize = [[CCDirector sharedDirector] winSize];
58 2 RongHong Huang
  int minY = target.contentSize.height/2;
59 2 RongHong Huang
  int maxY = winSize.height - target.contentSize.height/2;
60 2 RongHong Huang
  int rangeY = maxY - minY;
61 2 RongHong Huang
62 2 RongHong Huang
  int actualY = (arc4random() % rangeY) + minY;
63 2 RongHong Huang
64 2 RongHong Huang
  // Create the target slightly off-screen along the right edge,
65 2 RongHong Huang
  // and along a random position along the Y axis as calculated
66 2 RongHong Huang
  target.position = 
67 2 RongHong Huang
    ccp(winSize.width + (target.contentSize.width/2), 
68 2 RongHong Huang
    actualY);
69 2 RongHong Huang
  [self addChild:target];
70 2 RongHong Huang
71 2 RongHong Huang
  // Determine speed of the target
72 2 RongHong Huang
  int minDuration = 2.0;
73 1 RongHong Huang
  int maxDuration = 4.0;
74 1 RongHong Huang
  int rangeDuration = maxDuration - minDuration;
75 2 RongHong Huang
76 9 RongHong Huang
  int actualDuration = (arc4random() % rangeDuration)
77 9 RongHong Huang
                                  + minDuration;
78 2 RongHong Huang
79 2 RongHong Huang
  // Create the actions
80 2 RongHong Huang
  id actionMove = 
81 2 RongHong Huang
    [CCMoveTo actionWithDuration:actualDuration
82 2 RongHong Huang
          position:ccp(-target.contentSize.width/2, actualY)];
83 2 RongHong Huang
  id actionMoveDone = 
84 2 RongHong Huang
    [CCCallFuncN actionWithTarget:self
85 2 RongHong Huang
                selector:@selector(spriteMoveFinished:)];
86 2 RongHong Huang
  [target runAction:[CCSequence actions:actionMove, 
87 2 RongHong Huang
                    actionMoveDone, nil]]; 
88 2 RongHong Huang
} 
89 2 RongHong Huang
</code></pre> |
90 2 RongHong Huang
91 2 RongHong Huang
Here, callfuncN_selector(HelloWorld::spriteMoveFinished) backcalls the function spriteMoveFinished(), we need to declare it in the HelloWorldScene.h and define it as follows,
92 2 RongHong Huang
93 11 RongHong Huang
|<pre><code class="cplusplus">
94 2 RongHong Huang
// cpp with cocos2d-x
95 2 RongHong Huang
void HelloWorld::spriteMoveFinished(CCNode* sender)
96 2 RongHong Huang
{
97 2 RongHong Huang
  CCSprite *sprite = (CCSprite *)sender;
98 2 RongHong Huang
  this->removeChild(sprite, true);
99 2 RongHong Huang
}
100 11 RongHong Huang
</code></pre> |<pre><code class="cplusplus">
101 2 RongHong Huang
// objc with cocos2d-iphone
102 2 RongHong Huang
-(void)spriteMoveFinished:(id)sender 
103 2 RongHong Huang
{
104 2 RongHong Huang
  CCSprite *sprite = (CCSprite *)sender;
105 2 RongHong Huang
  [self removeChild:sprite cleanup:YES]; 
106 2 RongHong Huang
} 
107 2 RongHong Huang
</code></pre> |
108 2 RongHong Huang
109 6 RongHong Huang
TIPs:
110 6 RongHong Huang
1. About rand function. srand and rand are c std function. For each platform, you could get the mili-second system time as sand to get a random number. On WoPhone, the function is TimGetTickes(), and on IPhone, you could get the random number by arc4random() directly 
111 6 RongHong Huang
2. The YES and NO in objc are true and false in cpp
112 6 RongHong Huang
3. The callback function is selector:@selector(spriteMoveFinished) in objc, but it is a little complicated to realize in cpp, you could refer to the declarations in cocos2dx\include\selector_protocol.h. There are five different callback types:
113 6 RongHong Huang
114 6 RongHong Huang
    * schedule_selector
115 6 RongHong Huang
    * callfunc_selector
116 6 RongHong Huang
    * callfuncN_selector
117 6 RongHong Huang
    * callfuncND_selector
118 6 RongHong Huang
    * menu_selector
119 6 RongHong Huang
120 6 RongHong Huang
How to use them is according to the callback function definition.  For example, when use the function CCTimer::initWithTarget whose second parameter is a type of SEL_SCHEDULE, we could find its macro-definition schedule_selector(_SELECTOR) in selector_protocol.h, then we declare a callback function void MyClass::MyCallbackFuncName(ccTime), and transform it as the second parameter of CCTimer::initWithTarget.
121 6 RongHong Huang
122 2 RongHong Huang
Then, we should put the enemies into the scene at intervals, add the codes before init() function returns.
123 2 RongHong Huang
 
124 11 RongHong Huang
|<pre><code class="cplusplus">
125 2 RongHong Huang
// cpp with cocos2d-x
126 2 RongHong Huang
// Call game logic about every second
127 2 RongHong Huang
this->schedule( schedule_selector(HelloWorld::gameLogic), 1.0 );
128 11 RongHong Huang
</code></pre> |<pre><code class="cplusplus">
129 2 RongHong Huang
// objc with cocos2d-iphone
130 2 RongHong Huang
// Call game logic about every second
131 2 RongHong Huang
[self schedule:@selector(gameLogic:) interval:1.0];
132 2 RongHong Huang
</code></pre> |
133 2 RongHong Huang
134 2 RongHong Huang
and realize gameLogic() in HelloWorldScene.cpp. Notice that gameLogic() should be declared as public, otherwise it won't be backcalled.
135 2 RongHong Huang
136 11 RongHong Huang
|<pre><code class="cplusplus">
137 2 RongHong Huang
// cpp with cocos2d-x
138 2 RongHong Huang
void HelloWorld::gameLogic(ccTime dt)
139 2 RongHong Huang
{
140 2 RongHong Huang
    this->addTarget();
141 2 RongHong Huang
}
142 11 RongHong Huang
</code></pre>|<pre><code class="cplusplus">
143 2 RongHong Huang
// objc with cocos2d-iphone
144 2 RongHong Huang
-(void)gameLogic:(ccTime)dt
145 2 RongHong Huang
{
146 2 RongHong Huang
    [self addTarget];
147 2 RongHong Huang
}
148 10 RongHong Huang
</code></pre>|
149 2 RongHong Huang
150 2 RongHong Huang
Ok, everything is done, build and run, and enjoy your fruit.
151 2 RongHong Huang
152 5 RongHong Huang
IPhone !IOSSpriteAndEnemy.png!
153 5 RongHong Huang
Android !androidSpriteAndEnemy.png!
154 4 RongHong Huang
WoPhone !WoPhoneSpriteAndEmemy.png!
155 3 RongHong Huang
Win32   !Win32SpriteAndEmemies.png!