4. 如何使用cocos2d来制作简单的iphone游戏:更猛的怪物和更多的关卡。(第三部分。完!)

4. 如何使用cocos2d来制作简单的iphone游戏:更猛的怪物和更多的关卡。(第三部分。完!),第1张

概述免责申明(必读!):本博客提供的所有教程的翻译原稿均来自于互联网,仅供学习交流之用,切勿进行商业传播。同时,转载时不要移除本申明。如产生任何纠纷,均与本博客所有人、发表该翻译稿之人无任何关系。谢谢合作! 原文链接地址:http://www.raywenderlich.com/782/harder-monsters-and-more-levels 目前为止,我正在翻译的游戏《如何如何使用cocos2

免责申明(必读!):本博客提供的所有教程的翻译原稿均来自于互联网,仅供学习交流之用,切勿进行商业传播。同时,转载时不要移除本申明。如产生任何纠纷,均与本博客所有人、发表该翻译稿之人无任何关系。谢谢合作!

原文链接地址:http://www.raywenderlich.com/782/harder-monsters-and-more-levels

目前为止,我正在翻译的游戏《如何如何使用cocos2d来制作一个简单的iphone》游戏非常cool。我们有一个可以旋转的炮塔,有怪物可以射杀,还有很棒的音效。

但是,我们的炮塔觉得这太简单了。这些怪物只要开一q就挂了,而且现在只有一个关卡!它还没有热身呢!

在这个教程里,我将会扩展我们的工程,并增加一些不同种类和难度的怪物,然后实现多个关卡。

更猛的怪物

为了好玩,让我们创建两种不同类型的怪物:一种不怎么经打,但是移动速度很快,还有一种很能抗(坦克级别),但是移动速度很慢!为了使玩家可以区分这两种不同类型的怪物,下载修改的怪物图片并把它们添加到工程里。同时,下载我制作的爆炸音效,也把它们添加到工程中去。

好了,让我们来创建Monster类。这里有许多方法来为Monster类建模,但是,我们选择最简单的方式,即把Monster类当作CCSprite的一个子类。同时,我们会创建两个Monster类的子类:一个为我们的虚弱快速怪创建,另一个为我们的强悍缓慢怪创建。

选择file\New file,再选择Cocoa touch Class\Objective-C class,确保Subclass of NSObject被选中。单击下一步,取名为Monster.m,然后确保“Also create Monster.h”复选上。

接下来,把Monster.h中的代码替换成下面的:

#import ”cocos2d.h”

@interface Monster : CCSprite {
int _curHp;
int _minMoveDuration;
int _maxMoveDuration;
}

@property (nonatomic,assign) int hp;
@property (nonatomic,assign) int minMoveDuration;
@property (nonatomic,assign) int maxMoveDuration;

@end

@interface WeakAndFastMonster : Monster {
}
+(ID)monster;
@end

@interface StrongAndSlowMonster : Monster {
}
+(ID)monster;
@end

 

这里非常直白:我们从CCSprite派生一个Monster类,然后增加了一些成员变量来记录monster的状态。然后,我们又从Monster类派生出两个不同的monster子类。

现在,打开Monster.m并添加下面的代码:

#import ”Monster.h”

@implementation Monster

@synthesize hp = _curHp;
@synthesize minMoveDuration = _minMoveDuration;
@synthesize maxMoveDuration = _maxMoveDuration;

@end

@implementation WeakAndFastMonster

+ (ID)monster {

WeakAndFastMonster *monster = nil;
if ((monster = [[[super alloc] initWithfile:@”Target.png”] autorelease])) {
monster.hp = 1;
monster.minMoveDuration = 3;
monster.maxMoveDuration = 5;
}
return monster;

}

@end

@implementation StrongAndSlowMonster

+ (ID)monster {

StrongAndSlowMonster *monster = nil;
if ((monster = [[[super alloc] initWithfile:@”Target2.png”] autorelease])) {
monster.hp = 3;
monster.minMoveDuration = 6;
monster.maxMoveDuration = 12;
}
return monster;

}

@end

这里代码很简单的,只有我们为每个类添加的一个静态方法,用来返回这个类的实例。然后初使化了默认的HP和移动所需要的时间。

现在,让我们把新创建的Monster类集成到之前的代码中去!首先在HelloWorldScene.m中导入文件:

#import ”Monster.h”

然后,修改addTarget方法来构造我们新创建的类的实例,而不是直接创建精灵(sprite)。替换spriteWithfile那一行,如下所示:

//CCSprite *target = [CCSprite spriteWithfile:@"Target.png" rect:CGRectMake(0,27,40)];
Monster *target = nil;
if ((arc4random() % 2) == 0) {
target = [WeakAndFastMonster monster];
} else {
target = [StrongAndSlowMonster monster];
}

这里将会有50%的机率来出现不同类型的monster。当然,我们把怪物的speed定义移到了类当中,因此,我们需要修改min/max移动间隔,把它改成下面的样子:

int minDuration = target.minMoveDuration; //2.0;
int maxDuration = target.maxMoveDuration; //4.0;

最后,在updateMethod里面做一些修改。首先,在targetsToDelete的声明之前,添加一个boolean值。

BOol monsterHit = FALSE;

然后,在CGRectIntesectsRect里面,不是马上把对象添加到targetsToDelete里面,而是改成下面的:

//[targetsToDelete addobject:target];
monsterHit = TRUE;
Monster *monster = (Monster *)target;
monster.hp–;
if (monster.hp <= 0) {
[targetsToDelete addobject:target];
}
break;

这里,我们不是马上杀死怪物,而是减少它的HP,而且只有当它的生命值小于0的时候,才kill它。注意,如果projectile击中一个怪物的话 我们就跳出循环,这意味着一个飞盘射击一次只能打一个怪物。

最后,我们把projectilesToDelete测试改成下面所示:

if (monsterHit) {
[projectilesToDelete addobject:projectile];
[[SimpleAudioEngine sharedEngine] playEffect:@”explosion.caf”];
}

编译并运行代码,如果一切顺利,那么你将会看到两种不同类型的怪物在屏幕上飞过—这使得我们的炮塔的生活更加富有挑战了!

多个关卡

为了使游戏支持多个关卡,首先我们需要重构。这个重构的工作非常简单,但是在这个项目里,有许多工作要做。如果把所有的内容都放在这个帖子上,那将会是一篇又长又乏味的帖子。

相反,我会从一个更高的角度来谈谈我做了什么,并且提供一个功能完整的样例工程。

抽象出一个Level类。目前,HelloWorldScene类里面把“level”的概念硬编码进去了,比如发射哪种类型的monster,发射频率如何等等。因此,我们的第一步就是要把这些信息提取出来,放到一个Level类里面。这样,在HelloWorldScene里面我们就可以为不同的关卡重用相同的逻辑。

重用场景。目前,我们每一次转换场景(scene)的时候都是重新创建了一个新的场景类。这里有一个缺点就是效率问题。每一次在场景对象的init方法里加载资源,这会影响游戏frame。

因为我们是一个简单的游戏,我们需要做的就是,每一个scene创建一个实例,并且提供一个reset方法来清除任何老的状态(比如上一关中的飞盘或者怪物)。

使用应用程序委托来当做跳板。目前,我们并没有任何全局的状态,比如:我们在哪一个关卡或者当前关卡的设置是什么。每一个场景仅仅是硬编码它需要跳转的下一个场景是谁。

我们将会修改这些内容,使用App Delegate来存储指向一些全局状态(比如关卡信息)的指针。因为,所有的场景(scene)都可以很方便地得到delegate对象。我们也会在App Delegate类里面放置一些方法,用来实现不同场景之间的切换的集中控制。并且减少场景之间的相互依赖。

好了,上面就是我所做的主要的重构内容—更多细节可查看样例工程。记住,这只是实现功能的方式之一,如果你有其它更好的组织场景和游戏对象的方法,请在这里分享出来吧!

不管怎么说,下载代码,运行看看吧。我们有一个非常不错的游戏了—-一个旋转的炮塔,成千上万的不同类型的敌人,多个关卡,win/lose场景,当然,还有很棒的音效!

总结

老样子,这里你可以下载到本系列教程目前为止完整的源代码。

现在,你知道如何制作一个简单的游戏了,为什么不更深入一点呢?学一学如何使用cocos2d来制作基于tile的游戏?毕竟,谁不喜欢忍者吃西瓜呢?

我希望你能喜欢这个系列的教程,希望这些教程能对你做项目有所帮助。

ps:接下来,我们尝试翻译一些有关Box2d方面的教程,敬请期待!

原创文章,转载请注明: 转载自DEVDIV博客-History

本文链接地址: (译)如何使用cocos2d来制作简单的iphone游戏:更猛的怪物和更多的关卡。(第三部分。完!)

总结

以上是内存溢出为你收集整理的4. 如何使用cocos2d来制作简单的iphone游戏:更猛的怪物和更多的关卡。(第三部分。完!)全部内容,希望文章能够帮你解决4. 如何使用cocos2d来制作简单的iphone游戏:更猛的怪物和更多的关卡。(第三部分。完!)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1054369.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存