(译)如何使用cocos2d制作一个塔防游戏:第四部分(完)

原文链接地址:http://www.iphonegametutorials.com/2011/04/21/cocos2d-game-tutorial-how-to-build-a-tower-defense-game-for-the-iphone-part-4-starting-the-tower-attack/
教程截图:
(译)如何使用cocos2d制作一个塔防游戏:第四部分(完)
这部分教程,我们将实现我们刚开始所讨论的完整的塔防游戏。这是本系列教程的第四部分,也是最后一部分,在继续阅读之前,建议你先查看前3个教程,可以从这里开始。
今天,我们将学习到新的东西--“让炮塔开火!”。这是塔防游戏中最重要的组成部分,也是本程序中最有意思的部分。我当然不可能在这个教程中覆盖塔防游戏中所有好玩的东西,但是,我保证我们会在不将的将来创建各式各样的tower。我想,在学习完这个系列教程之后,你自己也可以制作出非常好玩的塔防游戏。我会尽量让代码的robust性更好的!
这里有本教程的完整源代码。
首先,我们需要做的就是创建实际的子弹(projectile)--projectile类目前有一点点简单,它里面什么也没有,但是,不代表它将来也没有内容。
Projectile.h
#import "cocos2d.h" @interface Projectile : CCSprite { } + (id)projectile; @end
Projectile.m
#import "Projectile.h" @implementation Projectile + (id)projectile { Projectile *projectile = nil; if ((projectile = [[[super alloc] initWithFile:@"Projectile.png"] autorelease])) { } return projectile; } - (void) dealloc { [super dealloc]; } @end
我们现在添加新的方法到update函数中,此函数在TowerScene中。那里面处理当前的子弹和creep的碰撞检测。这个基本的逻辑很简单:
1.遍历所有的projectiles
2.对于每一个projectiles,遍历所有的targets
3.看projectile的边界是否和target的边界有交叉
4.如果交叉了,减少creep的生命值,同时把projectile加到一个即将被删除的数组 projectilesToDelete里面去
5.如果creep的生命值==0,那么就把它加到targetToDelete数组里面。
具体代码如下:(其实这段代码和Ray的教程《如何使用cocos2d制作一个简单的iphone游戏》里面的忍者发射飞盘一样的)
- (void)update:(ccTime)dt { DataModel *m = [DataModel getModel]; NSMutableArray *projectilesToDelete = [[NSMutableArray alloc] init]; for (Projectile *projectile in m._projectiles) { CGRect projectileRect = CGRectMake(projectile.position.x - (projectile.contentSize.width/2), projectile.position.y - (projectile.contentSize.height/2), projectile.contentSize.width, projectile.contentSize.height); NSMutableArray *targetsToDelete = [[NSMutableArray alloc] init]; for (CCSprite *target in m._targets) { CGRect targetRect = CGRectMake(target.position.x - (target.contentSize.width/2), target.position.y - (target.contentSize.height/2), target.contentSize.width, target.contentSize.height); if (CGRectIntersectsRect(projectileRect, targetRect)) { [projectilesToDelete addObject:projectile]; Creep *creep = (Creep *)target; creep.hp--; if (creep.hp <= 0) { [targetsToDelete addObject:target]; } break; } } for (CCSprite *target in targetsToDelete) { [m._targets removeObject:target]; [self removeChild:target cleanup:YES]; } [targetsToDelete release]; } for (CCSprite *projectile in projectilesToDelete) { [m._projectiles removeObject:projectile]; [self removeChild:projectile cleanup:YES]; } [projectilesToDelete release]; }
最后,我们回到tower代码,看看我们是怎么处理开火机制的。在towerLogic代码里面,我们在RotateTo action之后再添加了一个action,叫做CCCallFunc。它会触发一个finishFiring方法。
[self runAction:[CCSequence actions: [CCRotateTo actionWithDuration:rotateDuration angle:cocosAngle], [CCCallFunc actionWithTarget:self selector:@selector(finishFiring)], nil]];
finishFiring只是在我们知道tower朝着正确的方向的时候才开火。它主要是创建一个新的子弹,然后把它加到DataModel的projectile数组中,同时给它一个位置和目的点。
- (void)finishFiring { DataModel *m = [DataModel getModel]; self.nextProjectile = [Projectile projectile]; self.nextProjectile.position = self.position; [self.parent addChild:self.nextProjectile z:1]; [m._projectiles addObject:self.nextProjectile]; ccTime delta = 1.0; CGPoint shootVector = ccpSub(self.target.position, self.position); CGPoint normalizedShootVector = ccpNormalize(shootVector); CGPoint overshotVector = ccpMult(normalizedShootVector, 320); CGPoint offscreenPoint = ccpAdd(self.position, overshotVector); [self.nextProjectile runAction:[CCSequence actions: [CCMoveTo actionWithDuration:delta position:offscreenPoint], [CCCallFuncN actionWithTarget:self selector:@selector(creepMoveFinished:)], nil]]; self.nextProjectile.tag = 2; self.nextProjectile = nil; }
你可以看到上面的代码,我们在projectile上面运行另一个CCMoveTo action,使之朝一个特定的方向移动。这样就会使得看起来是tower在发射子弹,但是,现在默认的距离是320.一旦子弹到达目的地后, "creepMoveFinished"方法就会被调用,它会从DataModel projectile数组中把这个projectile移除掉,并且把它从舞台中剔除。
-(void)creepMoveFinished:(id)sender { DataModel * m = [DataModel getModel]; CCSprite *sprite = (CCSprite *)sender; [self.parent removeChild:sprite cleanup:YES]; [m._projectiles removeObject:sprite]; }
恩,就这些了,编译并运行,你现在可以旋转炮塔了,而且它们可以攻击被杀死creep了。很酷吧?其实,我们的工作还没有完成,我们其实还需要添加一些塔的威力,还需要一个买卖系统,同时还要一个波数控制系统(可以控制当前波的速度快慢,总共多少波数等问题)。很多事情要做,不过我们已经上路了。。。
继续完善吧!
Tags: 

延伸阅读

最新评论

发表评论