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! |