Cocos2d-x如何检测碰撞

我们的英雄现在可以发射子弹了,但仅仅只是装饰而已,如何才能杀掉怪物呢?

在这一章,我们将介绍碰撞检测来实现这一效果。

首先,跟踪怪物和子弹是必需的。

在游戏中,我们为这两种精灵加以不同的tag来区分它们。当tag=1时,表示这是怪物,而tag=2时,则表示这为子弹。由于在CCNode里面有m_nTag这个成员变量,并且有setTaggetTag方法,因此CCSprite就继承了这些方法,我们可以利用之。

HelloWorldScene.h中,把以下两个成员变量加入到HelloWorld下,这两个成员变量用于缓存现有的怪物和子弹。

1// cpp with cocos2d-x
2protected:
3 cocos2d::CCMutableArray<cocos2d::CCSprite*> *_targets;
4 cocos2d::CCMutableArray<cocos2d::CCSprite*> *_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<CCSprite*>;
6_projectiles = new CCMutableArray<CCSprite*>; 
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(),把新目标添加到目标数组中,并设置其tag1
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(),把新子弹加入到子弹数组中,并设置其tag2
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<CCSprite*> *projectilesToDelete = 
5 new CCMutableArray<CCSprite*>;
6 CCMutableArray<CCSprite*>::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<CCSprite*>*targetsToDelete 
20 = new CCMutableArray<CCSprite*>;
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:)];


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值