文件结构

    Bg文件夹包含的是游戏的背景及界面构成图片,包括转盘、大炮等,plist文件夹是主要的素材文件夹,包含各种鱼的种类,渔网、炮弹等,这里边的大部分素材都没用到,ParticleEffect包含效果文件,如加五分、气泡、火焰等,由于这个游戏只是示例代码,所以不是很完善,多数素材只用到一部分,功能也是基本的,但对初学者来说,已经足够好了,即实现了以希望游戏的基本功能,效果又比较漂亮,也不是很复杂,虽然还有bug,但总而言之,对初学者而言,还算是比较好的入门资料。本文以一个初学者的角度来解析,可能比较啰嗦,旨在抛砖引玉,共同学习,同时非常感谢源代码的共享者。

    UINumber和UIRollNum实现了分数的上下滚动,CCNet只有一个Bool变量,是对是否被击中的判断,CCFish实现了鱼的随机出现和游动,由于没有实现场景的切换,所以HelloWorldLayer是唯一的游戏场景,是主要的控制文件,没有视图文件,界面是在代码里创建的。

   Resources文件夹包含一些基本的素材文件,例如数字滚动的背景图,程序图标文件等,libs文件包含cocos2d等一些引用的库文件。代码不是很多,不会看上去就头晕,很适合初学者研究学习。

    main.m研究

    代码------------------------------------------------------------------------------------------------------------------------------------------------


int main(int argc, char *argv[])


    代码------------------------------------------------------------------------------------------------------------------------------------------------


//C/C++语言中的main函数,经常带有参数argc,argv,如下:
//int main(int argc, char** argv)
//int main(int argc, char* argv[])
//这两个参数的作用是什么呢?argc 是指命令行输入参数的个数,argv存储了所有的命令行参数。假如你的程序是hello.exe,如果在命令行运行该程序,(首先应该在命令行下用 cd 命令进入到 hello.exe 文件所在目录) 运行命令为:
//hello.exe Wang zg
//那么,argc的值是 3,argv[0]是"hello.exe",argv[1]是"Wang",argv[2]是"zg"。


    代码------------------------------------------------------------------------------------------------------------------------------------------------



NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];



    代码------------------------------------------------------------------------------------------------------------------------------------------------


//    Cocoa的内存管理主要依赖于Reference Counting, 而NSAutoReleasePool就是用来支持它的. autorelease pool中存放的对象会在其自身干枯(drain)时被release.
//    我们都知道当一个object的release方法被触发时, 这个对象就被销毁了, 再也不能对它有任何引用, 否则就会出现异常. 但如果在销毁它时触发的是autorelease方法, 那这个object就进入了对应的autorelease pool, 它的生命就被延长了(当pool drain时才真正被销毁).
//    在Reference Counting的环境里, Cocoa总是期望在每一个thread都存在一个autorelease pool, 如果不存在, 那些被autoreleased的objects就不会被销毁, 从而产生memory leak. (印象中这种情况下xcode会在console打出warnning信息)
//    NSAutoReleasePool的初始化与普通的NSObject一样, 都是alloc+init, 不过pool不能被retain, 因为在drain的时候默认就销毁它自身了. 还有一点需要注意的是, 通常在销毁pool的时候用的不是它的release方法, 而是drain! 原因是为了让程序同时兼容Reference Counting内存管理环境 与 Garbge Collection环境, 因为在Garbage Colloection环境中drain的作用是触发collect garbage动作.
//    一般来说在应用的main thread中, 已经存在了一个autorelease pool. 有两种情况需要开发者自己新建autorelease pool:
//    1.在main thread中, 在某个方法中出现大量的autoreleased objects, 为了避免memory footprint的增大, 可以手动创建一些autorelease pool用来drain objects.
//    2.创建新的thread, 并在其中访问了Cocoa, 需要在访问的前创建autorelease pool, 访问结束后drain.
//    最后一点, 在每个thread中都会维持一个stack, 其中放置着所有在这个thread中创建但未销毁的pool, 每当一个新的pool创建后, 它就位于stack的最顶端,  相应autoreleased object就会放入其中. 当pool drain的时候, 它就会从stack的顶端移除, 并且release掉其包含的objects.


    代码------------------------------------------------------------------------------------------------------------------------------------------------


int retVal = UIApplicationMain(argc, argv, nil, @"AppDelegate");


    代码------------------------------------------------------------------------------------------------------------------------------------------------


//     UIApplication是初始化程序的核心,它接受4个参数。  其中argc和argv两个参数来自于main()接受的两个参数;另外两个String型参数分别表示程序的主要类(principal class)和代理类(delegate class)
//    那么UIApplicationMain函数到底做了哪些事情呢?这个函数主要负责三件事情:
//    1)从给定的类名初始化应用程序对象,也就是初始化UIApplication或者子类对象的一个实例,如果你在这里给定的是nil,那么系统会默认UIApplication类,也就主要是这个类来控制以及协调应用程序的运行。在后续的工作中,你可以用静态方法sharedApplication
//    来获取应用程序的句柄。
//    2)从给定的应用程序委托类,初始化一个应用程序委托。并把该委托设置为应用程序的委托,这里就有如果传入参数为nil,会调用函数访问 Info.plist文件来寻找主nib文件,获取应用程序委托。
//    3)启动主事件循环,并开始接收事件。
//    上面是UIApplicationMain函数的工作,接下来一个问题是应用程序视图的显示、消息的控制怎么办?下面就是UIApplication(或者子类)对象的职责,这个对象主要做下面几件事:
//    1)负责处理到来的用户事件,并分发事件消息到应该处理该消息的目标对象(sender, action)。
//    2)管理以及控制视图,包括呈现、控制行为、当前显示视图等。
//    3)该对象有一个应用程序委托对象,当一些生命周期内重要事件(可以包括系统事件或者生命周期控制事件)发生时,应用程序通知该对象。例如,应用程序启动、内存不够了或者应用程序结束等,让这些事件发生时,应用程序委托去响应。
//    通过上面的分析,可以知道UIApplication对开发者来说,是一个黑箱,它也可以是。因为所有的操作,都可以由它的委托来帮我们完成,它只需要在后面维护一些不可更改的东西,如事件消息分发和传递、给委托发送事件处理请求等等,如,应用程序加载处理完毕,它会发送消息给委托,然后委托可以在 applicationDidFinishLanching委托函数中去实现开发者想要的动作。利用XCODE在创建应用程序时,会默认实现一个应用程序委托类。而对于加载的视图,则有视图相关的委托类来处理视图加载过程的生命事件。
//    UIApplication 接收到所有的系统事件和生命周期事件时,都会把事件传递给UIApplicationDelegate进行处理,对于用户输入事件,则传递给相应的目标对象去处理。比如我们在应用程序被来电等消息后,可以调用应用程序委托类的 applicationWillResignActive()方法,这个方法在用户锁住屏幕时,也会调用,与之相适应的是应用程序重新被用户打开时的委托方法。另外常用的就是内存不足的系统警告,此时会调用应用程序委托类的applicationDidReceiveMemoryWarning()方法,然后我们就可以试着释放一些内存了。


//    AppDelegate实际上是实现了UIApplicationDelegate协议的类。UIApplicationDelegate协议定义了很多和Application状态、消息相关的方法。您可以简单的理解为Application和系统的一个联系。   
//    在创建project的时候,Xcode会自动为您生成一个AppDelegate类。并在程序运行起来的时候创建AppDelegate对象(方式是通过UIApplicationMain的方法,在main.c文件中,这个就是App的入口函数)。这样在App运行过程中,就会调用AppDelegate中的方法。比如:程序运行起来时,会调用applicationDidFinishLaunchingWithOptions:的方法
//    AppDelegate是你整个应用的一个代理。当你应用启动的时候,最先被调用到的就是你AppDelegate中的- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法。可以在这个方法中做些全局初始化。
//    AppDelegate中可以做应用退出后台或从后台返回到前台的一些处理。