我们的英雄现在可以发射子弹了,但仅仅只是装饰而已,如何才能杀掉怪物呢?在这一章,我们将介绍碰撞检测来实现这一效果。
首先,跟踪怪物和子弹是必需的。
在游戏中,我们为这两种精灵加以不同的tag来区分它们。当tag=1时,表示这是怪物,而tag=2时,则表示这为子弹。由于在CCNode里面有m_nTag这个成员变量,并且有setTag和getTag方法,因此CCSprite就继承了这些方法,我们可以利用之。
在HelloWorldScene.h中,把以下两个成员变量加入到HelloWorld下,这两个成员变量用于缓存现有的怪物和子弹。
1// cpp with cocos2d-x
2protected:
3 cocos2d::CCMutableArray *_targets;
4 cocos2d::CCMutableArray *_projectiles;
1// objc with cocos2d-iphone
2 NSMutableArray *_targets;
3 NSMutableArray *_projectiles;
在cocos2d-x里,CCMutableArray相当于iOS SDK中的NSMutableArray,该数组里的成员可以是NSObject或者他们的子类。但不同的是,你必须告诉它里面要放的是哪种具体的类型。
之后构造函数中初始化这两个变量,在init()中new 它们,并在析构函数中release 它们。
1// cpp with cocos2d-x
2
3// in init()
4// Initialize arrays
5_targets = new CCMutableArray;
6_projectiles = new CCMutableArray;
7
8HelloWorld::~HelloWorld()
9{
10 if (_targets)
11 {
12 _targets->release();
13 _targets = NULL;
14 }
15
16 if (_projectiles)
17 {
18 _projectiles->release();
19 _projectiles = NULL;
20 }
21
22 // cpp don't need to call super dealloc
23 // virtual destructor will do this
24}
25
26HelloWorld::HelloWorld()
27:_targets(NULL)
28,_projectiles(NULL)
29{
30}
1// objc with cocos2d-iphone
2// in init()
3// Initialize arrays
4_targets = [[NSMutableArray alloc] init];
5_projectiles = [[NSMutableArray alloc] init];
6
7- (void) dealloc
8{
9 [_targets release];
10 _targets = nil;
11
12 [_projectiles release];
13 _projectiles = nil;
14
15 // don't forget to call "super dealloc"
16 [super dealloc];
17}
现在可以修改addTarget(),把新目标添加到目标数组中,并设置其tag为1。
1// cpp with cocos2d-x
2// Add to targets array
3target->setTag(1);
4_targets->addObject(target);
1// objc with cocos2d-iphone
2// Add to targets array
3target.tag = 1;
4[_targets addObject:target];
修改ccTouchesEnded(),把新子弹加入到子弹数组中,并设置其tag为2。
1// cpp with cocos2d-x
2// Add to projectiles array
3projectile->setTag(2);
4_projectiles->addObject(projectile);
1// objc with cocos2d-iphone
2// Add to projectiles array
3projectile.tag = 2;
4[_projectiles addObject: projectile];
之后,按下面修改spriteMoveFinished()。这里根据标记的不同,在对应的数组中移除精灵
1// cpp with cocos2d-x
2void HelloWorld::spriteMoveFinished(CCNode* sender)
3{
4 CCSprite *sprite = (CCSprite *)sender;
5 this->removeChild(sprite,true);
6
7 if (sprite->getTag() == 1) // target
8 {
9 _targets->removeObject(sprite);
10 }
11 else if (sprite->getTag() == 2) // projectile
12 {
13 _projectiles->removeObject(sprite);
14 }
15}
1// objc with cocos2d-iphone
2-(void)spriteMoveFinished:(id)sender
3{
4 CCSprite *sprite = (CCSprite *)sender;
5 [self removeChild:sprite cleanup:YES];
6
7 if (sprite.tag == 1) // target
8 {
9 [_targets removeObject:sprite];
10 }
11 else if (sprite.tag == 2) // projectile
12 {
13 [_projectiles removeObject:sprite];
14 }
15}
下面的update()函数用于检测每帧的碰撞,并从游戏中删除碰撞中的子弹和怪物。
请在HelloWorldScene.h中声明,在HelloWorldScene.cpp中定义。
1// cpp with cocos2d-x
2void HelloWorld::update(ccTime dt)
3{
4 CCMutableArray *projectilesToDelete =
5 new CCMutableArray;
6 CCMutableArray::CCMutableArrayIterator it,jt;
7
8 for (it = _projectiles->begin(); it != _projectiles->end(); it++)
9 {
10 CCSprite *projectile =*it;
11 CCRect projectileRect = CCRectMake(
12 projectile->getPosition().x
13 - (projectile->getContentSize().width/2),
14 projectile->getPosition().y
15 - (projectile->getContentSize().height/2),
16 projectile->getContentSize().width,
17 projectile->getContentSize().height);
18
19 CCMutableArray*targetsToDelete
20 = new CCMutableArray;
21
22 for (jt = _targets->begin(); jt != _targets->end(); jt++)
23 {
24 CCSprite *target =*jt;
25 CCRect targetRect = CCRectMake(
26 target->getPosition().x - (target->getContentSize().width/2),
27 target->getPosition().y - (target->getContentSize().height/2),
28 target->getContentSize().width,
29 target->getContentSize().height);
30
31 if (CCRect::CCRectIntersectsRect(projectileRect,targetRect))
32 {
33 targetsToDelete->addObject(target);
34 }
35 }
36
37 for (jt = targetsToDelete->begin();
38 jt != targetsToDelete->end();
39 jt++)
40 {
41 CCSprite *target =*jt;
42 _targets->removeObject(target);
43 this->removeChild(target,true);
44 }
45
46 if (targetsToDelete->count() >0)
47 {
48 projectilesToDelete->addObject(projectile);
49 }
50 targetsToDelete->release();
51 }
52
53 for (it = projectilesToDelete->begin();
54 it != projectilesToDelete->end();
55 it++)
56 {
57 CCSprite* projectile =*it;
58 _projectiles->removeObject(projectile);
59 this->removeChild(projectile,true);
60 }
61 projectilesToDelete->release();
62}
1// objc with cocos2d-iphone
2- (void)update:(ccTime)dt
3{
4 NSMutableArray *projectilesToDelete
5 = [[NSMutableArray alloc] init];
6
7 for (CCSprite *projectile in _projectiles)
8 {
9
10 CGRect projectileRect = CGRectMake(
11 projectile.position.x - (projectile.contentSize.width/2),
12 projectile.position.y - (projectile.contentSize.height/2),
13 projectile.contentSize.width,
14 projectile.contentSize.height);
15
16 NSMutableArray *targetsToDelete
17 = [[NSMutableArray alloc] init];
18
19 for (CCSprite *target in _targets)
20 {
21
22 CGRect targetRect = CGRectMake(
23 target.position.x - (target.contentSize.width/2),
24 target.position.y - (target.contentSize.height/2),
25 target.contentSize.width,
26 target.contentSize.height);
27
28 if (CGRectIntersectsRect(projectileRect,targetRect))
29 {
30 [targetsToDelete addObject:target];
31 }
32 }
33
34 for (CCSprite *target in targetsToDelete)
35 {
36
37 [_targets removeObject:target];
38 [self removeChild:target cleanup:YES];
39 }
40
41 if (targetsToDelete.count >0)
42 {
43 [projectilesToDelete addObject:projectile];
44 }
45 [targetsToDelete release];
46 }
47
48 for (CCSprite *projectile in projectilesToDelete)
49 {
50
51 [_projectiles removeObject:projectile];
52 [self removeChild:projectile cleanup:YES];
53 }
54 [projectilesToDelete release];
55}
好了,最后一件事,我们要把update()加入到schedule里让它每帧都能被调用。
1// cpp with cocos2d-x
2this->schedule( schedule_selector(HelloWorld::update) );
1// objc with cocos2d-iphone
2[self schedule:@selector(update:)];
编译并运行项目,尽情地发射子弹吧,这时:啊哈,怪物都一个接着一个地被干掉了。