科技: 人物 企业 技术 IT业 TMT
科普: 自然 科学 科幻 宇宙 科学家
通信: 历史 技术 手机 词典 3G馆
索引: 分类 推荐 专题 热点 排行榜
互联网: 广告 营销 政务 游戏 google
新媒体: 社交 博客 学者 人物 传播学
新思想: 网站 新书 新知 新词 思想家
图书馆: 文化 商业 管理 经济 期刊
网络文化: 社会 红人 黑客 治理 亚文化
创业百科: VC 词典 指南 案例 创业史
前沿科技: 清洁 绿色 纳米 生物 环保
知识产权: 盗版 共享 学人 法规 著作
用户名: 密码: 注册 忘记密码?
    创建新词条
科技百科
  • 人气指数: 3074 次
  • 编辑次数: 1 次 历史版本
  • 更新时间: 2012-07-01
土土
土土
发短消息
相关词条
电子游戏价值
电子游戏价值
独立游戏革命兴起
独立游戏革命兴起
游戏影响未来生活
游戏影响未来生活
六大游戏设计资源
六大游戏设计资源
全球游戏市场投资及并购
全球游戏市场投资及并购
休闲与硬核体验准则
休闲与硬核体验准则
设计电子游戏7个建议
设计电子游戏7个建议
10亿美元游戏
10亿美元游戏
2013年独立游戏
2013年独立游戏
独立游戏7个真实神话
独立游戏7个真实神话
推荐词条
希拉里二度竞选
希拉里二度竞选
《互联网百科系列》
《互联网百科系列》
《黑客百科》
《黑客百科》
《网络舆情百科》
《网络舆情百科》
《网络治理百科》
《网络治理百科》
《硅谷百科》
《硅谷百科》
2017年特斯拉
2017年特斯拉
MIT黑客全纪录
MIT黑客全纪录
桑达尔·皮查伊
桑达尔·皮查伊
阿里双十一成交额
阿里双十一成交额
最新词条

热门标签

微博侠 数字营销2011年度总结 政务微博元年 2011微博十大事件 美国十大创业孵化器 盘点美国导师型创业孵化器 盘点导师型创业孵化器 TechStars 智能电视大战前夜 竞争型国企 公益型国企 2011央视经济年度人物 Rhianna Pratchett 莱恩娜·普莱契 Zynga与Facebook关系 Zynga盈利危机 2010年手机社交游戏行业分析报告 游戏奖励 主流手机游戏公司运营表现 主流手机游戏公司运营对比数据 创建游戏原型 正反馈现象 易用性设计增强游戏体验 易用性设计 《The Sims Social》社交亮 心理生理学与游戏 Kixeye Storm8 Storm8公司 女性玩家营销策略 休闲游戏的创新性 游戏运营的数据分析 社交游戏分析学常见术语 游戏运营数据解析 iPad风行美国校园 iPad终结传统教科书 游戏平衡性 成长类型及情感元素 鸿蒙国际 云骗钱 2011年政务微博报告 《2011年政务微博报告》 方正产业图谱 方正改制考 通信企业属公益型国企 善用玩家作弊行为 手机游戏传播 每用户平均收入 ARPU值 ARPU 游戏授权三面观 游戏设计所运用的化学原理 iOS应用人性化界面设计原则 硬核游戏 硬核社交游戏 生物测量法研究玩家 全球移动用户 用户研究三部曲 Tagged转型故事 Tagged Instagram火爆的3大原因 全球第四大社交网络Badoo Badoo 2011年最迅猛的20大创业公司 病毒式传播功能支持的游戏设计 病毒式传播功能 美国社交游戏虚拟商品收益 Flipboard改变阅读 盘点10大最难iPhone游戏 移动应用设计7大主流趋势 成功的设计文件十个要点 游戏设计文件 应用内置付费功能 内置付费功能 IAP功能 IAP IAP模式 游戏易用性测试 生理心理游戏评估 游戏化游戏 全美社交游戏规模 美国社交游戏市场 全球平板电脑出货量 Facebook虚拟商品收益 Facebook全球广告营收 Facebook广告营收 失败游戏设计的数宗罪名 休闲游戏设计要点 玩游戏可提高认知能力 玩游戏与认知能力 全球游戏广告 独立开发者提高工作效率的100个要点 Facebook亚洲用户 免费游戏的10种创收模式 人类大脑可下载 2012年最值得期待的20位硅谷企业家 做空中概股的幕后黑手 做空中概股幕后黑手 苹果2013营收 Playfish社交游戏架构

Cocos2D制作打鼹鼠游戏 发表评论(0) 编辑词条

目录

Cocos2D制作打鼹鼠游戏编辑本段回目录

本系列教程共分为2部分,我将在第1部分中完成游戏的基本元素,即让可爱的小鼹鼠能够从地洞中窜出来。我们将着重思考如何规划图像和坐标轴的设置,从而让游戏在iPhone,iPad和Retina屏幕中能够有效地呈现出来。

规划图像设置:综述

因为我们希望这款游戏能够同时运行于普通的iPhone,拥有Retina屏幕的iPhone以及iPad上,我们便需要在深入发展之前多花点时间仔细规划图像的设置。

为了掌握图像的规模和设置,我们首先需要考虑到以下要点:

Retina屏幕和UIKit

Retina屏幕和Cocos2D

iPad,iPhone和纵横比

Retina屏幕和UIKit

普通iPhone与拥有Retina屏幕的iPhone的区别在于,后者可以通过Retina屏幕呈现出双倍的像素。也就是如果在普通iPhone上所呈现出的是480×320像素,那么在Retina屏幕上将出现960×640像素。

iPhone-vs-Retina(from raywenderlich)

iPhone-vs-Retina(from raywenderlich)

但是这时候你便会感到疑惑,即“像素的双倍增加难道不会破坏了那些基于480×320像素所编写的应用?”当然会(游戏邦注:特别是当你在使用UIKit进行编程时),除非你在UIKit中明确了帧的大小,否则你便是在以点而非像素设置大小。

在普通iPhone中,一个点代表一个像素。而在Retina屏幕中,一个点则等于两个像素。所以当我们将点的位置设置为(10,10)时,在普通iPhone上它的位置便是(10,10),而在Retina屏幕中则变成了(20,20),这是一种相对的位移。

如果你正在使用苹果的控制方式或Core Graphics,你便会发现苹果已经编写了合适的代码而让所有内容能够更好地呈现在Retina屏幕上。

只有你真正针对一张图像进行操作时你才能够发现问题的所在。假设你的iPhone应用中有一张200×200的图像,如果你不设置其它元素而将其放在Retina屏幕中,那么这张图像将被放大2倍,而最终显示出来的效果便会非常糟糕,因为你没有使用额外的分辨率去提升图像的质量。

No-HD-Res(from raywenderlich)

未使用高清分辨率的图像(from raywenderlich)

所以我们需要做的便是提供另外一个版本的图像:即共有普通版本和双倍规格版本。如果你在双倍大小的图像中添加了“@2x”扩展名,那么当你尝试着去加载[UIImage imageNamed:...]图像或类似的应用程序界面时,Retina屏幕上将自动加载@2x图像。

所以使用Retina屏幕创造UIKit应用非常简单,即只要添加@2x图像便算你完成了大部分的工作。

那么Cocos2D又是怎样的情况?

Retina屏幕与Cocos2D

有一个好消息是,最新的Cocos2D版本完全支持于Retina屏幕,并且让整个过程操作更加简便:

1.基于CCDirector调用enableRetinaDisplay能让你在启动应用时确保Retina屏幕的有效运行。如果你正在使用Cocos2D项目模版,你便可以在你的应用委托类中取消这一批注。

2.在你的应用上添加双倍精灵,而不是使用“@2x”扩展名,在Cocos2D中你可以使用“-hd”作为扩展名。当你加载精灵时,你只需使用正常名称(游戏邦注:即没有“-hd”扩展名),而Cocos2D将自动帮助你在Retina屏幕上加载高清图像。

3.现在,当我们开始在Cocos2D中为精灵定位时,我们便可以使用点而不是像素了。但是我们需要注意的是一些应用程序界面(不多)仍然在使用像素进行定位——如果是这样的话我们便需要在方法名称中强调像素,而不是点。

其实最简单的方法便是让美工尽可能提高图片像素(例如将图像规格扩大2倍以适应Retina屏幕),这时候你便能够在面对普通iPhone时轻松地压缩图像比例了。

你可能会好奇为何要纠结于设置两种不同规格的图像,为什么不只加载较大的图像然后在面对其它设备时有规律地进行缩放?在内存中加载纹理是最耗应用内存的做法,所以如果你运行的是一个不能利用较高像素图像的设备,你只有加载适合设备的较小图像才能有效地节省内存。

不要担心,你并不需要不断地在Photoshop中缩放图像。Texture Packer 拥有一个非常棒的功能可帮助你轻松地缩放图像,而这也是我们将在本教程中所使用到的功能。

iPad,iPhone和纵横比

好吧,现在看来Retina屏幕的图像设置已经不成问题了,那iPad呢?

我们都清楚,同时针对于iPhone和iPad制作游戏是件烦人的事,因为这两款设备拥有完全不同的纵横比!

iPhone的屏幕规格是480×320或960×640——即纵横比是1.5。而iPad则是768×1024——纵横比为1.33。

这就意味着如果你的一张图像能够填满整个iPad背景(768×1024),而你想要在iPhone上再次使用这张图像,那图像便不可能吻合地平铺于iPhone屏幕上。如果说你压缩了图像规格以适应iPhone的宽度(乘以0.9375):图像规格便会变成720×960,这时候便会多出一些空白区域而需要我们进行裁剪。

Aspect-Ratio-Diff(from raywenderlich)

Aspect-Ratio-Diff(from raywenderlich)

这就让事情变得更加麻烦了。因为你不仅需要处理背景图像的问题,同时你还会发现不同的纵横比将导致你难以在多种设备中使用相同的坐标轴。

关于这一问题存在着多种策略,我将在此列出我所看到/听到/使用过的几种:

在屏幕中央设置一个符合iPhone的Retina屏幕规格(640×960)的“可游戏区域”。如此我们便能够在边缘留出一些额外的空间——你可以用背景去覆盖这些空间,并且玩家也不会轻易注视到这一点。这种方法能够帮助你在不同设备间轻松地转变坐标轴并重复使用图像(在iPad和Retina屏幕上使用高分辨率的图像而在普通的iPhone上使用正常分辨率图像)。这也是我们在本篇教程中所使用的方法。

如果你在iPad屏幕上的每一边使用42像素分隔线,并将“主要内容”设置为684×1024,你便能够让iPad拥有与iPhone相同的纵横比。如果你将你的内容都控制在684×1024规格下,你便能够面向不同设备去压缩你的图像。

你可以面对iPhone,iPad以及Retina屏幕设置不同的图像和不同的坐标轴。这么做虽然能够让我们更加灵活地应对不同设备,但是我们还需要考虑到不同设备所具有的更大的二进制规格以及重置对象位置的问题。

另外一个问题是,从自动加载带有“-hd”扩展名的图像以及转换坐标轴等来看,现在的Cocos2D还不足以提供给iPad一些有益的帮助。

规划图像:结论

基于以上讨论,让我们开始规划这篇教程:

将图像限制在960×640规格的“可游戏区域”中,使用带有Retina屏幕的iPhone的全屏设置,并被居中置于iPad屏幕上。

基于Texture Packer将图像压缩为普通iPhone规格的一半。

将完整的图像命名为带有“-hd”扩展名的名称,而压缩后的文件则不带这一扩展名,Cocos2D将基于是否启用Retina屏幕而加载合适的图像。

背景便是一种特殊情况,因为它们总是需要全屏展开。我们需要将背景设置为1024×768规格(iPad的规格标准),从而确保整个屏幕都能被填满。因为规格的近似我们也可以将同一图像再次用于iPhone上。虽然有些背景会超出屏幕范围,但是这种情况却不会出现在这一特殊背景上。

iPad版本中将包含一些特殊代码,能够帮助我们使用带有“-hd”扩展名的图像,转换坐标轴以适应内部“可游戏区域”,以及使用合适的字体等。

首先请先下载针对于本教程的图像。打开文件并观察内部设置:

在“前景”文件夹中,前景的规格是1024×768(iPad的规格),但是实际上这个规格却被分成了两个部分:下面部分和上面部分。如此我们便能够将鼹鼠放置在下面和上面部分的中间段,让玩家觉得鼹鼠好像真的藏在地下似得。

在“背景”文件夹中,背景的纵横比是1.33(也就是iPad的纵横比),但实际上却只有一半的规格(512×384)。主要是因为背景很少显示出来(即只通过3个鼹鼠洞进行呈现),所以我们没有必要创造出一个1024×1024规格的纹理去加载这一背景。也就是较小的纹理更加合适。

在“精灵”文件夹中,所有的精灵规模都巧妙地设置在960×640“可游戏区域”内。我们需要注意的是,1只鼹鼠对应2个动画(也就是鼹鼠窜出来时便会遭遇敲打)。

好了,让我们正式开始进行教程分析!

开始

打开XCode,在主菜单中选择“File\New Project…”,并选择“User Templates\cocos2d\cocos2d Application”,点击“Choose…”。将项目命名为“WhackAMole”,并点击“保存”。

接下来,使用Finder将你之前所下载的“图像”文件夹复制到你的“WhackAMole”项目的目录中,同时确保这一文件夹必须与“build”和“Classes”文件夹处于同等级别,如下所示:

Directory-Structure(from raywenderlich)

Directory-Structure(from raywenderlich)

接下来确保你安装了Texture Packer,并能够用于你的设备中。

现在你便设置了TexturePacker,并能够以此创造你在之后所需要的精灵列表。只要使用TexturePacker的命令行工具以及Xcode集合你便能够完成各种任务,而不再需要依赖于TexturePacker的图形用户界面。

右击“资源”,选择“Add\New File…”,选择Mac OS X\Other\Shell Script,并点击“下一步”。将文件命名为“PackTextures.sh”,点击“完成”。

用以下代码取代PackTextures.sh的内容:

#!/bin/sh

TP=”/usr/local/bin/TexturePacker”

if [ "${ACTION}" = "clean" ]
then
echo “cleaning…”

rm resources/background*
rm resources/foreground*
rm resources/sprites*

else
echo “building…”

${TP} –smart-update \
–format cocos2d \
–data resources/background-hd.plist \
–sheet resources/background-hd.pvr.ccz \
–dither-fs \
–opt RGB565 \
Art/background/*.png

${TP} –smart-update \
–format cocos2d \
–data resources/background.plist \
–sheet resources/background.pvr.ccz \
–dither-fs \
–scale 0.5 \
–opt RGB565 \
Art/background/*.png

${TP} –smart-update \
–format cocos2d \
–data resources/foreground-hd.plist \
–sheet resources/foreground-hd.pvr.ccz \
–dither-fs-alpha \
–opt RGBA4444 \
Art/foreground/*.png

${TP} –smart-update \
–format cocos2d \
–data resources/foreground.plist \
–sheet resources/foreground.pvr.ccz \
–dither-fs-alpha \
–scale 0.5 \
–opt RGBA4444 \
Art/foreground/*.png

${TP} –smart-update \
–format cocos2d \
–data resources/sprites-hd.plist \
–sheet resources/sprites-hd.pvr.ccz \
–dither-fs-alpha \
–opt RGBA4444 \
Art/sprites/*.png

${TP} –smart-update \
–format cocos2d \
–data resources/sprites.plist \
–sheet resources/sprites.pvr.ccz \
–dither-fs-alpha \
–scale 0.5 \
–opt RGBA4444 \
Art/sprites/*.png

fi
exit 0

这一脚本将能够运行TexturePacker而创造出背景图像,前景图像以及脚本图像的精灵列表——即高清和一般质量的图像。

我们必须以pvr.ccz格式保存每一份图像——因为基于内存和磁盘空间来看这是最有效的格式。同时关于每种图像设置我们还必须明确合适的像素格式和递色选项,而以此权衡图像质量和储存空间的使用。

如果你不清楚TexturePacker选项到底能够做什么,那就加载Terminal并运行TexturePacker,而以此获得每个选项的完整描述内容。

接下来你需要让你的项目能够在编译时运行这一列表脚本。在“目标”文件夹中右击并选择“Add\New Target…”,然后选择“外部目标”(也就是非列表脚本目标!),点击“下一步”。将其命名为“Target TexturePacker”,并点击“完成”。

双击TexturePacker上的目标并如下进行设置:

Target-Settings(from raywenderlich)

Target-Settings(from raywenderlich)

最后一步便是将这一目标依附于你的应用中。双击TextureFun上的目标,找到“General”标签,在“Direct Dependencies”中点击“+”按钮,在列表中选中Texture Packer然后点击“添加目标”。

Dependencies(from raywenderlich)

Dependencies(from raywenderlich)

编译应用,如果一切设置合理的话你便能够从创建结果中看到Texture Packer的输出。

TexturePackerResults(from raywenderlich)

TexturePackerResults(from raywenderlich)

接下来你需要在项目中添加新生成的精灵列表和属性列表。在“资源”文件夹中右击并选择“Add\Existing Files…”,然后从“资源”中选择背景,前景和精灵文件(总共12个文件)然后相继点击“添加”。你必须确保“组和文件”结构如下所示:

SpriteSheetsAdded(from raywenderlich)

SpriteSheetsAdded(from raywenderlich)

你可以双击任何.pvr.ccz文件去加载预览内容。这便是Texture Packer的新功能!

设置背景

打开HelloWorldScene.m并找到你的初始方法。删除用于创造“Hello World”标签的4行代码,并用以下代码进行替换:

// Determine names of sprite sheets and plists to load
NSString *bgSheet = @”background.pvr.ccz”;
NSString *bgPlist = @”background.plist”;
NSString *fgSheet = @”foreground.pvr.ccz”;
NSString *fgPlist = @”foreground.plist”;
NSString *sSheet = @”sprites.pvr.ccz”;
NSString *sPlist = @”sprites.plist”;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
bgSheet = @”background-hd.pvr.ccz”;
bgPlist = @”background-hd.plist”;
fgSheet = @”foreground-hd.pvr.ccz”;
fgPlist = @”foreground-hd.plist”;
sSheet = @”sprites-hd.pvr.ccz”;
sPlist = @”sprites-hd.plist”;
}

// Load background and foreground
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:bgPlist];
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:fgPlist];

// Add background
CGSize winSize = [CCDirector sharedDirector].winSize;
CCSprite *dirt = [CCSprite spriteWithSpriteFrameName:@"bg_dirt.png"];
dirt.scale = 2.0;
dirt.position = ccp(winSize.width/2, winSize.height/2);
[self addChild:dirt z:-2];

// Add foreground
CCSprite *lower = [CCSprite spriteWithSpriteFrameName:@"grass_lower.png"];
lower.anchorPoint = ccp(0.5, 1);
lower.position = ccp(winSize.width/2, winSize.height/2);
[self addChild:lower z:1];

CCSprite *upper = [CCSprite spriteWithSpriteFrameName:@"grass_upper.png"];
upper.anchorPoint = ccp(0.5, 0);
upper.position = ccp(winSize.width/2, winSize.height/2);
[self addChild:upper z:-1];

// Add more here later…

让我们重温这一过程——因为这里存在一些很有帮助的新内容。

明确并加载精灵列表中的名称。这一部分主要罗列出Texture Packer所生成的精灵列表的名称,并进行加载。我们需要注意的是在iPhone上,Cocos2D将基于Retina屏幕是否运行而自动选择“-hd”版本和普通版本。而iPad则不会加载“-hd”版本,除非你命令它这么做。所以我们有必要明确我们所面对的是否是iPad,或者是否需要使用“-hd”版本。

加载背景和前景。接下来我们就需要在精灵帧缓存中加载背景和前景的相关信息,有备于今后的使用。我们还需要注意的是不能将这些精灵添加到CCSpriteBachNode——因为这些图像只有一次使用价值。

添加背景。我们必须确保背景图像是置于所有图层之下。为了保存空间并确保图像居中,我们压缩了一半的图像规格。

添加前景。前景的添加主要分为两个部分。较为简单的方式便是图像的设置,即在顶层图像的中间/底部以及底层图像的中间/顶端设置定位点,并将这一定位点对准屏幕中心。在这一过程中你无需使用任何复杂的数学运算,所有的定位点都会出现在不同设备的合理位置上。虽然对于iPhone来说背景总是会超出屏幕范围,但是对于这一背景来说却不是什么大问题,并且甚少玩家会注意到这一点。除此之外我们还必须牢记我们使用的是不同z值去添加图像,所以必须适度降低最高图像的位置。

编译并运行代码,这时你便能够在屏幕上看到背景和前景了。并观察这一代码是否能够同时有效地运行于iPhone和iPad模拟器上。

Background(from raywenderlich)

Background(from raywenderlich)

如果你尝试着在Retina屏幕上运行代码并放大显示,你仍将看到普通的图像设置:

HD-vs-Normal(from raywenderlich)

HD-vs-Normal(from raywenderlich)

主要是因为我们未在早些时候完成“Retina屏幕和Cocos2D”的第一个步骤:在CCDirector上调用enableRetinaDisplay,确保你在启动应用时能够运行Retina屏幕。

为了做到这一点你需要打开WhackAMoleAppDelegate.m,并在applicationDidFinishLaunching中取消以下内容的批注:

if( ! [director enableRetinaDisplay:YES] )
CCLOG(@”Retina Display Not supported”);

编译并运行代码,现在当你运行Retina屏幕时便可以看到它自动使用高清文件了——主要归功于Cocos2D对于Retina屏幕的支持。

放置鼹鼠

在这款游戏中我们共需要添加三只鼹鼠——一个洞里一只。通常情况下鼹鼠都是藏在草地底下,但是当它们突然“窜出来”时你便需要想办法敲击它们。

首先我们需要在每个洞的底端添加鼹鼠。我们需要暂时让它们出现在其它图层之上,以确保将其设置在正确的点上;随后将它们放置在地下,并调整到最合适的位置上。

打开HelloWorldScene.h并添加一个数组以追踪鼹鼠所在的层面,如下:

// Inside @interface HelloWorld
NSMutableArray *moles;

通过将鼹鼠的定位点储存在这一数组中,我们便能够在之后轻松地设置每一个鼹鼠的位置了。

接下来我们需要在初始方法的最末处添加代码以设置鼹鼠的位置:

// Load sprites
CCSpriteBatchNode *spriteNode = [CCSpriteBatchNode batchNodeWithFile:sSheet];
[self addChild:spriteNode z:999];
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:sPlist];

moles = [[NSMutableArray alloc] init];

CCSprite *mole1 = [CCSprite spriteWithSpriteFrameName:@"mole_1.png"];
mole1.position = [self convertPoint:ccp(85, 85)];
[spriteNode addChild:mole1];
[moles addObject:mole1];

CCSprite *mole2 = [CCSprite spriteWithSpriteFrameName:@"mole_1.png"];
mole2.position = [self convertPoint:ccp(240, 85)];
[spriteNode addChild:mole2];
[moles addObject:mole2];

CCSprite *mole3 = [CCSprite spriteWithSpriteFrameName:@"mole_1.png"];
mole3.position = [self convertPoint:ccp(395, 85)];
[spriteNode addChild:mole3];
[moles addObject:mole3];

这便是我们首次创造出属于精灵的CCSpriteBatchNode,如此我们便能更有效地绘制鼹鼠并将其设置在地底层。我们需要注意的是我们只是暂时将z值设置为999,如此我们才能在鼹鼠出现在顶层时确保它们的位置是否合理。

然后在属性列表中加载所有的精灵帧到缓存中,以确保我们之后能够用到这些内容。

为每个鼹鼠创造一个精灵并放置在场景中,然后添加到鼹鼠列表上。每只鼹鼠的坐标值都被控制在480×320(iPhone的规格)的“可游戏区域”中。而如果面向的是iPad,我们就需要修改这一定位,即我们需要调用辅助功能convertPoint。

在初始方法的右上方添加以下方法:

- (CGPoint)convertPoint:(CGPoint)point {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
return ccp(32 + point.x*2, 64 + point.y*2);
} else {
return point;
}
}

这一方法将帮助我们将“可游戏区域”点移至iPad屏幕上最合适的位置。我们需要记住:

我们正在iPad上使用高清图像,所以所有点都是双倍的。

我们将在1024×968的iPad屏幕上划出960×640的中心区域,并在左右两边和上下两端各留下32像素和64像素的边缘空间。

所以这一方法只是通过简单的数学运算而明确对象在iPad上的正确位置。

除此之外,我们必须添加以下代码清除我们用于分配鼹鼠数组的内存:

[moles release];
moles = nil;

编译并运行代码,这时候你便能够在正确的地点看到三只欢快的鼹鼠。并观察这一代码是否能够同时有效地运行于iPhone,iPhone Retina和iPad上。

Moles(from raywenderlich)

Moles(from raywenderlich)

窜出的鼹鼠

既然我们明确了鼹鼠的位置,接下来我们便需要添加代码让它们能够从洞里窜出来。

首先我们需要将鼹鼠精灵列表的z值从999重新调回0,以确保鼹鼠一开始是待在地下的。

然后在你的初始方法最底断添加以下代码:

self schedule:@selector(tryPopMoles:) interval:0.5];

如果你之前未看过这些内容,你可以在节点上运行调度方法并推动Cocos2D调用另外一种方法。就像在这种情况下,我们便希望每0.5秒就有鼹鼠窜出来。

接下来我们需要添加tryPopMoles的执行:

- (void)tryPopMoles:(ccTime)dt {
for (CCSprite *mole in moles) {
if (arc4random() % 3 == 0) {
if (mole.numberOfRunningActions == 0) {
[self popMole:mole];
}
}
}
}

我们将每隔0.5秒调用一次这一方法,并且每次调用将面向每一只鼹鼠而让它们平均拥有三分之一次跳出机会。但是鼹鼠们也只有在不能够移动时才能够窜出洞口——所以一种简单的检查方法便是确保行动数值是否为0.

最后,添加popMole的执行:

- (void) popMole:(CCSprite *)mole {
CCMoveBy *moveUp = [CCMoveBy actionWithDuration:0.2 position:ccp(0, mole.contentSize.height)]; // 1
CCEaseInOut *easeMoveUp = [CCEaseInOut actionWithAction:moveUp rate:3.0]; // 2
CCAction *easeMoveDown = [easeMoveUp reverse]; // 3
CCDelayTime *delay = [CCDelayTime actionWithDuration:0.5]; // 4

[mole runAction:[CCSequence actions:easeMoveUp, delay, easeMoveDown, nil]]; // 5

这一代码正是使用Cocos2D行动而促使鼹鼠能够窜出洞口,时隔半秒再钻回去。让我们进一步明确这些内容:

1.创造一个行动而推动着鼹鼠沿着纵坐标(如鼹鼠般高)向上移动。因为我们已经将鼹鼠准确安置在洞的正下方,所以它们窜出的位置也是合理的。

2.确保鼹鼠的移动看起来足够自然,将他们的移动行动与CCEaseInOut行动结合在一起。这么做能够确保开始和结束时的行动较慢,即鼹鼠能够加速/减速,以此让整体看起来更加自然。

3.创造一个行动让鼹鼠能够再次回到洞里。一个简单的方法便是调用行动的反方法。

4.创造一个行动让鼹鼠能够在窜出后一秒停下行动。

5.既然完成了行动设置,我们便能够运行它们而完成鼹鼠的一系列行动:窜出,延迟然后缩回洞里。同时我们还需要在最后终止这一系列行动以表示动作的完成。

编译并运行代码,你将能够看到鼹鼠们欢快地窜出洞口了!

Mole-Pop(from raywenderlich)

Mole-Pop(from raywenderlich)

游戏邦注:原文发表于2011年1月10日,所涉事件和数据均以当时为准。

本文为游戏邦/gamerboom.com编译,作者:Ray Wenderlich )

Whack A Mole(from raywenderlich)

Whack A Mole(from raywenderlich)

而在本篇文章中我们将在鼹鼠身上添加一些可爱的动画,让它们不仅能够微笑还能够显现出被敲击的表情;同时还将添加一些游戏玩法让玩家能够敲打鼹鼠而获得分数,并且像其它游戏那样也会在此添加音效。

定义动画:实用性

为了让游戏看起来更加有趣,我们将在鼹鼠身上添加两个动画。首先当它窜出洞口时就会微笑(从而诱导玩家去敲打它!),而当你尝试着去敲打它时,它的脸上将会出现挨打的表情。

不过在正式开始前我想先谈谈如何使用代码去定义我们动画的实用性。

在cocos2d的动画教程中关于创造动画的一大步骤便是创造一列精灵帧。所以对于动画中的每幅不同图像,你都需要在其阵列中添加如下精灵帧:

[animFrames addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@”myImage.png”]];

我们的鼹鼠微笑动画将基于这个顺序成形:mole_laugh1.png, mole_laugh2.png mole_laugh3.png, mole_laugh2.png, mole_laugh3.png以及mole_laugh1.png。

所以我们便能以此编写出几行代码去创造动画:

[animFrames addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@”mole_laugh1.png”]];
[animFrames addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@”mole_laugh2.png”]];
[animFrames addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@”mole_laugh3.png”]];
[animFrames addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@”mole_laugh2.png”]];
// And so on…

但是如此看来我们的代码稍显凌乱,所以为了让整体看起来更加整洁,我们将代码放置在属性列表中而不是在动画中定义图像代码。

属性列表

如果你从未使用过属性列表,你便可以基于Xcode创建一些特殊文件,分级罗列出阵列,信息库,字符和数字等数据。

让我们看看具体要怎么做。首先我们需要在“资源”文件中右击并选择“Add\New File…”,然后选择“Mac OS X\Resource\Property List”,点击“下一步”。将新文件命名为“laughAnim.plist”并点击“完成”。这时我们便能够看到 laughAnim.plist 的属性列表编辑器,如下所示:

Property-List-Editor(from raywenderlich)

Property-List-Editor(from raywenderlich)

每个属性列表都拥有一个根元素,它可以是一个阵列或者一个信息库。而我们所创建的属性列表则将包含一组构成微笑动画的图像名称,所以我们需要点击根元素(目前是信息库)的第二栏并将其改为阵列。

接下来点击最右边的小按钮(游戏邦注:如下图,看起来就像三条线的图标),从而在阵列中添加一个新的条目。默认的条目类型是字符,而这也正是我们想要的。将动画中的第一个条目数值改为“mole_laugh1.png”。

点击“+”按钮添加新的一行,并重复添加所有动画帧,如下:

Laugh-Anim(from raywenderlich)

Laugh-Anim(from raywenderlich)

接下来当鼹鼠遭到敲打时我们仍需要重复上述的动画制作过程,并创造出一个名为hitAnim.plist的新属性列表,如下:

Hit-Anim(from raywenderlich)

Hit-Anim(from raywenderlich)

现在,是时候添加代码去加载这些动画了。我们需要打开HelloWorldScene.h并为每个动画添加如下变量:

// Inside @interface HelloWorld
CCAnimation *laughAnim;
CCAnimation *hitAnim;

我们将以此作为一种便利的参考,从而让我们能够在代码中轻松找到并重复使用CCAnimation。

接下来我们需要基于属性列表中所定义的图像而添加一种方法去创造CCAnimation:

- (CCAnimation *)animationFromPlist:(NSString *)animPlist delay:(float)delay {

NSString *plistPath = [[NSBundle mainBundle] pathForResource:animPlist ofType:@”plist”]; // 1
NSArray *animImages = [NSArray arrayWithContentsOfFile:plistPath]; // 2
NSMutableArray *animFrames = [NSMutableArray array]; // 3
for(NSString *animImage in animImages) { // 4
[animFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:animImage]]; // 5
}
return [CCAnimation animationWithFrames:animFrames delay:delay]; // 6

}

我们必须理解这些代码:

1.属性列表是包含于项目文件中,所以它是在应用的“main bundle”中。这种方法将能够帮助我们在主束中创建一个文件,并且之后你需要在属性列表中阅读这一文件内容。

2.阅读属性列表,你将会发现这与在NSArray上调用arrayWithContentsOfFile方法并传送到属性列表中一样简单。我们将重新获得NSArray的相关内容(在这里也就是一列关于动画图像名称的字符)。我们需要注意的是之所这种方法会奏效是因为我们将根元素设定为NSArray了。而如果我们将其设定为NSDictionary,我们可能就要使用[NSDictionary dictionaryWithContentsOfFile...]了。

3.创建一个空白阵列以储存动画帧。

4.在属性列表的阵列中浏览每个图像名称。

5.获得每个图像的精灵帧并将其添加到阵列中。

6.基于精灵帧阵列而重新回到CCAnimation。

接下来我们需要在初始代码的末尾添加以下代码而调用每个动画的帮助功能:

laughAnim = [self animationFromPlist:@"laughAnim" delay:0.1];
hitAnim = [self animationFromPlist:@"hitAnim" delay:0.02];
[[CCAnimationCache sharedAnimationCache] addAnimation:laughAnim name:@”laughAnim”];
[[CCAnimationCache sharedAnimationCache] addAnimation:hitAnim name:@”hitAnim”];

同时还需要注意的是当我们储存了动画参考后,我们还需要将其添加到动画缓存中。这一点非常重要,如此我们才能够有效地保存动画,并且我们也能够使用名称在动画中检索到我们想要的内容。

最后一步——让我们开始使用动画(目前只是关于微笑的动画)。如下修改popMole方法:

- (void) popMole:(CCSprite *)mole {
CCMoveBy *moveUp = [CCMoveBy actionWithDuration:0.2 position:ccp(0, mole.contentSize.height)];
CCEaseInOut *easeMoveUp = [CCEaseInOut actionWithAction:moveUp rate:3.0];
CCAction *easeMoveDown = [easeMoveUp reverse];
CCAnimate *laugh = [CCAnimate actionWithAnimation:laughAnim restoreOriginalFrame:YES];

[mole runAction:[CCSequence actions:easeMoveUp, laugh, easeMoveDown, nil]];
}

这里所存在的不同在于,比起在鼹鼠钻回洞里前延迟1秒钟,反而是在此运行CCAnimate行动。CCAnimate行动较早使用laughAnim进行设置,并将resotreOriginalFrame设置为“YES”,从而让鼹鼠能够在动画结束后恢复到正常的表情。

编译并运行代码,现在你便可以看到鼹鼠窜出洞口后朝你微笑了!

Mole-Laugh(from raywenderlich)

Mole-Laugh(from raywenderlich)

接下来我们便需要让鼹鼠的微笑转变成挨打的表情了!

添加游戏逻辑

现在我们需要在游戏中添加游戏逻辑。游戏理念是关于一定数量的鼹鼠会窜出洞口,你可以通过敲击它们而获得分数。你可以努力去争取最高的分数。

所以我们就需要去追踪分数并将其呈现给玩家。而当鼹鼠结束了跳窜行动后我们也需要让玩家明确地知道这一点。

所以让我们打开HelloWorldScene.h,并在HelloWorld层上添加以下实例变量:

CCLabelTTF *label;
int score;
int totalSpawns;
BOOL gameOver;

这些代码将能够追踪分数标签,当前分数,目前位置窜出的鼹鼠数量以及游戏是否结束等信息。

接下来我们需要在初始方法的最末尾添加以下代码:

self.isTouchEnabled = YES;

float margin = 10;
label = [CCLabelTTF labelWithString:@"Score: 0" fontName:@"Verdana" fontSize:[self convertFontSize:14.0]];
label.anchorPoint = ccp(1, 0);
label.position = ccp(winSize.width – margin, margin);
[self addChild:label z:10];

首先我们赋予了层面可触摸的性质,因为我们总是希望能在玩家碰触屏幕时察觉到这一动作。然后我们创造了一个标签向玩家呈现分数变化。同时还需要注意的是我们在标签的右下角设置了一个定位点“o”,如此我们便能够将标签放置在屏幕的右下方处。

我们最好先使用一个帮助功能去转化字体大小。因为iPad的屏幕更大,所以我们需要较大的字体。所以我们需要如下执行convertFontSize:

- (float)convertFontSize:(float)fontSize {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
return fontSize * 2;
} else {
return fontSize;
}
}

这个过程其实非常简单——我们只需要将iPad上的字体设置为2倍大便可。

接下来我们将要添加触碰检测代码以观察玩家的碰触是否击中了鼹鼠。但是在此之前我们需要在鼹鼠身上添加一个标记以帮助我们明确鼹鼠是否挨打了。当鼹鼠微笑时它只能窜出洞口,而当它钻回洞里时它也就“安全”了。

我们将为鼹鼠创造一个CCSprite子集进行追踪,但是因为我们只需要储存一条信息,所以我们只需要在CCSprite上使用userData便可。我们需要如下添加两个帮助方法并再一次修改popMole:

CCSprite *mole = (CCSprite *)sender;
[mole setUserData:TRUE];
}

- (void)unsetTappable:(id)sender {
CCSprite *mole = (CCSprite *)sender;
[mole setUserData:FALSE];
}

- (void) popMole:(CCSprite *)mole {

if (totalSpawns > 50) return;
totalSpawns++;

[mole setDisplayFrame:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@”mole_1.png”]];

// Pop mole
CCMoveBy *moveUp = [CCMoveBy actionWithDuration:0.2 position:ccp(0, mole.contentSize.height)];
CCCallFunc *setTappable = [CCCallFuncN actionWithTarget:self selector:@selector(setTappable:)];
CCEaseInOut *easeMoveUp = [CCEaseInOut actionWithAction:moveUp rate:3.0];
CCAnimate *laugh = [CCAnimate actionWithAnimation:laughAnim restoreOriginalFrame:YES];
CCCallFunc *unsetTappable = [CCCallFuncN actionWithTarget:self selector:@selector(unsetTappable:)];
CCAction *easeMoveDown = [easeMoveUp reverse];

[mole runAction:[CCSequence actions:easeMoveUp, setTappable, laugh, unsetTappable, easeMoveDown, nil]];

}

我们需要如下改变popMole:

在鼹鼠微笑之前我们需要运行CCCallFunc行动去调用一个特定的方法(setTappable)。这一方法能够在精灵上将userData属性设置为TRUE,而我们也将以此明确是否能够拍打鼹鼠。

同样地,在鼹鼠微笑后我们需要使用CCCAllFunc行动去调用unsetTappable,并将鼹鼠身上的标志再次设为FALSE。

如果鼹鼠窜出的次数达到了50次以上(游戏邦注:因为50次已经是这款游戏的极限了),那么这一方法便会立刻恢复之前的样子。

在方法的开始处将精灵显示帧重置为基础图像(“mole_1.png”),因为当鼹鼠最后一次遭到敲击时,我们将会看到“敲击”图像并将需要对此进行重置。

既然精灵带有userData标志能够预示鼹鼠是否遭到敲击,我们便可以添加如下敲击检测代码:

-(void) registerWithTouchDispatcher
{
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:kCCMenuTouchPriority swallowsTouches:NO];
}

-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
for (CCSprite *mole in moles) {
if (mole.userData == FALSE) continue;
if (CGRectContainsPoint(mole.boundingBox, touchLocation)) {

mole.userData = FALSE;
score+= 10;

[mole stopAllActions];
CCAnimate *hit = [CCAnimate actionWithAnimation:hitAnim restoreOriginalFrame:NO];
CCMoveBy *moveDown = [CCMoveBy actionWithDuration:0.2 position:ccp(0, -mole.contentSize.height)];
CCEaseInOut *easeMoveDown = [CCEaseInOut actionWithAction:moveDown rate:3.0];
[mole runAction:[CCSequence actions:hit, easeMoveDown, nil]];
}
}
return TRUE;
}

registerWithTouchDispatcher方法能够推动着ccTouchBegan方法调用每次碰触。

ccTouchBegan方法能够转变碰触在层面上的坐标轴,并依次通过每只鼹鼠。即如果玩家未碰到鼹鼠(即userData为false),它便会自己跳到下一只鼹鼠身上。另外,它也将使用CGRectContainsPoint去明确碰触点是否位于鼹鼠的边界框内。

如果鼹鼠遭到敲打,这一方法便能够让鼹鼠不再具有被敲打的属性,并提高玩家的分数。然后停止任何行动,播放“敲打”动画,并将鼹鼠迅速移回洞中。

最后一步,在tryPopMoles的开始处添加一些代码去更新分数并检查关卡的完成状态:

if (gameOver) return;

[label setString:[NSString stringWithFormat:@"Score: %d", score]];

if (totalSpawns >= 50) {

CGSize winSize = [CCDirector sharedDirector].winSize;

CCLabelTTF *goLabel = [CCLabelTTF labelWithString:@"Level Complete!" fontName:@"Verdana" fontSize:[self convertFontSize:48.0]];
goLabel.position = ccp(winSize.width/2, winSize.height/2);
goLabel.scale = 0.1;
[self addChild:goLabel z:10];
[goLabel runAction:[CCScaleTo actionWithDuration:0.5 scale:1.0]];

gameOver = true;
return;

编译并运动你的代码,这时候你便能够敲击鼹鼠并提高你的分数了!

High-Score(from raywenderlich)

High-Score(from raywenderlich)

音效

像往常一样我们也需要在此添加一些特别的音效而让游戏变得更加有趣。下载我通过使用Garage Band(这是一款由苹果电脑编写的数码音乐创作软件,是Macintosh电脑上的应用程序套装iLife的一部分)和Audacity(一款跨平台,免费开源的录音,编辑声音编辑器)所创造的音效,打开文件,并将声音拖到你的“资源”文件夹中。确保你选中了“将内容复制到你的目标群组”这一文件夹,然后点击“添加”。

然后在HelloWorldScene.m做出如下改变:

// Add to top of file
#import “SimpleAudioEngine.h”

// Add at the bottom of your init method
[[SimpleAudioEngine sharedEngine] preloadEffect:@”laugh.caf”];
[[SimpleAudioEngine sharedEngine] preloadEffect:@”ow.caf”];
[[SimpleAudioEngine sharedEngine] playBackgroundMusic:@”whack.caf” loop:YES];

// Add at bottom of setTappable
[[SimpleAudioEngine sharedEngine] playEffect:@”laugh.caf”];

// Add inside ccTouchBegan, inside the CGRectContainsPoint case
[[SimpleAudioEngine sharedEngine] playEffect:@”ow.caf”];

编译并运行代码,现在你便能够听到每秒的旋律了!

游戏邦注:原文发表于2011年1月17日,所涉事件和数据均以当时为准。(本文为游戏邦/gamerboom.com编译,拒绝任何不保留版权的转载,如需转载请联系:游戏邦

How To Create A Mole Whacking Game with Cocos2D: Part 2/2

17 January 2011

This article is the second part of a two-part series on how to create a mole whacking game with Cocos2D. This series brings together a lot of concepts from other cocos2D tutorials on this site, and introduces some new concepts along the way as well.

In the first part of the series, we created the basics of the game – cute little moles popping out of holes. We spent a lot of time thinking about how to organize the art and coordinates so that the game would look good on the iPhone, iPad, and Retina display – and be efficient too!

In this article, we’ll add some cute animations to the mole as he laughs and gets whacked, add gameplay so you can do the whacking and earn points, and of course add some gratuitous sound effects as usual.

If you don’t have it already, grab a copy of the project where we left things off in the last tutorial.

Defining Animations: Practicalities

To make the game a little more fun, we’re going to give the mole two animations. First, he’ll laugh a little when he pops out of the hole (to make you really want to whack him!), then if you do manage to whack him he’ll make a “just got whacked” face.

But before we begin, let’s talk about the practicalities of defining our animations in code.

Recall from the cocos2d animations tutorial that one of the steps to create an animation is to create a list of sprite frames. So for each different image in your animation, you have to add the sprite frame for that sprite into an array like this:

Our mole’s laugh animation is going to be these images in this order: mole_laugh1.png, mole_laugh2.png mole_laugh3.png, mole_laugh2.png, mole_laugh3.png, mole_laugh1.png.

So we could hard-code a bunch of lines to set up our animation, like this:

But that would make our code kind of ugly. To make things a bit cleaner, instead of defining the images in the animation in code, we’ll bring them out to a property list instead.

Property Lists
If you haven’t used property lists before, they are special files you can create in XCode to contain data like arrays, dictionaries, strings, numbers, and so on in a hierarchial format. It’s extremely easy to create these, and just as easy to read them from code.

Let’s see what I mean by trying this out in XCode. Right click on Resources, choose “Add\New File…”, choose “Mac OS X\Resource\Property List”, and click “Next”. Name the new file “laughAnim.plist”, and click Finish. At this point the property list editor for laughAnim.plist should be visible, as shown below:

Every property list has a root element. This is usually either an array or a dictionary. This property list is going to contain an array of image names that make up the laugh animation, so click on the second column for the root element (Type, currently set to Dictionary), and change it to Array.

Next, click the small button to the far right that looks like three lines – this adds a new entry to the array. By default, the type of the entry is a String – which is exactly what we want. Change the value to “mole_laugh1.png” for the first entry in the animation.

Click the + button to add a new row, and repeat to add all of the frames of the animation, as shown below:

Next, repeat the process for the animation to play when the mole is hit. Follow the same steps as above to create a new property list named hitAnim.plist, and set it up as shown below:

Now, time to add the code to load these animations. Start by opening up HelloWorldScene.h and add a member variable for each animation, as shown below:

These will be used to keep a handy reference to each CCAnimation so it can be easily found and reused in the code.

Next add a method to create a CCAnimation based on the images defined in the property list, as follow:

This is important to understand, so let’s go through it line by line.

1.The property list is included in the project file, so it’s in the app’s “main bundle”. This helper method gives a full path to a file in the main bundle, which you’ll need to read in the property list.

2.To read a property list, it’s as easy as calling a method on NSArray called arrayWithContentsOfFile and passing in the path to the property list. It will return an NSArray with the contents (a list of strings for the image names in the animatoin, in this case). Note this works because we set the root element to be an NSArray. If we had set it to a NSDictionary, we could use [NSDictionary dictionaryWithContentsOfFile...] instead.

3.Creates an empty array that will store the animation frames.

4.Loops through each image name in the array read from the property list.

5.Gets the sprite frame for each image and adds it to the array.

6.Returns a CCAnimation based on the array of sprite frames.

Next, add the code to the end of your init method to call this helper function for each animation:

Note that after squirreling away a reference to the animation, it adds it to the animation cache. This is important to do so that the animations are saved off (and retained) somewhere. It’s also helpful since you could retrieve them from the animation cache by name if you wanted (but we dont’ need to since we’re keeping a reference ourselves).

One last step – let’s use the animations (just the laugh one for now). Modify the popMole method to read as the following:

The only difference here is that instead of delaying a second before popping down, it runs a CCAnimate action instead. The CCAnimate action uses the laughAnim set up earlier, and sets resotreOriginalFrame to YES so that when the animation is done, it reverts back to the normal mole face.

Compile and run your code, and now when the moles pop out, they laugh at you!

Time to wipe that smile off their faces and start whacking!

Adding Game Logic
We’re now going to add the gameplay logic into the game. The idea is a certain number of moles will appear, and you get points for each one you whack. You try to get the most number of points you can.

So we’ll need to keep track of the score, and also display it to the user. And when the moles are finished popping, we’ll need to tell the user about that as well.

So start by opening HelloWorldScene.h, and add the following instance variables to the HelloWorld layer:

These will keep track of the score label, the current score, the number of moles popped so far, and whether the game is over or not.

Next add the following to the end of your init method:

This first sets the layer as touch enabled, since you’ll want to detect when the player taps the screen. It then creates a label to show the score. Note that it sets the anchor point o the bottom right of the label so that it’s easy to place it in the lower right of the screen.

Also note that rather than pasing the font size directly, it goes through a helper function to convert the font size first. This is because the font size will need to be larger on the iPad, since it has a bigger screen. So implemenet convertFontSize next as the following:

This is very simple – on the iPad the font size is doubled, otherwise it’s left alone.

Next we want to add the touch detection code to see if a touch has hit a mole. But before we can do that, we need to add a flag to the mole to the game knows whether the mole is currently tappable or not. The mole should only be able to be tapped while it’s laughing – while it’s moving or underground it’s “safe.”

We could create a subclass of CCSprite for the mole to keep track of this, but because we only need to store this one piece of information, we’ll use the userData property on the CCSprite instead. So add two helper methods and modify popMole one more time to do this as follows:

The changes to popMole are as follows:

Right before the mole laughs, it runs a CCCallFunc action to call a specified method (setTappable). This method sets the userData property on the sprite to TRUE, which we’ll use to indicate whether the mole is tappable.

Similarly, after the mole laughs, it uses a CCCAllFunc action to call unsetTappable, which sets the flag back to FALSE.

The method also immediately returns if there has been 50 or more spawns, since 50 is the limit for this game.

It resets the display frame of the sprite to the base image (“mole_1.png”) at the beginning of the method, since if the mole was hit last time, it will still be showing the “hit” image and will need to be reset.

Ok, now that the sprite has a userData flag indicating whether it can be tapped or not, we can finally add the tap detection code as follows:

The registerWithTouchDispatcher method sets things up so that the ccTouchBegan method gets called for each touch. For more details on this and why this is useful, check out an explanation in the How To Make a Tile Based Game with Cocos2D Ttutorial.

The ccTouchBegan method converts the touch to coordinates in the layer, and loops through each mole. If the mole isn’t tappable (the userData is false), it skips to the next mole. Otherwise, it uses CGRectContainsPoint to see if the touch point is within the mole’s bounding box.

If the mole is hit, it sets the mole as no longer tappable, and increases the score. It then stops any running actions, plays the “hit” animation, and moves the mole immediately back down the hole.

One final step – add some code to update the score and check for the level complete condition at the beginning of tryPopMoles:

That’s it! Compile and run your code, and you should be able to whack moles and increase your score! How high of a score can you get?

Gratuitous Sound Effects

As usual, let’s add even more fun to the game with some zany sound effects. Download these sound effects I made with Garage Band and Audacity, unzip the file, and drag the sounds to your Resources folder. Make sure that “Copy items into destination group’s folder” is selected, and click Add.

Then make the following changes to HelloWorldScene.m:

Compile and run your code, and enjoy the groovy tunes!(source:raywenderlich)

→如果您认为本词条还有待完善,请 编辑词条

词条内容仅供参考,如果您需要解决具体问题
(尤其在法律、医学等领域),建议您咨询相关领域专业人士。
0

标签: Cocos2D制作打鼹鼠游戏

收藏到: Favorites  

同义词: 暂无同义词

关于本词条的评论 (共0条)发表评论>>

对词条发表评论

评论长度最大为200个字符。