<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_子龙山人</title><subtitle type="text">Learning,Sharing,Improving!</subtitle><id>http://feed.cnblogs.com/blog/u/85573/rss</id><updated>2012-04-28T03:01:37Z</updated><author><name>子龙山人</name><uri>http://www.cnblogs.com/zilongshanren/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/zilongshanren/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/85573/rss"/><entry><id>http://www.cnblogs.com/zilongshanren/archive/2012/04/28/2473282.html</id><title type="text">（译）cocos2d-x跨android&amp;amp;ios平台开发入门教程</title><summary type="text">免责申明（必读！）：本博客提供的所有教程的翻译原稿均来自于互联网，仅供学习交流之用，切勿进行商业传播。同时，转载时不要移除本申明。如产生任何纠纷，均与本博客所有人、发表该翻译稿之人无任何关系。谢谢合作！原文链接地址：http://www.raywenderlich.com/11283/cocos2d-x-for-ios-and-android-getting-started教程截图： Cocos2D是一个非常棒而且非常容易使用的游戏框架，但是，由于它是采用objc写的，所以你只能使用它来开发ios和mac下面的游戏。 假如你可以使用和cocos2d相似的api来开发android上面的游戏..</summary><published>2012-04-28T02:53:00Z</published><updated>2012-04-28T02:53:00Z</updated><author><name>子龙山人</name><uri>http://www.cnblogs.com/zilongshanren/</uri></author><link rel="alternate" href="http://www.cnblogs.com/zilongshanren/archive/2012/04/28/2473282.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/zilongshanren/archive/2012/04/28/2473282.html"/><content type="html">&lt;p&gt;&lt;span style="color: #ff0000;"&gt;免责申明（必读！）：本博客提供的所有教程的翻译原稿均来自于互联网，仅供学习交流之用，切勿进行商业传播。同时，转载时不要移除本申明。如产生任何纠纷，均与本博客所有人、发表该翻译稿之人无任何关系。谢谢合作！&lt;/span&gt;&lt;/p&gt;&lt;p&gt;原文链接地址：&lt;a href="http://www.raywenderlich.com/11283/cocos2d-x-for-ios-and-android-getting-started" target="_blank"&gt;http://www.raywenderlich.com/11283/cocos2d-x-for-ios-and-android-getting-started&lt;/a&gt;&lt;/p&gt;&lt;p&gt;教程截图：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042711543591.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; Cocos2D是一个非常棒而且非常容易使用的游戏框架，但是，由于它是采用objc写的，所以你只能使用它来开发ios和mac下面的游戏。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 假如你可以使用和cocos2d相似的api来开发android上面的游戏，那岂不是更爽？这样，你就可以毫不费劲地扩大你的游戏的市场份额（android的用户数量巨大啊！）&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 好吧，确实存在这么一个游戏框架，她就是cocos2d-x！cocos2d-x采用c++把cocos2d的api重新移植了一遍，，除了一些语法细节上面的差异之外，你可以使用几乎一样的api来编写游戏。正是由于它是c++写的，所以可以跨多个平台，从ios到android、windows、再到linux、bada等！&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 在这篇教程里面，你将学习到，如何使用cocos2d-x和c++来编写一个能够同时在ios和android设备上面跑的&amp;ldquo;Hello World&amp;rdquo;程序。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 而且，过两天，我会再出一篇教程，向大家展示一个具体的游戏例子---一个跨平台的太空射击游戏！&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 好了，带上你的iPhone和Android设备，让我们开始吧！&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Hello, Cocos2D-X for iOS!&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 在继续之前，确保你先下载最新版本的&lt;a href="http://www.cocos2d-x.org/" target="_blank"&gt;cocos2d-x&lt;/a&gt;。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 随便在你的硬盘的某个位置上面解压就可以了。注意，这个解压出来的文件夹的完整路径名，我们之后会用一个统一的别名&amp;nbsp;$COCOS2DX_HOME来指代。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 现在，你已经下载到源码了，让我们来安装项目模板吧！你可以先cd到$COCOS2DX_HOME这个目录（译者：指你刚刚解压缩代码的存放路径）下面去。在安装模板之前，先退出Xcode，然后打开一个终端，并输入下面的命令：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #000000;"&gt;cd $COCOS2DX_HOME&lt;br/&gt;sudo .&lt;/span&gt;/install-templates-xcode.sh -u&lt;/div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;注意: 在上面所示的代码中，你不能直接输入$COCOS2DX_HOME，而要输入实际的路径。如果你直接输入了$COCOS2DX_HOME是不会有任何反应的。当然，你可以参考我写的&lt;a href="http://www.cnblogs.com/zilongshanren/archive/2012/02/23/2364163.html"&gt;《如何在macos下面配置集成ios和android游戏教程》&lt;/a&gt;，里面有讲到环境变量的配置。大概方法就是打开～/.bash_profile文件，然后用export来定义环境变量就ok了。&lt;/div&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 你可能会被要求输入管理员密码（加了-u应该是不需要输入密码的，不加-u就需要输入），之后的过程就非常简单了。在模板安装好之后，启动xcode，然后创建一个新的项目。这时，你可以在项目模板对话框中看到有cocos2d-x的模板了。不用担心，cocos2d-x的模板与cocos2d的模板并不会有冲突，因此，你还是可以创建cocos2d的项目。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 让我们来试一下新模板吧！打开Xcode，然后创建一个新的工程，选择&amp;nbsp;iOS\cocos2d-x\cocos2dx模板，如下图所示：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042711561910.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 把工程例句为Cocos2DxFirstIosSample，然后保存。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp;现在，编译并运行，你将会看到cocos2d-x的hello wolrd程序跑起来了，如下图所示：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042711564984.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 非常简单，不是吗？这时，你可以看看xcode里面的文件，特别是Classes\HelloWorldScene.H和Classes\HelloWorldScene.cpp。如果你也熟悉cocos2d的话，那么里面的代码看起来会觉得非常熟悉---几乎完全一样的cocos2d API，只是语言是c++而已！&lt;/p&gt;&lt;p&gt;&lt;strong&gt;配置cocos2d-x的eclipse开发环境&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 现在我们已经完成了Xcode4的hello world程序了，是时候看看如何使用eclipse来配置android 的cocos2d-x开发环境了。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 这篇教程假设你有一个可以进行Android开发的标准开发环境。如果你还没有的话，可以参考&lt;a href="http://www.raywenderlich.com/5527/getting-started-with-android-development" target="_blank"&gt;这篇教程&lt;/a&gt;来配置，它里面提供了详细的过程，教你如何一步步配置好一个标准的eclipse android开发环境。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp;但是，请等一下。一个标准的eclipse android开发环境是专为java开发设计的，而cocos2d-x却是基于c++来做开发的！&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 不用担心，eclipse已经有10年的历史了，它有许多插件可以支持其它语言的开发，这当然就包括c/C++语言的插件啦。先让我们来安装这个插件吧。打开eclipse，然后执行以下步骤：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;从Eclipse IDE的主工具栏上面，选择Help/Install New Software。&lt;/li&gt;&lt;li&gt;打开Work With复选框，并从中选择一个包含你的eclipse版本名称的项（如果是最新版的eclipse的话，就选择indigo）&lt;/li&gt;&lt;li&gt;在插件树里面找到Programming Languages (只有当你复选中&amp;ldquo;Group items by category&amp;rdquo;时，你才可以看到插件树。)并打开它.&lt;/li&gt;&lt;li&gt;选择CDT插件，然后安装下列组件。（但是，请注意，你如果直接就点击C/C++ Development Tools的话，你是得不到下图所示的样子的，你还需要在&amp;ldquo;Mobile Development&amp;rdquo;里面去查找相关的项）（译者：我没找了，直接就选择了C/C++ Development Tools就Next安装了）&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042711573652.png" alt="" /&gt;&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;点击next来完成向导，然后等待组件下载并安装。现在，你可以使用eclipse来开发C/C++项目了！&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Setup the Android NDK (Native Development Toolkit)&lt;/strong&gt;&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;本来，android开发只能采用java，而且现在市场上面大部分的app也是采用java写的。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 然而，现在你还可以通过Native Development Toolkit (NDK)，使用C/C++来编写android程序。这种编程方式是由Google在2009年6月份引入的，它允许一些组件采用C/C++来编写，然后通过标准的Java Native Interface (JNI)来调用。&lt;/p&gt;&lt;p align="left"&gt;安装NDK的过程非常简单：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;下载最新版本的NDK。&amp;nbsp;&lt;a href="http://developer.android.com/sdk/ndk/index.html"&gt;here&lt;/a&gt;&amp;nbsp;(注意选择 MacOSX 平台).&lt;/li&gt;&lt;li&gt;解压tar.bz2 到任意目录.之后，我会使用$NDKROOT来指定这个解压缩后的目录。&lt;/li&gt;&lt;/ul&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; NDK给Android开发带来了全套的C/C++编译工具集，可以使用GCC4.4.3来编译来链接并且可以构建即时安装的APK包。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp; 有了这套编译工具集，我们就可以在eclipse里面集成一些外部的C/C++库（比如cocos2d-x）。这些库被编译成动态库，然后通过JNI(Java Native Interface)与Java Android体系程序进行交互。&lt;/p&gt;&lt;p align="left"&gt;这些编译工具集可以采用下面两种方式使用 :&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;独立模式&lt;/em&gt;: 直接在你的makefile中使用 arm-linux-androideabi-g++. 这种方式会增加你的项目的复杂性和可维护性。我推荐你不要使用这种方式。&lt;/li&gt;&lt;li&gt;&lt;em&gt;集成模式：&lt;/em&gt; 使用$NDKROOT/ndk-build shell 工具，它是一种高度可定制的makefile，专门为NDK库所设计的。这也是我们这篇教程所采用的方式。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042711581595.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p align="left"&gt;解释JNI和NDK可能会花费大量时间，而且也超出了本教程的讨论范围。现在网络上有许多关于JNI的资源。这里还推荐&lt;a href="http://java.sun.com/docs/books/jni/"&gt;一本书&lt;/a&gt;，它也讨论了JNI这个主题。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 如果你需要更多关于NDK的信息，这里推荐一本非常好的书，它里面涵盖了使用C/C++进行NDK开发，书名是：&amp;nbsp;&lt;a href="http://www.packtpub.com/android-ndk-beginners-guide/book"&gt;Android Native Development Kit Beginner&amp;rsquo;s Guide&lt;/a&gt;。这本书覆盖了NDK编程的方方面面，可谓是&amp;ldquo;从入门到精通&amp;rdquo;，而且NDK本身也带有非常详细的文档，在$NDKROOT/docs路径下面。&lt;/p&gt;&lt;p align="left"&gt;&lt;strong&gt;Hello, Cocos2D-X for Android!&lt;/strong&gt;&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 现在，让我们在Andriod平台上面来开发一个&amp;ldquo;Hello，World&amp;rdquo;程序吧，就像我们之前在ios平台上的程序一样。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我们需要通过命令行来完成工作，因为目前还没有在Eclipse IDE里面集成cocos2d-x的模板。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在$COCOS2DX_HOME目录下面包含一个shell脚本，叫做create-android-project.sh，我们可能通过它来创建android项目。但是，在运行脚本之前，我们需要在脚本文件的顶部做一些修改：&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;# &lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt; environment paramters&lt;br/&gt;NDK_ROOT_LOCAL&lt;/span&gt;=&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;/home/laschweinski/android/android-ndk-r5&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;ANDROID_SDK_ROOT_LOCAL&lt;/span&gt;=&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;/home/laschweinski/android/android-sdk-linux_86&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p align="left"&gt;修改上面这些行，把NDK_ROOT_LOCAL指向你安装Android NDK ($NDKROOT)的位置，同时把ANDROID_SDK_ROOT_LOCAL指向你安装Android SDK位置。（译者：这里其实可以不用修改，读者可以打开这个sh脚本去看看为什么。如果之前看过我的配置教程，里面有配置一个全局的NDK_ROOT和ANDROID_SDK_ROOT。这个脚本在判断有全局的环境变量存在的时候，会直接替代NDK_ROOT_LOCAL和ANDROID_SDK_ROOT_LOCAL。）&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 现在，可以运行create-android-project.sh脚本了，然后你会接收到一系列的提示输入。我们将一个个向您解释一下：&lt;/p&gt;&lt;ol start="1"&gt;&lt;li&gt;第一个提示要求你&amp;ldquo;Input package path&amp;rdquo;。这个包名会给后面的java代码使用。你可以使用你的域名反过来写，类似写ios的bundle ID。比如com.yourdomain.samplecocos2dxandroid ，记住实际输入的时候要替换掉&amp;ldquo;com.yourdomain&amp;rdquo;。&lt;/li&gt;&lt;li&gt;接下来，你会得到一系列可用的Android API和它们的id号。这个具体取决于你的机器上面安装的Andriod API的情况。&lt;/li&gt;&lt;li&gt;最后，你需要提供项目的名称，在这里取名为&lt;em&gt;samplecocos2dxandroid&lt;/em&gt;：&lt;/li&gt;&lt;/ol&gt;&lt;p align="left"&gt;命令行的输出大致如下：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;bash-$ ./create-android-&lt;span style="color: #000000;"&gt;project.sh&lt;br/&gt;Input package path. For example: org.cocos2dx.example&lt;br/&gt;org.jymc.samplecocos2dxandroid&lt;br/&gt;. . .&lt;br/&gt;Available Android targets:&lt;br/&gt;&lt;/span&gt;----------&lt;span style="color: #000000;"&gt;&lt;br/&gt;. . .&lt;br/&gt;&lt;/span&gt;----------&lt;span style="color: #000000;"&gt;&lt;br/&gt;id: &lt;/span&gt;&lt;span style="color: #800080;"&gt;9&lt;/span&gt; or &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Google Inc.:Google APIs:15&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;     Name: Google APIs&lt;br/&gt;     Type: Add&lt;/span&gt;-&lt;span style="color: #000000;"&gt;On&lt;br/&gt;     Vendor: Google Inc.&lt;br/&gt;     Revision: &lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;     Description: Android &lt;/span&gt;+&lt;span style="color: #000000;"&gt; Google APIs&lt;br/&gt;     Based on Android &lt;/span&gt;&lt;span style="color: #800080;"&gt;4.0&lt;/span&gt;.&lt;span style="color: #800080;"&gt;3&lt;/span&gt; (API level &lt;span style="color: #800080;"&gt;15&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br/&gt;. . .&lt;br/&gt;input target id:&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #800080;"&gt;9&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;input your project name:&lt;br/&gt;samplecocos2dxandroid&lt;br /&gt;&lt;br/&gt;Created project directory: &lt;/span&gt;/Users/jymen/development/cocos2dx/&lt;span style="color: #000000;"&gt;samplecocos2dxandroid&lt;br/&gt;. . .&lt;br/&gt;Added file &lt;/span&gt;/Users/jymen/development/cocos2dx/samplecocos2dxandroid/&lt;span style="color: #000000;"&gt;AndroidManifest.xml&lt;br/&gt;Added file &lt;/span&gt;/Users/jymen/development/cocos2dx/samplecocos2dxandroid/&lt;span style="color: #000000;"&gt;build.xml&lt;br/&gt;Added file &lt;/span&gt;/Users/jymen/development/cocos2dx/samplecocos2dxandroid/&lt;span style="color: #000000;"&gt;proguard.cfg&lt;br/&gt;bash&lt;/span&gt;-$&lt;/div&gt;&lt;p align="left"&gt;&amp;nbsp;注意&amp;ldquo;Created project directory:&amp;rdquo;这一行是脚本文件最后输出来的，这个输出的路径也就是你的Andriod项目被创建好的路径。我这里指的是/Users/jymen/development/cocos2dx/samplecocos2dxandroid，如上图所示：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;Note: Do not &lt;span style="color: #0000ff;"&gt;try&lt;/span&gt; to move the project &lt;span style="color: #0000ff;"&gt;from&lt;/span&gt; that location to a different location. At least one of the scripts we&amp;rsquo;ll work with &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; the next section will not work &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; you &lt;span style="color: #0000ff;"&gt;do&lt;/span&gt;.&lt;/div&gt;&lt;p align="left"&gt;&lt;strong&gt;构&lt;/strong&gt;&lt;strong&gt;建工程&lt;/strong&gt;&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这里有两个步骤来构建项目----首先通过命令行脚本编译c++代码，然后通过ecipse来编译java代码。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 为了编译c++代码，我们需要切换到$PROJECT_HOME/android文件夹下面去，然后在终端里面输入下列命令：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;./build_native.sh&lt;/div&gt;&lt;p align="left"&gt;你应该会看到下面类似的输出：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;Gdbserver      : [arm-linux-androideabi-&lt;span style="color: #800080;"&gt;4.4&lt;/span&gt;.&lt;span style="color: #800080;"&gt;3&lt;/span&gt;] libs/armeabi/&lt;span style="color: #000000;"&gt;gdbserver&lt;br/&gt;Gdbsetup       : libs&lt;/span&gt;/armeabi/&lt;span style="color: #000000;"&gt;gdb.setup&lt;br/&gt;Compile&lt;/span&gt;++ thumb  : cocos2d &amp;lt;=&lt;span style="color: #000000;"&gt; CCConfiguration.cpp&lt;br/&gt;Compile&lt;/span&gt;++ thumb  : cocos2d &amp;lt;=&lt;span style="color: #000000;"&gt; CCDrawingPrimitives.cpp&lt;br/&gt;:&lt;br/&gt;:&lt;br/&gt;:&lt;br/&gt;Compile&lt;/span&gt;++ thumb  : cocos2d &amp;lt;=&lt;span style="color: #000000;"&gt; CCTileMapAtlas.cpp&lt;br/&gt;Compile&lt;/span&gt;++ thumb  : cocos2d &amp;lt;=&lt;span style="color: #000000;"&gt; CCTouchDispatcher.cpp&lt;br/&gt;Compile&lt;/span&gt;++ thumb  : cocos2d &amp;lt;=&lt;span style="color: #000000;"&gt; CCTouchHandler.cpp&lt;br/&gt;Prebuilt       : libstlport_static.a &lt;/span&gt;&amp;lt;= /sources/cxx-stl/stlport/libs/armeabi/&lt;span style="color: #000000;"&gt;&lt;br/&gt;SharedLibrary  : libcocos2d.so&lt;br/&gt;Install        : libcocos2d.so &lt;/span&gt;=&amp;gt; libs/armeabi/&lt;span style="color: #000000;"&gt;libcocos2d.so&lt;br/&gt;Compile&lt;/span&gt;++ thumb  : cocosdenshion &amp;lt;=&lt;span style="color: #000000;"&gt; SimpleAudioEngine.cpp&lt;br/&gt;Compile&lt;/span&gt;++ thumb  : cocosdenshion &amp;lt;=&lt;span style="color: #000000;"&gt; SimpleAudioEngineJni.cpp&lt;br/&gt;SharedLibrary  : libcocosdenshion.so&lt;br/&gt;Install        : libcocosdenshion.so &lt;/span&gt;=&amp;gt; libs/armeabi/&lt;span style="color: #000000;"&gt;libcocosdenshion.so&lt;br/&gt;Compile&lt;/span&gt;++ thumb  : game_logic &amp;lt;=&lt;span style="color: #000000;"&gt; AppDelegate.cpp&lt;br/&gt;Compile&lt;/span&gt;++ thumb  : game_logic &amp;lt;=&lt;span style="color: #000000;"&gt; HelloWorldScene.cpp&lt;br/&gt;SharedLibrary  : libgame_logic.so&lt;br/&gt;Install        : libgame_logic.so &lt;/span&gt;=&amp;gt; libs/armeabi/&lt;span style="color: #000000;"&gt;libgame_logic.so&lt;br/&gt;Compile&lt;/span&gt;++ thumb  : game &amp;lt;=&lt;span style="color: #000000;"&gt; main.cpp&lt;br/&gt;SharedLibrary  : libgame.so&lt;br/&gt;Install        : libgame.so &lt;/span&gt;=&amp;gt; libs/armeabi/libgame.so&lt;/div&gt;&lt;p align="left"&gt;&amp;nbsp;这里就是在编译cocos2d-x库和你的项目里面的c++文件。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 为了编译java代码，我们需要创建一个eclipse工程---这可比命令行要方便多了。：）&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 打开Eclipse，然后他吃软饭File\New\Other，选择Android\Android Project，然后点击Next，在Project Name里面输入&lt;em&gt;samplecocos2dxandroid&lt;/em&gt;&amp;nbsp;，然后选择&amp;nbsp;&lt;em&gt;Create project from existing source&lt;/em&gt;&lt;em&gt;，然后浏览到&lt;/em&gt;$PROJECT_HOME/android文件夹，如下图所示：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042714151936.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;点击Next，选择一个&amp;nbsp;Android version to target（这里选择的是3.2，你可以选择任何一个）&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042714160690.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;点击Finish，好了，现在你有一个工程了！&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042714163350.png" alt="" /&gt;&lt;/p&gt;&lt;p align="left"&gt;在左边的树上右击项目，选择Run As\Android Application，然后AVD (Android Virtual Device)就会启动，然后就会跑出来Hello, Cocos2D-X项目了！&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042714170327.png" alt="" /&gt;&lt;/p&gt;&lt;p align="left"&gt;&lt;em&gt;&amp;nbsp;&lt;/em&gt;&lt;em&gt;注意：如果程序没有启动的话，你需要按照提示去创建一个&lt;/em&gt;&lt;em&gt;AVD&lt;/em&gt;&lt;em&gt;来测试。更多的细节，请参考&lt;/em&gt;&lt;a href="http://www.raywenderlich.com/5527/getting-started-with-android-development"&gt;Getting Started with Android Development&lt;/a&gt;&amp;nbsp;这篇教程。&lt;/p&gt;&lt;p align="left"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/em&gt;&lt;em&gt;恭喜你，你现在有一个&amp;ldquo;&lt;/em&gt;&lt;em&gt;Hello&lt;/em&gt;&lt;em&gt;，&lt;/em&gt;&lt;em&gt;World&lt;/em&gt;&lt;em&gt;&amp;rdquo;项目可以同时跑在&lt;/em&gt;&lt;em&gt;ios&lt;/em&gt;&lt;em&gt;和&lt;/em&gt;&lt;em&gt;android&lt;/em&gt;&lt;em&gt;上面了！&lt;/em&gt;&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&lt;/p&gt;&lt;p align="left"&gt;&lt;strong&gt;在&lt;/strong&gt;&lt;strong&gt;Eclipse&lt;/strong&gt;&lt;strong&gt;里面定&lt;/strong&gt;&lt;strong&gt;义&lt;/strong&gt;&lt;strong&gt;一个&lt;/strong&gt;&lt;strong&gt;结&lt;/strong&gt;&lt;strong&gt;合&lt;/strong&gt;&lt;strong&gt;java/c++&lt;/strong&gt;&lt;strong&gt;的工程&lt;/strong&gt;&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 通过命令脚本来编译c++代码，完了之后用eclipse来编译java代码，这种来回切换的做法非常笨重。如果全部可以用eclipse来完成的话，那么生活会更简单一些。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 幸运的是，我们可以告诉eclipse，我们的android项目是一个集成java/c++的跨语言项目！&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp; 为此，我们在左边的项目树上选择samplecocos2dxandroid，然后从菜单里面选择File\New\Other，然后从对话框里面选择C/C++\Convert to a C/C++ Project，如下所示：&lt;/p&gt;&lt;p&gt;&lt;em&gt;&amp;nbsp;&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042714173931.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;点击Next。在下一个屏幕里面，选中你的项目，然后选择c++单选按钮，然后为Project type指定Makefile project\Other Toolchain，如下所示：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042714181312.png" alt="" /&gt;&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;点击完成。这时eclipse会询问你是否打开C/C++视图，当对话框出现的时候，选择NO。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp; 接下来的步骤就是修改项目设置，指定如何运行我们的make命令。在左边的项目树上，右击samplecocos2dxandroid工程，选择Properties，然后选择C/C++ build&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042714184661.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;取消&amp;ldquo;Use default build command&amp;rdquo;复选框，然后在build文本框中输入下面的命令：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;bash ${workspace_loc:/samplecocos2dxandroid}/build_native.sh NDK_DEBUG=&lt;span style="color: #800080;"&gt;1&lt;/span&gt; V=&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;/div&gt;&lt;p align="left"&gt;点击Apply，然后点OK。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp; 回到ecipse，从主菜单中选择Project\Build All，这时你可以在ecipse的控制台输出中看到c++ make在运行。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042714193438.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;我们仍然有一些警告需要解决。想知道我是什么意思吗，你打开jni/helloworld/main.cpp，这里你会看到一系列的警告，如下所示：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042714200675.png" alt="" /&gt;&lt;/p&gt;&lt;p align="left"&gt;这些警告之所以会出现，是因为我们没有配置正确的c++包含路径。为了解决它，我们右击samplecocos2dxandroid工程，然后选择Properties\C/C++ General\Path and Symbols\GNU C++。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp; 选择Add&amp;hellip;按钮来选择下面的目录，之后点击Apply和OK。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;$(NDKROOT)/platforms/android-&lt;span style="color: #800080;"&gt;9&lt;/span&gt;/arch-arm/usr/&lt;span style="color: #000000;"&gt;include&lt;br/&gt;$(COCOS2DX_HOME)&lt;/span&gt;/cocos2dx/include&lt;/div&gt;&lt;p align="left"&gt;&lt;em&gt;注意&lt;/em&gt;: 不用忘了使用实际的路径来替换掉$(NDKROOT) 和$(COCOS2DX_HOME)。&lt;/p&gt;&lt;p&gt;&lt;em&gt;&amp;nbsp;&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042714205439.png" alt="" /&gt;&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;点击Apply，这时会提示你是否重建索引。直接点击yes继续就可以了。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp; 现在，你再看看main.cpp，你会看到大部分警告已经消失了。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042714213368.png" alt="" /&gt;&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;但是，AppDelegate.h文件还是找不到。这是因为AppDelegate.h是在$PROJECT_HOME\Classes文件夹下面。这个文件夹对我们来说非常重要，因为它包含了我们工程里面的可移植的c++类，比如HelloWorldScene.cpp等。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 当我们创建eclipse项目的时候，我们必须选择$PROJECT_HOME\android文件夹，因为eclipse需要一个AndroidManifest.xml文件。但是，这样的话，我们的工程就不包括关键的&amp;ldquo;Classes&amp;rdquo;文件夹了，这也是为什么我们会得到这么多警告的原因。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp; 让我们来修正它吧。右击samplecocos2dxandroid项目，选择Properties\C/C++ General\Paths and Symbols\Source location。点击Link Folder，然后复选中&lt;em&gt;Link to a folder in the file system&lt;/em&gt;&lt;em&gt;，接着浏览到&lt;/em&gt;$PROJECT_HOME文件夹，并指向Classes目录，最后点Apply和OK。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042714220355.png" alt="" /&gt;&lt;/p&gt;&lt;p align="left"&gt;你现在可以在文件树里面看到Classes目录了，而且在main.cpp里面的#include &amp;ldquo;AppDelegate.h&amp;rdquo;警告也应该消失了。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp; Eclipse工程里面还会有许多警告，但是，这是因为eclipse对于解析c++头文件的能力并不强大。为了消除这些警告，我们又需要设置一下项目设置。（右键点工程，然后选择Properties），把Code Analysis部分的warnings关闭，如下图所示：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042714223110.png" alt="" /&gt;&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;然后点击Apply和OK，这时，你就得到一个工程可以在eclipse里面进行编辑了。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&lt;/p&gt;&lt;p align="left"&gt;&lt;strong&gt;What About the Java Code?&lt;/strong&gt;&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这时你在eclipse里面再找找看，你会在src和gen目录下面找到一些java代码，你肯定很好奇这些代码是干吗用的。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp; Andriod开发采用的主要语言是java，这个项目模板已经为我们创建了一些java框架代码，用来加载c++编写好的动态库。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp; 一般情况下，你是不需要修改这些java代码的，但是，还是让我们来看看src\com\xxx\samplecosos2dxandroid\samplecocos2dandroid.java这个类。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp; 这个类包含了主Android Activity类，当应用程序启动的时候会加载。它首先通过NDK来请求编译好的c++动态库。（如果采用的是最新版的coocs2dx的话，下面只会加载一个game库）&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042714231588.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;由于类是从Cocos2dxActivity所派生，在后台cocos2d-x会把控制权移交给c++的AppDelegate 的initInstance方法来处理，最后applicationDidFinishLAunching方法也就被执行起来了。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 因此，再重申一遍，java代码只是一些包装代码，大部分情况下我们都不要去修改它，因为我们的游戏逻辑是由c++写的。&lt;/p&gt;&lt;p align="left"&gt;So to repeat, the Java code just contains wrapper code that you will rarely need to change, since all the game&amp;rsquo;s logic will be inside the C++ code.&lt;/p&gt;&lt;p align="left"&gt;&lt;strong&gt;连接&lt;/strong&gt;&lt;strong&gt;andriod&lt;/strong&gt;&lt;strong&gt;和&lt;/strong&gt;&lt;strong&gt;ios&lt;/strong&gt;&lt;strong&gt;项&lt;/strong&gt;&lt;strong&gt;目&lt;/strong&gt;&lt;strong&gt;结&lt;/strong&gt;&lt;strong&gt;构&lt;/strong&gt;&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 现在，我们有两个cocos2d-x的项目了，一个是ios下面的，一个是andriod下面的。我们的目标是让两个工程共享同样的目录，这样就可以使用同样的c++文件了。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我们两个项目里面，都有一个文件夹叫做&amp;ldquo;Classes&amp;rdquo;，它包含了我们的可移植的游戏代码（如下图：android的在左边，ios的在右边）&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042714235197.png" alt="" /&gt;&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;如果你仔细看看eclipse和xcode里面的Classes目录，你会发现这些c++文件完全相等。因此，我们需要做的就是让两个项目指向同一个文件夹就ok了！&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 为了实现这个目标，在xcode里面打开Cocos2DxFirstIosSample项目。选择Classes分组，然后点击Delete，选择&amp;ldquo;Move to Trash&amp;rdquo;；&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 接下来，右键Project Navigator，选择&amp;ldquo;New Group&amp;rdquo;，然后重命名为Classes。点键Classes，点击Add Files。然后选择$PROJECT_HOME\Classes目录，同时确保&amp;ldquo;&lt;em&gt;Copy items into destination group&amp;rsquo;s folder&lt;/em&gt;&amp;rdquo;没有被选中！&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042714242230.png" alt="" /&gt;&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;然后clean并rebuild xcode项目，并运行一下，确保一切ok。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp; 恭喜，现在基础配置全部弄好了！你可以试着在eclipse里面修改，xcode这边运行，或者xcode里面修改，eclipse里面运行了。&lt;/p&gt;&lt;p align="left"&gt;&lt;strong&gt;什么&lt;/strong&gt;&lt;strong&gt;时&lt;/strong&gt;&lt;strong&gt;候使用&lt;/strong&gt;&lt;strong&gt; Xcode, &lt;/strong&gt;&lt;strong&gt;什么&lt;/strong&gt;&lt;strong&gt;时&lt;/strong&gt;&lt;strong&gt;候使用&lt;/strong&gt;&lt;strong&gt;Eclipse?&lt;/strong&gt;&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 现在，你有两个项目了，那么问题马上就出来了，我们到底什么时候该使用哪一个呢？&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 使用cocos2d-x通常的开发策略是，首先在ios上面通过xcode来测试，确认没问题后，再通过eclipse来测试。只需要在心里记住下面几点就行：&lt;/p&gt;&lt;ol start="1"&gt;&lt;li&gt;经常测试&lt;em&gt;.&lt;/em&gt;&lt;em&gt;开&lt;/em&gt;&lt;em&gt;发&lt;/em&gt;&lt;em&gt;完一个小功能之后，就&lt;/em&gt;&lt;em&gt;应该&lt;/em&gt;&lt;em&gt;在&lt;/em&gt;&lt;em&gt;andriod上面&lt;/em&gt;&lt;em&gt;测试&lt;/em&gt;&lt;em&gt;看行不行。&lt;/em&gt;&lt;em&gt;这样&lt;/em&gt;&lt;em&gt;的&lt;/em&gt;&lt;em&gt;话&lt;/em&gt;&lt;em&gt;，就不至于遇到&lt;/em&gt;&lt;em&gt;问题&lt;/em&gt;&lt;em&gt;找不到了。&lt;/em&gt;&amp;nbsp;&lt;/li&gt;&lt;li&gt;&lt;em&gt;在多个&lt;/em&gt;&lt;em&gt;设备&lt;/em&gt;&lt;em&gt;上面&lt;/em&gt;&lt;em&gt;测试&lt;/em&gt;: 现在市场上面有大量的android设备，而且它们的差别很细微，所以，你要尽可能多地测试多种不同型号的设备。&lt;/li&gt;&lt;/ol&gt;&lt;p align="left"&gt;当然，你也可以先在andriod上面测试，然后再在ios上面测试。但是这样肯定会降低你的生产率。因为xcode比eclipse反应速度更快，而ios模拟器比android的模拟器的启动速度也要快一些。&lt;/p&gt;&lt;p align="left"&gt;&lt;strong&gt;调试&lt;/strong&gt;&lt;strong&gt;技巧&lt;/strong&gt;&lt;/p&gt;&lt;p align="left"&gt;在ios上面调试cocos2d-x和cocos2d的方法差不多，这里也没什么多讲的。&lt;/p&gt;&lt;p align="left"&gt;然而，对于Android，这里有几点需要注意下。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp; 当使用NDK来调试的时候，一个&amp;ldquo;服务端的&amp;rdquo;gdb和gdbcontext被ndk-build shell脚本塞到APk里面去了。这个远程的gdb调试器可以与任何gdb兼容的客户端进行通信。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp; Eclipse里面最好的gdb agent就是&amp;nbsp;&lt;a href="http://developer.nvidia.com/nvidia-debug-manager-android-ndk"&gt;NVidia debug manager plugin&lt;/a&gt;，但是安装这个插件不在本教程的讨论范围之内。&lt;/p&gt;&lt;p align="left"&gt;注意: 如果你想安装NVidia Debug Manager plugin,你首先到&lt;a href="http://developer.nvidia.com/tegra-resources#tools"&gt;这个页面&lt;/a&gt;下载完整的Tegra Android开发包，即便你可能现在并不需要它。然后，安装Tegra Developer，它会提示你安装哪些项，然后你可以选择NVidia Debug Manager plugin这个插件了。当你安装完之后，它并没有包插件安装到eclipse里面去，而是把zip文件放在你的硬盘的某个位置，你可以参考这个&lt;a href="http://www.google.com/url?sa=t&amp;amp;rct=j&amp;amp;q=&amp;amp;esrc=s&amp;amp;source=web&amp;amp;cd=1&amp;amp;ved=0CCgQFjAA&amp;amp;url=http%3A%2F%2Fdeveloper.download.nvidia.com%2Ftegra%2Fdocs%2FNVDebugMgrForAndroidNDK-InstallGuide_20110228.pdf&amp;amp;ei=dAdxT4TJE8_prQfxuoXGDQ&amp;amp;usg=AFQjCNECgf1HdSVs4UwXMESuJQOmGLQJMA&amp;amp;sig2=X4P_gpOGndmfIYIeY88JWg"&gt;pdf文档&lt;/a&gt;来进行安装。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我发现在一些物理设备（比如Samsumg Galaxy S），remote debugger老是启动不了，但是使用AVD就可以正常启动。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp; 为了启动一个debug会话，你可以选择你的项目，然后右击Debug As Android NDK application，如下图所示：&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042714260913.png" alt="" /&gt;&lt;/p&gt;&lt;p align="left"&gt;请注意，只有你安装了NVidia debug manager plugin，你才会在右击的时候看到&lt;em&gt;Android NDK Application&lt;/em&gt;&lt;em&gt;这个选项。&lt;/em&gt;&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp; 你可以在一行代码上面双击来设置一个断点，如下所示：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042714280867.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;当断点到达的时候，它将会停留在断点所在行：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012042714291779.png" alt="" /&gt;&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;悲催的是，使用gdb来调试android有时候并不管用，所以，你可能需要添加一些额外的tracing系统。想知道更多的信息，请联系我，我将与大家分享这些tips。&lt;/p&gt;&lt;p align="left"&gt;&lt;strong&gt;何去何从&lt;/strong&gt;&lt;strong&gt;?&lt;/strong&gt;&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 恭喜你，你现在可以使用cocos2d-x来开发iphone和android下面的游戏了。&lt;/p&gt;&lt;p align="left"&gt;&amp;nbsp;&amp;nbsp; 请耐心等待我的第二篇教程吧，它将带你一起开发一个跨平台的太空射击游戏，当然是使用cocos2d-x啦！&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 如果你遇到什么问题，或者有什么意见或建议，欢迎留言！&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp;更多精彩教程，请关注&lt;a href="http://article.ityran.com/" target="_blank"&gt;泰然首页&lt;/a&gt;：）&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/zilongshanren/aggbug/2473282.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/zilongshanren/archive/2012/04/28/2473282.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2390111.html</id><title type="text">cocos2d里面如何实现MVC（完）</title><summary type="text">今天我们讨论的主题是Model-View-Controller (MVC)设计模式，以及如何在cocos2d里面实现它。来自波兰的Bartek Wilczyński写了一系列的文章来介绍这个模式，同时说明了为什么要使用mvc，以及如何在cocos2d里面使用mvc。 这个波兰人写的文章已经被我全部翻译过来了，请点击传送门查看。 当我在读他写的这些文章的时候，我记得Jeremy Flores在github上面有一个cocos2d里面实现mvc的版本库。他把它取名为Cocos2D-MNC，全名是Model-Node-Controller。并且代码是开源的，MIT许可。 这个MVC模式和游...</summary><published>2012-03-18T13:29:00Z</published><updated>2012-03-18T13:29:00Z</updated><author><name>子龙山人</name><uri>http://www.cnblogs.com/zilongshanren/</uri></author><link rel="alternate" href="http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2390111.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2390111.html"/><content type="html">&lt;p&gt;&amp;nbsp; &amp;nbsp; 今天我们讨论的主题是&lt;a href="http://en.wikipedia.org/wiki/Model%E2%80%93View%E2%80%93Controller"&gt;Model-View-Controller (MVC)&lt;/a&gt;设计模式，以及如何在cocos2d里面实现它。来自波兰的Bartek Wilczyński写了一系列的文章来介绍这个模式，同时说明了为什么要使用mvc，以及如何在cocos2d里面使用mvc。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 这个波兰人写的文章已经被我全部翻译过来了，请点击&lt;a href="http://www.cnblogs.com/andyque/archive/2012/03/11/2390814.html" target="_blank"&gt;传送门&lt;/a&gt;查看。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 当我在读他写的这些文章的时候，我记得Jeremy Flores在github上面有一个cocos2d里面实现mvc的版本库。他把它取名为&lt;a href="https://github.com/jeremyflores/cocosMNC/"&gt;Cocos2D-MNC&lt;/a&gt;，全名是Model-Node-Controller。并且代码是开源的，MIT许可。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 这个MVC模式和游戏实体组件系统差不多，我在&lt;a href="http://www.learn-cocos2d.com/2010/06/prefer-composition-inheritance/" target="_blank"&gt;这篇文章&lt;/a&gt;里面就有介绍过了。对于这两个系统来说，它的思想都是统一的，那就是不要继承CCSprite并把游戏logic全部塞到sprite里面去。CCSprite应该只负责渲染显示。而且有时候，你可能需要创建很多sprite，我们最好是创建一个CCNode类，然后里面聚合许多sprites。这样CCNode成为了Controller，控制view。当view（比如sprite，effect，gL drawings等等）在屏幕上面移动的时候，controller结点会轮询所有它包含的结点来查询一些游戏相关的状态信息，并且做一些游戏逻辑，然后反过来再更新view。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 对于小游戏来说，mvc模式确实可以运行地很好。它比起直接继承CCSprite，并把一大堆处理逻辑放到CCSprite里面要强多了。如果你发现，你还是不停地继承ccsprite，然后把一大堆处理逻辑塞到一个ccsprite的子类里面，那么你就应该考虑一下mvc设计模式了。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;当我们在cocos2d论坛里面提到&amp;ldquo;&lt;a href="http://www.cocos2d-iphone.org/forum/topic/6621" target="_blank"&gt;是否继承CCSprite还是使用一些model类来构建你的游戏对象结构&lt;/a&gt;？&amp;rdquo;这样的问题的时候，我还是要再强调一点，多用组合，少用继承！如果一味地使用继承，那么当游戏世界里面的对象种类变多，功能变复杂以后，会导致整个继承树&amp;ldquo;头重脚轻&amp;rdquo;，严重破坏了良好的面向对象设计原则---我们设计的类层次结构应该是扁平结构的，而不是一个头很大的树。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 那么，我们需要使用怎样的架构来处理游戏里面的对象呢？答案就是使用组合。现在已经有一些非常好的引擎，比如&lt;a href="http://www.torquepowered.com/products/torquex-3d"&gt;TorqueX&lt;/a&gt;、&lt;a href="http://pushbuttonengine.com/"&gt;PushButton Engine&lt;/a&gt;、Unity3D等，它们都是基于组合的实体组件系统。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 你可以从&lt;a href="http://pushbuttonengine.com/docs/04-Components.html"&gt;PushButton的文档&lt;/a&gt;里面得到有关实体组件系统的介绍。同时，可以读一读《&lt;a href="http://docs.torquepowered.com/torquex/official/content/documentation/TorqueX%20Core/Concepts/Component%20System.html"&gt;Components in TorqueX and what the differences are to XNA Game Components&lt;/a&gt;》这篇文章来加深对实体组件系统的理解。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;你还可以从&lt;a href="http://en.wikipedia.org/wiki/Component-based_software_engineering"&gt;维基百科&lt;/a&gt;上获得更多的信息。实际上，objc语言本身就是被设计为一种可重用的软件组件。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;Scott Bilas在2002的GDC大会上提出了一种&lt;a href="http://scottbilas.com/files/2002/gdc_san_jose/game_objects_slides_with_notes.pdf" target="_blank"&gt;基于数据驱动的游戏对象系统&lt;/a&gt;，同时&lt;a href="http://www.gaspowered.com/dsuniverse/"&gt;Dungeon Siege&lt;/a&gt;使用了这个新理念，它指出了为什么继承对于游戏开发者来说非常不好，还说明了基于对象组合的组件系统的优点。事实上，在2002年，我开始与&lt;a href="http://store.steampowered.com/app/39540/"&gt;SpellForce&lt;/a&gt;一起工作的时候，我们已经有一个组件系统了，我们把它叫做Aspects、Abilities和Spells。它可以帮助我们把所有的游戏数据都存储到数据库里面，程序员只需要写一些泛型代码来统一处理这些数据就行了。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 在2009年的GDC大会上面，Radical Entertainment&amp;rsquo;s Marcin Chady也做了一个类似的ppt，大家可以&lt;a href="http://cmpmedia.vo.llnwd.net/o1/vault/gdccanada09/slides/marcinchadyGDCCanada.ppt" target="_blank"&gt;点此查看&lt;/a&gt;。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;Mick West还写了一篇文章，《&lt;a href="http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/" target="_blank"&gt;重构游戏实体为游戏组件&lt;/a&gt;》，在这篇文章里面，它很好地描述了，为什么要更改以前的继承模型，转而投向组件系统的怀抱。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 还有一些更高级的读物，比如一些paper《&lt;a href="http://www.josericardojunior.com/docs/DGOCSMBC_SBG08_1.pdf"&gt;Dynamic Game Object Component System for Mutable Behavior Characters&lt;/a&gt;》 ，它基于&lt;a href="http://en.wikipedia.org/wiki/Finite_state_machine"&gt;finite state machines&lt;/a&gt;讨论了组件系统，而且引入了基于规则的NPC行为系统。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp;在Game Architect 博客里面把它称之为&lt;a href="http://gamearchitect.net/2008/06/01/an-anatomy-of-despair-aggregation-over-inheritance/"&gt;Anatomy of Despair&lt;/a&gt;，并且指出了基于继承的类设计的一些缺点，同时展示了使用组合如何来解决这些问题。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp; 后记：《如何在cocos2d里面实现mvc》这一系统的文章到此就全部结束了，非常感谢大家的耐心阅读。mvc在cocoa开发中被广泛使用，几乎没有哪一个ios开发者不知道mvc。但是，mvc不是银弹，没有银弹！我个人觉得基于组件的实体系统和fsm更适合现在游戏架构。由于本人水平和经验有限，故只能翻译这么多。这篇博文提到了其它许多没有翻译过的文章，建议大家都读一读。我也不打算翻译了。有兴趣的同学可以翻译出来，为开发者社区贡献一点力量。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp;全剧终！&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;参考文献：&lt;/p&gt;&lt;p&gt;&lt;a href="http://gameprogrammingpatterns.com/component.html"&gt;Game Programming Patterns / Behaving Patterns / Component&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://xperienced.com.pl/blog/how-to-implement-mvc-pattern-in-cocos2d-game"&gt;How to implement MVC pattern in cocos2d game | XPerienced Blog&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://t-machine.org/index.php/2010/05/09/entity-system-1-javaandroid/"&gt;T=Machine &amp;raquo; Entity System 1: Java/Android&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/"&gt;T=Machine &amp;raquo; Entity Systems are the future of MMOG development &amp;ndash; Part 1&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://xperienced.com.pl/blog/how-to-implement-mvc-pattern-in-cocos2d-gamepart-2"&gt;How to implement MVC pattern in cocos2d game&amp;ndash;part 2 | XPerienced Blog&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://gamesfromwithin.com/"&gt;Games from Within| Indie iPhone game development&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://gameprogrammingpatterns.com/"&gt;Game Programming Patterns&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.poddcorp.com/2010/11/17/using-design-patterns-in-game-development/"&gt;Game development |&lt;/a&gt;&lt;a href="http://www.poddcorp.com/2010/11/17/using-design-patterns-in-game-development/"&gt;Mobile development |&lt;/a&gt;&lt;a href="http://www.poddcorp.com/2010/11/17/using-design-patterns-in-game-development/"&gt;PODD&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/"&gt;Cowboy Programming &amp;raquo; Evolve Your Hierarchy&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://gbgames.com/blog/2006/03/object-oriented-game-design/"&gt;Object-Oriented Game Design&lt;/a&gt;&lt;a href="http://gbgames.com/blog/2006/03/object-oriented-game-design/"&gt;| GBGames - Thoughts on Indie Game Development&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://deadpanic.com/mvc_for_games"&gt;Why Use MVC for Games? A Q&amp;amp;A Session | Dead&lt;/a&gt;&lt;a href="http://deadpanic.com/mvc_for_games"&gt;Panic&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.willrmiller.com/?p=73"&gt;C Coroutines for Game Entity State Management | Will's Blog&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://aigamedev.com/open/articles/fsm-age-is-over/"&gt;10 Reasons the Age of Finite State Machines is Over &amp;mdash; AiGameDev.com&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cocos2d-iphone.org/forum/topic/6621"&gt;Subclass CCSprite vs Model Class. Best Practice? &amp;laquo; cocos2d for iPhone&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cocos2d-iphone.org/forum/topic/12752#post-71778"&gt;Animating a CCSprite using MVC design &amp;laquo; cocos2d for iPhone&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cocos2d-iphone.org/forum/topic/12752"&gt;Animating a CCSprite using MVC design &amp;laquo; cocos2d for iPhone&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cocos2d-iphone.org/forum/topic/12494"&gt;Subclassing CCNode and using CCSpriteBatchNode properly &amp;laquo; cocos2d for iPhone&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cocos2d-iphone.org/forum/topic/195"&gt;Component based entity systems &amp;laquo; cocos2d for iPhone&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cocos2d-iphone.org/forum/topic/8683"&gt;How do you organize your code? &amp;laquo; cocos2d for iPhone&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://gamearchitect.net/Articles/GameObjects1.html"&gt;Game Object Structure: Inheritance vs. Aggregation&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://forums.create.msdn.com/forums/p/19077/101646.aspx"&gt;Game Architecture Best Patterns and Practices - App Hub Forums&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://kwigbo.com/post/958879024/finite-state-machine-part-1"&gt;Finite State Machine Part 1&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://gamedev.stackexchange.com/questions/4157/what-are-some-programming-design-patterns-that-are-useful-in-game-development"&gt;c++ - What are some programming design patterns that are useful in game development? - Game Development - Stack Exchange&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/5546711/how-to-write-solid-pure-aggregation-composition-game-objects-in-java"&gt;How to write solid Pure Aggregation (composition) Game Objects in Java? - Stack Overflow&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.learn-cocos2d.com/2010/06/prefer-composition-inheritance/"&gt;Prefer Composition over Inheritance | Learn &amp;amp; Master Cocos2D Game Development&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.bigbadrobots.com/?p=85"&gt;Components, Draw Calls and performance&amp;hellip;. &amp;laquo; Big Bad Robots Indie Game Studio&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.bigbadrobots.com/?p=78"&gt;To Components with Cocos2D with love&amp;hellip; &amp;laquo; Big Bad Robots Indie Game Studio&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://pushbuttonengine.com/"&gt;PushButton Engine&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://pushbuttonengine.com/v2/docs/PBEDemos.html"&gt;PBEDemos.as&lt;/a&gt;&lt;a href="http://gamadu.com/artemis/"&gt;Artemis&lt;/a&gt;&lt;a href="http://gamadu.com/artemis/"&gt;&amp;nbsp;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://gamadu.com/artemis/"&gt;Entity System Framework&lt;/a&gt;&lt;a href="http://t-machine.org/index.php/2010/12/30/entity-system-1-objective-c/"&gt;T=Machine &amp;raquo; Entity System 1: Objective-C&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/1901251/component-based-game-engine-design"&gt;architecture - Component based game engine design - Stack Overflow&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.purplepwny.com/blog/?p=215"&gt;Component Based Entity System Design Part 1 | Purple Pwny Games&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://gamedev.stackexchange.com/questions/4637/component-based-game-object-systems-in-practice"&gt;Component-based game object systems in practice - Game Development - Stack Exchange&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/1028250/what-is-functional-reactive-programming"&gt;What is (functional) reactive programming? - Stack Overflow&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://lambdor.net/?p=171"&gt;Why I switched from component-based game engine architecture to functional reactive programming &amp;ndash; Lambdor Devblog by Gerold Meisinger&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://lambdor.net/?p=4"&gt;Quickstarting game development in Haskell and Ubuntu &amp;ndash; Lambdor Devblog by Gerold Meisinger&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.mcshaffry.com/GameCode/thread.php?threadid=732"&gt;Game Coding Complete - Component System Example Code (from GPG6)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/2640630/obj-c-component-based-game-architecture-and-message-forwarding"&gt;objective c - Obj-C component-based game architecture and message forwarding - Stack Overflow&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.mikeash.com/pyblog/friday-qa-2009-03-27-objective-c-message-forwarding.html"&gt;mikeash.com: Friday Q&amp;amp;A 2009-03-27: Objective-C Message Forwarding&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.oddrosemedia.com/wiki/index.php?title=Articles"&gt;Articles - Component Based Objects&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.unseen-academy.de/snippet_component_system.html"&gt;Unseen-Academy - Component System&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://games.fh-hagenberg.at/wiki/index.php?title=Componentbased_entity_systems"&gt;Componentbased entity systems - Game Development Lab Wiki&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="https://github.com/divotkey/cogaen3-java"&gt;divotkey/cogaen3-java - GitHub&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://gamedev.stackexchange.com/questions/9588/open-source-component-based-game-or-engines"&gt;Open source component-based game or engines? - Game Development - Stack Exchange&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.purplepwny.com/blog/?p=290"&gt;Component Based Entity System Design Part 2 | Purple Pwny Games&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://game.techweb.com.cn/thread-234669-1-1.html"&gt;一个基于组件的动态对象系统 - 游戏创意和设计 - TechWeb-游戏社区&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://blog.chinaunix.net/space.php?uid=293474&amp;amp;do=blog&amp;amp;id=2134103"&gt;游戏对象的实现 (补)_thunder54007-ChinaUnix博客&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cppblog.com/flashboy/archive/2009/07/29/91635.html"&gt;游戏对象的实现 - 组件工厂 - C++博客&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="https://github.com/thelinuxlich/artemis_CSharp"&gt;thelinuxlich/artemis_CSharp - GitHub&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="https://github.com/thelinuxlich/starwarrior_CSharp"&gt;thelinuxlich/starwarrior_CSharp - GitHub&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/51786/recommended-eclipse-plugins-to-generate-uml-from-java-code"&gt;Recommended Eclipse plugins to generate UML from Java code - Stack Overflow&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.gamearchitect.net/Articles/GameObjects1.html"&gt;Game Object Structure: Inheritance vs. Aggregation&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.learn-cocos2d.com/2010/12/linkvent-calendar-day-3-mvc-cocos2d/"&gt;Linkvent Calendar, Day 3: MVC with Cocos2D | Learn &amp;amp; Master Cocos2D Game Development&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://ploobs.com.br/?p=1765"&gt;Artemis Entity Framework Ported to C# | Ploobs&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://code.google.com/p/cistron/downloads/list"&gt;Downloads - cistron - A component-based programming framework targeted at game development. - Google Project Hosting&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.gamedev.net/blog/1390/entry-2254064-c-port-of-artemis-entity-component-system-framework-in-progress/"&gt;C++ Port of Artemis Entity Component System Framework (In Progress) - GameDev.net&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/zilongshanren/aggbug/2390111.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2390111.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2390109.html</id><title type="text">cocos2d里面如何实现MVC（六）</title><summary type="text">本文将会比较简短。如果你对于前面几篇介绍cocos2d里面如何实现mvc有什么不清楚的地方，请跟我讲，这样我就可以补充地更详细一点。我（原作者）最近接了一些非常大的外包项目，所以，用来写博客的时间不是很多。在此，我简单地总结一下前面写的这些文章：我们实现了Model，它可以帮助我们封装游戏的逻辑，这样可以使我们的关注点集中于游戏逻辑，而不是其它的（比如渲染）我们实现了Controller来处理用户交互，同时相应地更新model。我们实现了View，而它的职责仅仅是负责显示model的状态。它们三者之间的交互关系如下:Controller负责初始化Model和ViewView负责显示Mode..</summary><published>2012-03-18T12:44:00Z</published><updated>2012-03-18T12:44:00Z</updated><author><name>子龙山人</name><uri>http://www.cnblogs.com/zilongshanren/</uri></author><link rel="alternate" href="http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2390109.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2390109.html"/><content type="html">&lt;p&gt;&amp;nbsp; &amp;nbsp; 本文将会比较简短。如果你对于前面几篇介绍cocos2d里面如何实现mvc有什么不清楚的地方，请跟我讲，这样我就可以补充地更详细一点。我（原作者）最近接了一些非常大的外包项目，所以，用来写博客的时间不是很多。在此，我简单地总结一下前面写的这些文章：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;我们实现了Model，它可以帮助我们封装游戏的逻辑，这样可以使我们的关注点集中于游戏逻辑，而不是其它的（比如渲染）&lt;/li&gt;&lt;li&gt;我们实现了Controller来处理用户交互，同时相应地更新model。&lt;/li&gt;&lt;li&gt;我们实现了View，而它的职责仅仅是负责显示model的状态。&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;它们三者之间的交互关系如下:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Controller负责初始化Model和View&lt;/li&gt;&lt;li&gt;View负责显示Model&amp;nbsp;&lt;/li&gt;&lt;li&gt;View负责接收用户touch事件，然后传递给controller来处理。&lt;/li&gt;&lt;li&gt;Controller实现view的代理，同时可以操作Model。&lt;/li&gt;&lt;li&gt;model则执行一些游戏逻辑处理并通知view它的状态改变。&lt;/li&gt;&lt;li&gt;View根据model的当前状态来更新它里面的所有对象，比如精灵。&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;留几个开放性的问题:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;如果你想使用NSUodoManager来实现&amp;ldquo;撤销&amp;rdquo;功能，你会把该功能放在哪里呢？Model？Controller？View？&lt;/li&gt;&lt;li&gt;你会怎么保存当前场景的状态信息呢？&lt;/li&gt;&lt;li&gt;或者你还可以补充其它问题?&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;后记：本文已同步更新到&lt;a href="http://www.cnblogs.com/andyque/archive/2012/03/11/2390814.html" target="_blank"&gt;cocos2d mvc这个系列&lt;/a&gt;里面去了。&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 如果你觉得本文章对你有所帮助，请您点一下旁边的&amp;ldquo;推荐&amp;rdquo;按钮，这样可以让更多的人看到，同时也会给我写作的动力，谢谢大家。&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/zilongshanren/aggbug/2390109.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2390109.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2390106.html</id><title type="text">cocos2d里面如何实现MVC（五）</title><summary type="text">本文基于前面两篇文章，如果您还没有看过，建议先阅读下面两篇文章：cocos2d里面如何实现mvc（三）,cocos2d里面如何实现mvc（四）更新Model 当用户从工具箱中选一个小工具，然后把它放置到game board上面去时，我们需要编码响应这些事件。在上一篇文章中，我们已经实现了GameBoardViewDelegate的touchedAtRow方法。我们还需要给这个协议再添加一个接口方法。如下所示：@protocol GameBoardViewDelegate - (void)gameBoard:(GameBoard *)gameBoard touchedAtRow:(int)...</summary><published>2012-03-18T12:30:00Z</published><updated>2012-03-18T12:30:00Z</updated><author><name>子龙山人</name><uri>http://www.cnblogs.com/zilongshanren/</uri></author><link rel="alternate" href="http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2390106.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2390106.html"/><content type="html">&lt;p&gt;&amp;nbsp; &amp;nbsp; 本文基于前面两篇文章，如果您还没有看过，建议先阅读下面两篇文章：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.cnblogs.com/andyque/archive/2012/03/18/2390100.html"&gt;cocos2d里面如何实现mvc（三）,&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.cnblogs.com/andyque/archive/2012/03/18/2390102.html"&gt;cocos2d里面如何实现mvc（四）&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;更新Model&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 当用户从工具箱中选一个小工具，然后把它放置到game board上面去时，我们需要编码响应这些事件。在上一篇文章中，我们已经实现了&lt;em&gt;GameBoardViewDelegate的&lt;/em&gt;&lt;em&gt;touchedAtRow方法。我们还需要给这个协议再添加一个接口方法。如下所示：&lt;/em&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@protocol GameBoardViewDelegate&lt;br /&gt; &lt;br /&gt;- (&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)gameBoard:(GameBoard *)gameBoard touchedAtRow:(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;)row column:(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;)column;&lt;br /&gt;- (&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)gameBoard:(GameBoard *)gameBoard toolboxItemTouchedAtIndex:(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;)index;&lt;br /&gt; &lt;br /&gt;@end&lt;/div&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; 我们需要修改touch事件处理器，这样就可以判断我们到底是触摸了工具箱还是game board。&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;- (&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)&lt;span style="color: #0000ff;"&gt;event&lt;/span&gt; {&lt;br /&gt;    UITouch *touch = [touches anyObject];&lt;br /&gt;    CGPoint point = [self convertTouchToNodeSpace:touch];&lt;br /&gt; &lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; touched on a game board&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (CGRectContainsPoint(gameBoardRectangle, point)) {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; row, column;&lt;br /&gt;        &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; calculate row and column based on a touch coordinate&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; ...&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; call controller&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;        [self.&lt;span style="color: #0000ff;"&gt;delegate&lt;/span&gt; gameBoard:self.gameBoard touchedAtRow:row column:column];&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; touched on a toolbox&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    &lt;span style="color: #0000ff;"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (CGRectContainsPoint(toolboxRectangle, point)) {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; index;&lt;br /&gt;        &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; calculate toolbox item index based on a touch coordinate&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;        [self.&lt;span style="color: #0000ff;"&gt;delegate&lt;/span&gt; gameBoard:self.gameBoard toolboxItemTouchedAtIndex:index];&lt;br /&gt;    }&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; 在controller类里面处理touch事件是非常简单的，我们只需要持有一个model的引用，然后基于touch事件来调用model的方法就行了。我们的接口看起来和下面差不多，只是省略掉了一些实现细节：&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@interface GameBoard : NSObject {&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; ...&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;}&lt;br /&gt; &lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; ...&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;- (&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)putGamePiece:(GamePiece *)gamePiece row:(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;)row column:(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;)column;&lt;br /&gt;- (GamePiece *)getGamePieceFromToolboxItemAtIndex:(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;)index;&lt;br /&gt;@end&lt;/div&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; 然后，我们在GameBoardController里面完全实现GameBoardViewDelegate的两个方法。&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;- (&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)gameBoard:(GameBoard *)aGameBoard toolboxItemTouchedAtIndex:(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;)index {&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; keep the toolbox selection state in the Model&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    gameBoard.selectedToolboxItemIndex = index;&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;- (&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)gameBoard:(GameBoard *)aGameBoard touchedAtRow:(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;)row column:(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;)column {&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; if the toolbox item is selected move item from toolbox to game board&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (gameBoard.selectedToolboxItemIndex != -&lt;span style="color: #800080;"&gt;1&lt;/span&gt;) {&lt;br /&gt;        GamePiece *gamePiece = [gameBoard getGamePieceFromToolboxItemAtIndex:gameBoard.selectedToolboxItemIndex];&lt;br /&gt;        [gameBoard putGamePiece:gamePiece row:row column:column];&lt;br /&gt;    }&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 到目前为止，我们实现了，用户可以点击工具箱中的小工具，然后把它们放置到game board中的一个小方块上面，同时model类在中间起了桥梁作用。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;通知view关于model的改变&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 为了在view里面反映出model的状态更改，我们可以在model有变化的时候给view发送通知消息，然后view就可以根据不同的消息来作出不同的响应了。和我们在实现view通过controller一样，这里我们也定义了一个GameBoardDelegate，用来通知view model的变化。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@protocol GameBoardDelegate;&lt;br /&gt;@interface GameBoard : NSObject&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; ...&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;@property (nonatomic, assign)&lt;br /&gt;id&amp;amp;lt;GameBoardDelegate&amp;amp;gt; &lt;span style="color: #0000ff;"&gt;delegate&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; ...&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;@end&lt;br /&gt; &lt;br /&gt;@protocol GameBoardDelegate&lt;br /&gt;- (&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)gameBoard:(GameBoard *)gameBoard didPutGamePiece:(GamePiece *)gamePiece row:(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;)row column:(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;)column;&lt;br /&gt;@end&lt;br /&gt; &lt;br /&gt;@implementation GameBoard&lt;br /&gt; &lt;br /&gt;- (&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)putGamePiece:(GamePiece *)gamePiece row:(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;)row column:(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;)column {&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; ...&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; store game piece&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; notify that the game piece was put on a gameboard&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    [&lt;span style="color: #0000ff;"&gt;delegate&lt;/span&gt; gameBoard:self didPutGamePiece:gamePiece row:row column:column];&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;@end&lt;/div&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; 在GameBoardView里面实现GameBoardDelegate的时候，当我们需要在game board上面放置一个小工具的时候，我们定义了一个CCSprite。&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@interface GameBoardView : CCLayer&lt;br /&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; ...&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;@end&lt;br /&gt; &lt;br /&gt;@implementation GameBoardView&lt;br /&gt; &lt;br /&gt;- (id)initWithGameBoard:(GameBoard *)aGameBoard &lt;span style="color: #0000ff;"&gt;delegate&lt;/span&gt;:(id)aDelegate {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; ((self = [super init])) {&lt;br /&gt;        &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; retain gameboard&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;        self.gameBoard = aGameBoard;&lt;br /&gt;        self.gameBoard.&lt;span style="color: #0000ff;"&gt;delegate&lt;/span&gt; = self;&lt;br /&gt; &lt;br /&gt;        &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; assign delegate&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;        self.&lt;span style="color: #0000ff;"&gt;delegate&lt;/span&gt; = aDelegate;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;- (&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)gameBoard:(GameBoard *)gameBoard didPutGamePiece:(GamePiece *)gamePiece row:(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;)row column:(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;)column {&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; create CCSprite and put it on a game board at corresponding position&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    CCSprite *gamePieceSprite = [CCSprite spriteWithFile:fileName];&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; ...&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    [self addChild:gamePieceSprite];&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;@end&lt;/div&gt;&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 现在框架中所有的部分都联系起来了，model、view和controller三者组成了著名的MVC模式&lt;/p&gt;&lt;ul&gt;&lt;li&gt;View接收touch事件，然后把事件传递给controller,&lt;/li&gt;&lt;li&gt;Controller 响应用户的touch事件，然后更新model&lt;/li&gt;&lt;li&gt;model 更新它自身的状态, 处理游戏逻辑，然后告诉view它改变了哪些东西。&lt;/li&gt;&lt;li&gt;View则基于Model当前的状态来更新自己的显示&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;后记：本文已同步更新到&lt;a href="http://www.cnblogs.com/andyque/archive/2012/03/11/2390814.html" target="_blank"&gt;cocos2d mvc这个系列&lt;/a&gt;里面去了。&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 如果你觉得本文章对你有所帮助，请您点一下旁边的&amp;ldquo;推荐&amp;rdquo;按钮，这样可以让更多的人看到，同时也会给我写作的动力，谢谢大家。&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/zilongshanren/aggbug/2390106.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2390106.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2390102.html</id><title type="text">cocos2d里面如何实现MVC（四）</title><summary type="text">在上一篇文章中，我们使用cocos2d基于mvc做了一个简单了游戏架子，这个架子还非常简单，还有许多东西有待实现。介绍模型 在上一篇博文中，我们介绍了view和controller。为了实现mvc模式，我们还需要添加一个model类来维护游戏的状态。我们的实现应该要包含下列这些类：GameBoardView- 也就是View,GameBoardController- 也就是Controller.GameBoard – 也就是Model.Model 实现GameBoard 实现 我们在第一部分所描述的需求是这样子的: 。。。一个game board是通过n行n列组成的，它会随着游戏难度...</summary><published>2012-03-18T11:59:00Z</published><updated>2012-03-18T11:59:00Z</updated><author><name>子龙山人</name><uri>http://www.cnblogs.com/zilongshanren/</uri></author><link rel="alternate" href="http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2390102.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2390102.html"/><content type="html">&lt;p&gt;&amp;nbsp; &amp;nbsp; 在&lt;a href="http://www.cnblogs.com/andyque/archive/2012/03/18/2390100.html" target="_blank"&gt;上一篇文章&lt;/a&gt;中，我们使用cocos2d基于mvc做了一个简单了游戏架子，这个架子还非常简单，还有许多东西有待实现。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;介绍模型&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 在上一篇博文中，我们介绍了view和controller。为了实现mvc模式，我们还需要添加一个model类来维护游戏的状态。我们的实现应该要包含下列这些类：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;em&gt;GameBoardView&lt;/em&gt;&amp;nbsp;- 也就是View,&lt;/li&gt;&lt;li&gt;&lt;em&gt;GameBoardController&lt;/em&gt;&amp;nbsp;- 也就是Controller.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;GameBoard &amp;ndash; 也就是Model.&lt;/strong&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012031114072069.jpg" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Model 实现&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;GameBoard 实现&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 我们在第一部分所描述的需求是这样子的:&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 。。。一个game board是通过n行n列组成的，它会随着游戏难度有所变化。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 因此，我们按照下面的编码方式来实现之:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@interface GameBoard : NSObject {&lt;br /&gt;    NSInteger numberOfRows;&lt;br /&gt;    NSInteger numberOfColumns;&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;- (id)initWithRows:(NSInteger)aNumberOfRows columns:(NSInteger)aNumberOfColumns;&lt;br /&gt; &lt;br /&gt;@property (nonatomic) NSInteger numberOfRows;&lt;br /&gt;@property (nonatomic) NSInteger numberOfColumns;&lt;br /&gt; &lt;br /&gt;@end&lt;/div&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 请注意，model是从NSObject继承过来的---因为model只需要关注game board的状态就行了（当然，还有相应的更新状态的方法）---我们不应该把其它东西也放进来，比如继承到CCNode就不行，我们并不需要CCNode的东西，所以，为了纯粹性，我们这里继承到game board。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;GameBoardView 的实现&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 我们现在需要修改View，同时它包含一个model的引用，我们可以通过initWithGameBoard方法来初始化这个成员变量：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@interface GameBoardView : CCNode {&lt;br /&gt;    GameBoard *gameBoard;&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;@property (nonatomic, retain) GameBoard *gameBoard;&lt;br /&gt; &lt;br /&gt;- (id)initWithGameBoard:(GameBoard *)aGameBoard;&lt;br /&gt; &lt;br /&gt;@end&lt;/div&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;具体GameBoardView的实现细节如下：（为了演示方便，我们忽略了实际渲染每一个小方块的代码）&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;- (id)initWithGameBoard:(GameBoard *)aGameBoard {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; ((self = [super init])) {&lt;br /&gt;        &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; retain gameboard&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;        self.gameBoard = aGameBoard;&lt;br /&gt; &lt;br /&gt;        &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; render gameboard background&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;        CCSprite *gameboardSprite = [CCSprite spriteWithFile:&lt;span style="color: #800000;"&gt;@"&lt;/span&gt;&lt;span style="color: #800000;"&gt;gameboard.png&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;];&lt;br /&gt;        gameboardSprite.anchorPoint = CGPointMake(&lt;span style="color: #800080;"&gt;0&lt;/span&gt;, &lt;span style="color: #800080;"&gt;0&lt;/span&gt;);&lt;br /&gt; &lt;br /&gt;        [self addChild:gameboardSprite];&lt;br /&gt; &lt;br /&gt;        &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; render spaces&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;        &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; i = &lt;span style="color: #800080;"&gt;0&lt;/span&gt;; i &amp;amp;lt; gameBoard.numberOfRows; i++) {&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; j = &lt;span style="color: #800080;"&gt;0&lt;/span&gt;; j &amp;amp;lt; gameBoard.numberOfColumns; j++) {&lt;br /&gt;                &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; position and render game board spaces&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; self;&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&lt;strong&gt;GameBoardController&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 最后，我们要更新GameBoardController的init方法，因为view需要把GameBoard对象通过init方法注入进去，所以，我们在controller的init方法里面，就应该定义好model对象，然后传递给view。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;- (id)init {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; ((self = [super init])) {&lt;br /&gt;        &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; initialize model&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;        gameBoard = [[GameBoard alloc] initWithRows:&lt;span style="color: #800080;"&gt;7&lt;/span&gt; columns:&lt;span style="color: #800080;"&gt;9&lt;/span&gt;];&lt;br /&gt; &lt;br /&gt;        &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; initialize view&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;        view = [[GameBoardView alloc] initWithGameBoard:gameBoard];&lt;br /&gt; &lt;br /&gt;        [self addChild:view];&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; self;&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&lt;strong&gt;处理touch事件&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;GameBoardView updates&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 为了能够处理touch事件，我们需要再稍微修改一下View。我们让它继承至CCLayer，而不是CCNode。因为CCLayer内置了处理touch事件的方法：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@interface GameBoardView : CCLayer {&lt;br /&gt;...&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; 而view本身是不应该处理用户的交互（touch事件）的，所以，我们需要定义一个代理（GameBoardViewDelegate）。（译者：为什么这里要定义代理呢？所谓代理代理，当然就是你不想做的事，找别人去做，这就是代理。所以，当你写代码的时候，你想保持类的简单性、重用性，你就可以把事件尽量都交给其它类去做，自己只管做好自己的事。也就是SRP，单一职责原则。如果一个类关注的点过多，做的事情太多。这些事情不管是你直接做的，还是调用别的对象去完成的。这都不行，自己做这些事，那就会使类的功能复杂化，维护不方便。而过多地调用其它对象来完成一些事情，表面上看起来好像不错，实际上是过度耦合了。我们编写类的原则应该是追求高内聚，低耦合的。可能你会说，用代理不也是交给别人做吗？没错，问的好。但是，代理是接口，我们是针对接口编程，所以它的重用性会非常好。因此，下次当你想写可扩展和可重用的代码的时候，不妨先想想代理这个东西吧。objc里面delegate是用protocol实现的，而java和c＋＋则是用接口实现的，具体他们之间怎么转换的，比较一下应该就可以了。）&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@protocol GameBoardViewDelegate&lt;br /&gt;- (&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)gameBoard:(GameBoard *)gameBoard touchedAtRow:(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;)row column:(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;)column;&lt;br /&gt;@end&lt;/div&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; 我们还需要再修改一下GameBoardView的init方法，通过传送一个delegate进来处理touch事件。&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;- (id)initWithGameBoard:(GameBoard *)aGameBoard &lt;span style="color: #0000ff;"&gt;delegate&lt;/span&gt;:(id)aDelegate;&lt;/div&gt;&lt;p&gt;下面是touch事件的具体实现：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;- (&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)&lt;span style="color: #0000ff;"&gt;event&lt;/span&gt; {&lt;br /&gt;    UITouch *touch = [touches anyObject];&lt;br /&gt;    CGPoint point = [self convertTouchToNodeSpace:touch];&lt;br /&gt; &lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; calculate row and column touched by the user and call a delegate method&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; ...&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    [self.&lt;span style="color: #0000ff;"&gt;delegate&lt;/span&gt; gameBoard:self.gameBoard touchedAtRow:row column:column];&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&lt;strong&gt;GameBoardController 更新&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; GameBoardController将会负责处理用户touch事件，所以，我们需要让GameBoardController实现GameBoardViewDelegate接口：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@interface GameBoardController : CCNode&amp;lt;GameBoardViewDelegate&amp;gt;&lt;/div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;- (&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)gameBoard:(GameBoard *)gameBoard touchedAtRow:(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;)row column:(&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;)column {&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; do the game logic here and update view accordingly&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;}&lt;/div&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;还有最后一步，那就是修改view的init方法，把controller传递进去。&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; initialize view&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;view = [[GameBoardView alloc] initWithGameBoard:gameBoard &lt;span style="color: #0000ff;"&gt;delegate&lt;/span&gt;:self];&lt;/div&gt;&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 在这篇文章中，我们实现了Model，同时还通过一些代码把view和controller联系起来了。同时，我们还在view和controller，以及用户touch事件之间建立了联系，这样controller类就可以来响应游戏里面的用户输入了。（译者：为什么费这么多劲，无非就是职责分离，这个非常重要！）。在接下来的文章里面，我们会谈到下面两个问题：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;在Controller里面更新Model,&lt;/li&gt;&lt;li&gt;通知View关于Model的改变.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;后记：本文已同步更新到&lt;a href="http://www.cnblogs.com/andyque/archive/2012/03/11/2390814.html" target="_blank"&gt;cocos2d mvc这个系列&lt;/a&gt;里面去了。&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 如果你觉得本文章对你有所帮助，请您点一下旁边的&amp;ldquo;推荐&amp;rdquo;按钮，这样可以让更多的人看到，同时也会给我写作的动力，谢谢大家。&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/zilongshanren/aggbug/2390102.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2390102.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2390100.html</id><title type="text">cocos2d里面如何实现MVC（三）</title><summary type="text">引子：前面两篇文章介绍了一些关于在cocos2d里面如何实现mvc的理论知识，接下来的这三篇教程，我将用一个简单的教程示例，给大家演示一下具体代码实现细节。 这篇文章的写作目的就是让大家更好地理解如何在cocos2d里面实践mvc模式（当然，这里演示的不一定是标准的mvc，因为cocos2d特殊的编程方式。但是，这并不妨碍我们编写更好的代码，你们说对吧？），本文是基于前两篇文章的，所以，在继续阅读之前，我强烈建议你先读一下第一篇的理论介绍。情景 我们将制作一个简单的面板解谜游戏（board puzzle game），当然，我们不是简单地开发一个游戏，而是要利用mvc开发出一个简单的“游...</summary><published>2012-03-18T09:07:00Z</published><updated>2012-03-18T09:07:00Z</updated><author><name>子龙山人</name><uri>http://www.cnblogs.com/zilongshanren/</uri></author><link rel="alternate" href="http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2390100.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2390100.html"/><content type="html">&lt;p&gt;&amp;nbsp; &amp;nbsp; 引子：前面两篇文章介绍了一些关于在cocos2d里面如何实现mvc的理论知识，接下来的这三篇教程，我将用一个简单的教程示例，给大家演示一下具体代码实现细节。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 这篇文章的写作目的就是让大家更好地理解如何在cocos2d里面实践mvc模式（当然，这里演示的不一定是标准的mvc，因为cocos2d特殊的编程方式。但是，这并不妨碍我们编写更好的代码，你们说对吧？），本文是基于前两篇文章的，所以，在继续阅读之前，我强烈建议你先读一下&lt;a href="http://www.cnblogs.com/andyque/archive/2012/03/11/2390074.html" target="_blank"&gt;第一篇&lt;/a&gt;的理论介绍。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;情景&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 我们将制作一个简单的面板解谜游戏（board puzzle game），当然，我们不是简单地开发一个游戏，而是要利用mvc开发出一个简单的&amp;ldquo;游戏框架&amp;rdquo;，而且这个框架将会在我的新游戏里面使用到，它具有如下一些特性：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;一个n行n列的游戏面板（game board），n可以随着游戏难度进行变化。&amp;nbsp;&lt;/li&gt;&lt;li&gt;这个游戏面板里面会包含一些&amp;ldquo;小方块（game pieces）&amp;rdquo;，而且每一个game board上都只能放一个game piece。&lt;/li&gt;&lt;li&gt;这个游戏面板可以初始化一些固定的小方块，玩家在游戏过程中，是不能移动这些小方块的。&lt;/li&gt;&lt;li&gt;这里还定义了一个&amp;ldquo;工具箱（toolbox）&amp;rdquo;，它上面可以放置许多小工具（toolbox item），它们可以看作是&amp;ldquo;可放置可移动小方块的槽子&amp;rdquo;。&lt;/li&gt;&lt;li&gt;小工具（或者叫槽子）上面可以放置许多同一类型的小工具。&lt;/li&gt;&lt;li&gt;这些小工具可以从工具箱上面移动，并且可以放置到game board 上面。&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012031114013073.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;基本概念&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;来自&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller"&gt;wikipedia&lt;/a&gt;:&lt;/p&gt;&lt;p&gt;&lt;em&gt;&amp;nbsp; &amp;nbsp; model负责管理应用领域的数据和行为逻辑，同时负责响应对自己的状态数据请求（这些请求通常是从view过来的），然后响应一些指令来更改自身的状态（这些请求通常是来自controller的）。在一个事件驱动的系统中，model会通知订阅者（observers）（通常是views）它的状态改变，这样view就可以做相应的显示更新。&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;&amp;nbsp; &amp;nbsp; view则根据model的状态来合理地显示，通常是一些UI元素。一个model可以对应多个view，比如，同一数据的柱状图、饼状条、曲线图等。&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;&amp;nbsp; &amp;nbsp;controller负责接收多用户输入和调用model的一些方法。一个controller通过从用户那里获得输入，然后操作model对象，最后，model通知view来更新显示。&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;&amp;nbsp; &amp;nbsp;从维基百科的定义中，我们可以识别出以下几个主要的类（我们会在后面把model给加上去）：&lt;/em&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;em&gt;GameBoardView&lt;/em&gt;&amp;nbsp;代表应用程序的主视图&lt;/li&gt;&lt;li&gt;&lt;em&gt;GameBoardController&lt;/em&gt;&amp;nbsp;是GameBoardView的一个控制器。&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012031114021461.jpg" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 请注意，这里的实线代表一种直接的关联关系（controller里面包含一个view的引用），而虚线则代表了一种间接的关联（通过观察者模式）。这里的直接关联后面会用来实现touch事件处理。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;实现&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;项目组织结构&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 在XCode4里面基于cocos2d的默认模板创建一个新的项目之后，我们又创建了下面这些Groups：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;View &amp;ndash; views &amp;amp; controller 组 (我们也可以把view和controller放在那个不同的group里面，但是，由于我们两个有直接的关联关系，为了方便，我就把它们放在一些了）&lt;/li&gt;&lt;li&gt;Model &amp;ndash; 之后，我们会把model类放在这个group下面。&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012031114025098.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;GameBoardView 的实现&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 接下来，我们开始实现GameBoardView。首先，我们把GameBoardView继承至CCNode。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@interface GameBoardView : CCNode {&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; 然后，实现它的init方法，然后简单地显示一串字符来验证程序的正确性。（译者：这就和我们有时候会在方法的第一句加一个CCLOG一样，只是为了验证函数是否被调用了，确保每一步都是按照你的想法去走的，这样比那种埋头编写2个小时代码不编译，而后花一晚上修改编译错误和bug要好很多。有时候只是输出还不够，还必须要做单元测试，这样才能提高效率）&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;- (id)init {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; ((self = [super init])) {&lt;br /&gt;        &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; create and initialize a Label&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    CCLabelTTF *label = [CCLabelTTF labelWithString:&lt;span style="color: #800000;"&gt;@"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Hello World from view&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; fontName:&lt;span style="color: #800000;"&gt;@"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Marker Felt&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; fontSize:&lt;span style="color: #800080;"&gt;48&lt;/span&gt;];&lt;br /&gt; &lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; ask director the the window size&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    CGSize size = [[CCDirector sharedDirector] winSize];&lt;br /&gt; &lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; position the label on the center of the screen&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    label.position =  ccp( size.width /&lt;span style="color: #800080;"&gt;2&lt;/span&gt; , size.height/&lt;span style="color: #800080;"&gt;2&lt;/span&gt; );&lt;br /&gt; &lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; add the label as a child to this Layer&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    [self addChild: label];&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; self;&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&lt;strong&gt;GameBoardController 实现&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;GameBoardController负责初始化view，所以它里面包含了一个GameBoardView的引用，将来就可以非常方便地直接使用了。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@interface GameBoardController : CCNode {&lt;br /&gt;    GameBoardView *view;&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;因为我们的GameBoardController继承到CCNode，所以，我们可以把GameBoardView当作GameBoardController的孩子给添加进去。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;- (id)init {&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; ((self = [super init])) {&lt;br /&gt;        view = [GameBoardView node];&lt;br /&gt; &lt;br /&gt;        [self addChild:view];&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; self;&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&lt;strong&gt;最后的修改&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 我们然后修改AppDelegate类，然后运行我们新创建的contorller：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;[[CCDirector sharedDirector] runWithScene: [GameBoardController node]];&lt;/div&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp;好了，现在编译并运行。当程序跑起来的时候，这个结果和cocos2d自带的模板运行效果差不多。但是，有个很重要的区别，那就是我们创建了一个mvc的骨架，在接下来的游戏逻辑中，我们可以在上面做很多文章。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;接下来做什么&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 该项目进行到现在，已经为我们引入一些更高级的概念打下了良好的基础，所以，在下一篇教程里，我们将涉及下面两个东西：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;处理touch事件.&lt;/li&gt;&lt;li&gt;引用model的概念.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp;&lt;/p&gt;&lt;p&gt;后记：本文已同步更新到&lt;a href="http://www.cnblogs.com/andyque/archive/2012/03/11/2390814.html" target="_blank"&gt;cocos2d mvc这个系列&lt;/a&gt;里面去了。&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 如果你觉得本文章对你有所帮助，请您点一下旁边的&amp;ldquo;推荐&amp;rdquo;按钮，这样可以让更多的人看到，同时也会给我写作的动力，谢谢大家。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/zilongshanren/aggbug/2390100.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2390100.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2404651.html</id><title type="text">（译）Iphone开发之音频101 (第一部分)： 文件和数据类型</title><summary type="text">免责申明（必读！）：本博客提供的所有教程的翻译原稿均来自于互联网，仅供学习交流之用，切勿进行商业传播。同时，转载时不要移除本申明。如产生任何纠纷，均与本博客所有人、发表该翻译稿之人无任何关系。谢谢合作！原文链接地址：http://www.raywenderlich.com/204/audio-101-for-iphone-developers-file-and-data-formats本教程由大侠自来也翻译，泰然论坛翻译组校对，感谢大侠自来也！ 在做iphone开发之前，我（ray）对声音格式了解的相当少。我知道一些“wav”和“mp3”声音格式的差异，但是我肯定不能准确地告诉你“AAC”..</summary><published>2012-03-18T06:41:00Z</published><updated>2012-03-18T06:41:00Z</updated><author><name>子龙山人</name><uri>http://www.cnblogs.com/zilongshanren/</uri></author><link rel="alternate" href="http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2404651.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2404651.html"/><content type="html">&lt;p class="p0"&gt;&lt;span style="color: #ff0000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 免责申明（必读！）：本博客提供的所有教程的翻译原稿均来自于互联网，仅供学习交流之用，切勿进行商业传播。同时，转载时不要移除本申明。如产生任何纠纷，均与本博客所有人、发表该翻译稿之人无任何关系。谢谢合作！&lt;/span&gt;&lt;/p&gt;&lt;p class="p0"&gt;&amp;nbsp;&lt;/p&gt;&lt;p class="p0"&gt;原文链接地址：&lt;a href="http://www.raywenderlich.com/233/audio-101-for-iphone-developers-converting-and-recording"&gt;http://www.raywenderlich.com/204/audio-101-for-iphone-developers-file-and-data-formats&lt;/a&gt;&lt;/p&gt;&lt;p class="p0"&gt;&amp;nbsp;&lt;/p&gt;&lt;p class="p0"&gt;本教程由&lt;span style="color: #ff0000;"&gt;大侠自来&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;也&lt;/span&gt;翻译，泰然&lt;span style="color: #ff0000;"&gt;论坛翻译组&lt;/span&gt;校对，感谢&lt;span style="color: #ff0000;"&gt;&lt;a href="http://home.cnblogs.com/u/bandok123/" target="_blank"&gt;大侠自来也&lt;/a&gt;！&lt;/span&gt;&lt;/p&gt;&lt;p class="p0"&gt;&amp;nbsp;&lt;/p&gt;&lt;p class="p0"&gt;在做iphone开发之前，我（&lt;span style="font-family: Tahoma;"&gt;ray&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;）对声音格式了解的相当少。我知道&lt;/span&gt;一些&amp;ldquo;wav&amp;rdquo;&lt;span style="font-family: 宋体;"&gt;和&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;&amp;ldquo;mp3&amp;rdquo;&lt;/span&gt;声音格式的差异，但是我肯定不能准确地告诉你&lt;span style="font-family: Tahoma;"&gt;&amp;ldquo;AAC&amp;rdquo;&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;、&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;&amp;ldquo;CAF&amp;rdquo;&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;是什么&lt;/span&gt;格式的声音文件，同时也不知道在MAC&lt;span style="font-family: 宋体;"&gt;上最好的转换音频文件的方法&lt;/span&gt;是什么。&lt;/p&gt;&lt;p class="p0"&gt;我深知，假如你想要成为一名合格的iphone开发者，你必须对声音文件数据格式，转换，录音和使用什么音频操作API&lt;span style="font-family: 宋体;"&gt;有个基本的了解。&lt;/span&gt;&lt;/p&gt;&lt;p class="p0"&gt;这篇文章是三篇涵盖音频开发教程中的第一篇。在这篇文章中，我们将会从文件和数据格式开始。&lt;/p&gt;&lt;h3 class="p0"&gt;文件格式和数据格式&lt;/strong&gt;&lt;/p&gt;&lt;p class="p0"&gt;&amp;nbsp;首先我们要知道的是，对每个音频文件有两部分：&lt;span style="font-family: Tahoma;"&gt;1&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;是文件格式（&lt;/span&gt;也叫音频容器），&lt;span style="font-family: Tahoma;"&gt;2&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;是数据格式（&lt;/span&gt;也叫音频编码）。&lt;/p&gt;&lt;p class="p0"&gt;文件格式（或者是音频容器）描述了这个文件它自己的格式。它里面的实际音频数据能使用很多不同的方式编码。例如，一个后缀为caf的文件是一种文件格式，它能够包含用&lt;span style="font-family: Tahoma;"&gt;MP3&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;、线性&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;pcm&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;（&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;lpcm&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;）&lt;/span&gt;和其他许多格式编码的音频数据。&lt;/p&gt;&lt;p class="p0"&gt;　&amp;nbsp;&amp;nbsp; 接下来让我们更深入些。&lt;/p&gt;&lt;h3 class="p0"&gt;数据格式（音频编码）&lt;/strong&gt;&lt;/p&gt;&lt;p class="p0"&gt;我们接下来将要开始了解音频编码，而不是文件格式，因为音频编码才是最重要的。&lt;/p&gt;&lt;p class="p0"&gt;以下是&lt;span style="font-family: Tahoma;"&gt;iphone&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;支持的的&lt;/span&gt;音频数据编码格式和针对每个的描述：&lt;/p&gt;&lt;ul&gt;&lt;li class="p0"&gt;&amp;nbsp;AAC&lt;span style="font-family: 宋体;"&gt;：&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;aac&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;其实是&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;&amp;ldquo;&lt;/span&gt;高级音频编码（advanced&amp;nbsp;audio&amp;nbsp;coding）&amp;rdquo;的缩写，它是被设计用来取代MP3格式的。你可能会想，它压缩了原始的声音，导致容量占用少但是质量肯定会有所下降。不过这些质量的损失取决于声音比特率的大小，当比特率合适的时候，这些损失人耳是很难听出来的。事实上，&lt;span style="font-family: Tahoma;"&gt;aac&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;比&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;mp3&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;有更好的压缩率，特别是在比特率&lt;/span&gt;低于128bit/s&lt;span style="font-family: 宋体;"&gt;的时候&lt;/span&gt;。&lt;span style="font-family: Tahoma;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li class="p0"&gt;&amp;nbsp;HE-AAC&lt;span style="font-family: 宋体;"&gt;：&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;HE-AAC&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;是&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;AAC&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;的一个&lt;/span&gt;超集，这个&lt;span style="font-family: Tahoma;"&gt;&amp;ldquo;HE&amp;rdquo;&lt;/span&gt;代表的是&amp;ldquo;High&amp;nbsp;efficiency&amp;rdquo;。&amp;nbsp;HE-AAC是专门为低比特率所优化的一种音频编码格式，比如streaming&amp;nbsp;audio&lt;span style="font-family: 宋体;"&gt;就特别适合使用这种编码格式&lt;/span&gt;。&lt;/li&gt;&lt;li class="p0"&gt;AMR&lt;span style="font-family: 宋体;"&gt;：&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;AMR&lt;/span&gt;全称是&lt;span style="font-family: Tahoma;"&gt;&amp;ldquo;Adaptive&amp;nbsp;Multi-Rate&amp;rdquo;&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;，&lt;/span&gt;它也是另一个专门为&amp;ldquo;说话（speech&lt;span style="font-family: 宋体;"&gt;）&amp;rdquo;&lt;/span&gt;所优化的编码格式，也是适合低比特率环境下采用。&lt;/li&gt;&lt;li class="p0"&gt;ALAC&lt;span style="font-family: 宋体;"&gt;：它&lt;/span&gt;全称是&lt;span style="font-family: Tahoma;"&gt;&amp;ldquo;Apple&amp;nbsp;Lossless&amp;rdquo;&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;，这是一种没有任何质量损失的音频编码方式，也就是我们说的无损压缩。&lt;/span&gt;在实际使用过程中，它能够压缩40%-60%&lt;span style="font-family: 宋体;"&gt;的原始数据。这种编码格式的解码速度非常快，这对&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;iphone&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;或者&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;ipod&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;这种小型设备来说非常适合。&lt;/span&gt;&lt;/li&gt;&lt;li class="p0"&gt;iLBC:&amp;nbsp;&lt;span style="font-family: 宋体;"&gt;这是另一&lt;/span&gt;种专门为说话所设计的音频编码格式，它非常适合于IP&lt;span style="font-family: 宋体;"&gt;电话等其它需要流式音频的场合。&lt;/span&gt;&lt;/li&gt;&lt;li class="p0"&gt;IMA4&lt;span style="font-family: 宋体;"&gt;：&amp;nbsp;这是一个在&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;16-bit&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;音频文件下按照&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;4&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;：&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;1&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;的压缩&lt;/span&gt;比来进行压缩的格式。这是&lt;span style="font-family: Tahoma;"&gt;iphone&lt;/span&gt;上面一种非常重要的编码格式，我们将在以后讨论原因。&lt;/li&gt;&lt;li class="p0"&gt;&amp;nbsp;Linear&amp;nbsp;PCM&lt;span style="font-family: 宋体;"&gt;：&lt;/span&gt;它的中文意思是基于线性脉冲编码调制，用于将模拟声音数据转换成数字声音数据。简而言之，就是意味着无压缩数据。由于数据是非压缩的，它可以非常快的播放，并且当空间不是问题时，这是在&lt;span style="font-family: Tahoma;"&gt;iphone&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;上面首选的音频编码方式。&lt;/span&gt;&lt;/li&gt;&lt;li class="p0"&gt;&amp;nbsp;&amp;mu;-law&amp;nbsp;and&amp;nbsp;a-law&lt;span style="font-family: 宋体;"&gt;：&amp;nbsp;就我所知道的，这种编码是交替的编码模拟数据&lt;/span&gt;为数字格式数据，但是在speech优化方面比&lt;span style="font-family: Tahoma;"&gt;linear&amp;nbsp;PCM&lt;/span&gt;更好。&lt;/li&gt;&lt;li class="p0"&gt;&amp;middot;MP3&lt;span style="font-family: 宋体;"&gt;：&amp;nbsp;这种格式是我们都知道也喜欢的，&lt;/span&gt;虽然很多年过去了，但MP3到目前为止仍然是一种非常流行的编码格式，它也能被&lt;span style="font-family: Tahoma;"&gt;iphone&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;很好&lt;/span&gt;地支持。&lt;/li&gt;&lt;/ul&gt;&lt;h3 class="p0"&gt;我们到底选择什么编码格式？&lt;/strong&gt;&lt;/p&gt;&lt;p class="p0"&gt;上面的看起来是张很大的表，但是实际上只有一些是我们做开发时首选的。在具体做选择的时候，你必须记住以下几点：&lt;/p&gt;&lt;ul&gt;&lt;li class="p0"&gt;你可以播放&lt;span style="font-family: Tahoma;"&gt;linear&amp;nbsp;PCM&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;，&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;IMA4&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;和一些其它没有压缩&lt;/span&gt;的或者简单压缩的音频格式，这些格式可以很好地被&lt;span style="font-family: Tahoma;"&gt;iphone&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;的硬件解码。&lt;/span&gt;&lt;/li&gt;&lt;li class="p0"&gt;对于更多高级的压缩格式，例如&lt;span style="font-family: Tahoma;"&gt;AAC&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;，&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;MP3&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;，和&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;ALAC&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;，&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;iphone&lt;/span&gt;并没有提供硬件编解码器的支持来很快解压缩这些数据，并且在一个时候只能处理一个文件。因此，假如你播放超过一个使用这些编码的音频文件，系统将选择使用软件来解码，那样会比较慢，还会占用&lt;span style="font-family: Tahoma;"&gt;CPU&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;。&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p class="p0"&gt;因此选择什么样的数据格式，这里有两条建议：&lt;/p&gt;&lt;ul&gt;&lt;li class="p0"&gt;假如空间不是问题，那么使用&lt;span style="font-family: Tahoma;"&gt;linear&amp;nbsp;PCM&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;来编码每个音频。这样不仅使你的音频最快&lt;/span&gt;地播放，而且你能够在不占用&lt;span style="font-family: Tahoma;"&gt;CPU&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;资源的情况下&lt;/span&gt;同时播放多个声音。&lt;/li&gt;&lt;li class="p0"&gt;假如空间是问题，你大多数时候要使用&lt;span style="font-family: Tahoma;"&gt;AAC&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;来编码你的背景音乐和&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;IMA4&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;来编码你的音效。&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 class="p0"&gt;Linear&amp;nbsp;PCM&lt;span style="font-family: 宋体;"&gt;的许多&lt;/span&gt;变种&lt;/strong&gt;&lt;/p&gt;&lt;p class="p0"&gt;还有一个很重要的关于&lt;span style="font-family: Tahoma;"&gt;linear&amp;nbsp;PCM&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;的&lt;/span&gt;问题需要强调，那就是这种无压缩的数据格式是iphone上面编程首选的。针对不同的数据存储，这里有一些linear&amp;nbsp;PCM变种。这些数据可以使用高尾数或者低尾数格式来储存，它们之间的差别，就像浮点型和整型它们占用的位宽不同。&lt;/p&gt;&lt;p class="p0"&gt;这里最重要的一件事就是，在&lt;span style="font-family: Tahoma;"&gt;iphone&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;上面首选的&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;linear&amp;nbsp;PCM&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;是低&lt;/span&gt;尾数（little-endian）格式的&lt;span style="font-family: Tahoma;"&gt;16&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;位整型，或者是&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;"LEI16"(&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;好像是一种编码格式，&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;apple&amp;nbsp;caf&amp;nbsp;audio&amp;nbsp;format&amp;nbsp;code&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;：&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;LEI16,&amp;nbsp;ios&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;设备的音频格式是&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;16&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;位低&lt;/span&gt;尾数编码&lt;span style="font-family: Tahoma;"&gt;)&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;。这个是和&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;Mac&amp;nbsp;os&amp;nbsp;x&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;不一样的，它使用的是本地&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;32&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;位浮点型&lt;/span&gt;尾数编码。因为音频文件经常要在&lt;span style="font-family: Tahoma;"&gt;Mac&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;上面创建，所以检查文件&lt;/span&gt;并把他们转换为iphone&lt;span style="font-family: 宋体;"&gt;首选的&lt;/span&gt;音频编码格式是个很好的主意。&lt;/p&gt;&lt;h3 class="p0"&gt;文件格式（音频容器）&lt;/strong&gt;&lt;/p&gt;&lt;p class="p0"&gt;&lt;span style="font-family: Tahoma;"&gt;iphone&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;支持很多文件格式，包括&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;MPEG-1&amp;nbsp;(.mp3),&amp;nbsp;MPEG-2&amp;nbsp;ADTS&amp;nbsp;(.aac),&amp;nbsp;AIFF,&amp;nbsp;CAF,&amp;nbsp;and&amp;nbsp;WAVE&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;。但是最重要的事是你可以&lt;/span&gt;只使用&lt;span style="font-family: Tahoma;"&gt;CAF&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;，因为它能包含任何&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;iphone&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;支持的编码格式的数据，在&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;iPhone&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;上面它是推荐的文件格式。&lt;/span&gt;&lt;/p&gt;&lt;p class="p0"&gt;（译者：在这里我在啰嗦点，其实文件格式就像是桶一样，里面可以装很多水，那些水就是那些音频数据。桶有很多种，也就是有很多种文件格式，而且不一样的桶，也需要装不同的水。&lt;span style="font-family: Tahoma;"&gt;CAF&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;这种桶就可以装各种各样的水，不过有些就只能装几种类型的水。希望我这样的比喻你可以很好的理解。&lt;/span&gt;）&lt;/p&gt;&lt;h3 class="p0"&gt;比特率&lt;/strong&gt;&lt;/p&gt;&lt;p class="p0"&gt;这有一个有关音频编码很重要的术语，我们接下来会提及：比特率。&lt;/p&gt;&lt;p class="p0"&gt;比特率是音频文件每秒占据的字节数（比特数）。一些像&lt;span style="font-family: Tahoma;"&gt;AAC&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;或者&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;MP3&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;编码会指定音频文件压缩的比特数。当你&lt;/span&gt;在使用比较低的比特率时，你将会丢失声音质量。&lt;/p&gt;&lt;p class="p0"&gt;你应该根据特定的声音文件的不同来选择不同的比特率，试着使用不同的比特率，来比较哪个是最合适的，在声音文件大小和声音质量之间做一些权衡。假如你的文件大多数是语音说话数据，你可以使用比较低的比特率。&lt;/p&gt;&lt;p class="p0"&gt;这里有一个表，给你一个最常见的比特率的概述：&lt;/p&gt;&lt;ul&gt;&lt;li class="p0"&gt;32kbit/s:&amp;nbsp;&lt;span style="font-family: 宋体;"&gt;调幅&lt;/span&gt;（AM）广播的质量&lt;/li&gt;&lt;li class="p0"&gt;48kbit/s:&amp;nbsp;&lt;span style="font-family: 宋体;"&gt;一般比较长时间的语音播客的比特率&lt;/span&gt;&lt;/li&gt;&lt;li class="p0"&gt;64kbit/s:&amp;nbsp;&lt;span style="font-family: 宋体;"&gt;一般正常长度的语音播客的比特率&lt;/span&gt;&lt;/li&gt;&lt;li class="p0"&gt;96kbit/s:&amp;nbsp;&lt;span style="font-family: 宋体;"&gt;调频&lt;/span&gt;（FM）广播的质量&lt;/li&gt;&lt;li class="p0"&gt;128kbit/s:&amp;nbsp;&lt;span style="font-family: 宋体;"&gt;大多数&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;MP3&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;音乐的比特率&lt;/span&gt;&lt;/li&gt;&lt;li class="p0"&gt;160kbit/s:&amp;nbsp;&lt;span style="font-family: 宋体;"&gt;那些很喜欢音乐的，想要听觉感受的人更喜欢的在&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;128kbit/s&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;之上的一个比特率&lt;/span&gt;&lt;/li&gt;&lt;li class="p0"&gt;192kbit/s:&amp;nbsp;&lt;span style="font-family: 宋体;"&gt;数字电台的质量&lt;/span&gt;&lt;/li&gt;&lt;li class="p0"&gt;320kbit/s:&amp;nbsp;&lt;span style="font-family: 宋体;"&gt;在这个比特率下人们几乎和&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;CD&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;的播放效果一样，不能区别&lt;/span&gt;&lt;/li&gt;&lt;li class="p0"&gt;500kbit/s-1,411kbit/s:&amp;nbsp;&lt;span style="font-family: 宋体;"&gt;无损的音频编码，就像&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;linear&amp;nbsp;PCM&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 class="p0"&gt;采样率&lt;/strong&gt;&lt;/p&gt;&lt;p class="p0"&gt;在我们继续介绍音频之前，这里还有一个术语我们需要了解一下，就是：采样率。&lt;/p&gt;&lt;p class="p0"&gt;当转换一个模拟信号到数字格式，采样率表示多久抽取一次声音波形试样来转换成一个数字信号。&lt;/p&gt;&lt;p class="p0"&gt;大多情况下，&lt;span style="font-family: Tahoma;"&gt;44100Hz&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;是被经常使用的，因为这和&lt;/span&gt;&lt;span style="font-family: Tahoma;"&gt;CD&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;音频一样的采样率。&lt;/span&gt;&lt;/p&gt;&lt;p class="p0"&gt;&amp;nbsp;&lt;/p&gt;&lt;p class="p0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;更多关于iphone音频格式及音频操作的文章，可以去&lt;a href="http://home.cnblogs.com/u/bandok123/" target="_blank"&gt;大侠自来也&lt;/a&gt;的主页看看。&amp;nbsp;&lt;/p&gt;&lt;p class="p0"&gt;&amp;nbsp;&lt;/p&gt;&lt;p class="p0"&gt;&lt;span style="font-family: 宋体;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 要论坛交流，请点击&lt;a href="http://www.ityran.com/thread-1319-1-1.html" target="_blank"&gt;传送门&lt;/a&gt;！&lt;/span&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/zilongshanren/aggbug/2404651.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/zilongshanren/archive/2012/03/18/2404651.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/zilongshanren/archive/2012/03/11/2390814.html</id><title type="text">cocos2d里面如何实现mvc</title><summary type="text">cocos2d里面如何实现MVC（一）cocos2d里面如何实现MVC（二）cocos2d里面如何实现mvc（三）cocos2d里面如何实现mvc（四）cocos2d里面如何实现mvc（五）cocos2d里面如何实现mvc（六）cocos2d里面如何实现mvc（完）</summary><published>2012-03-11T15:07:00Z</published><updated>2012-03-11T15:07:00Z</updated><author><name>子龙山人</name><uri>http://www.cnblogs.com/zilongshanren/</uri></author><link rel="alternate" href="http://www.cnblogs.com/zilongshanren/archive/2012/03/11/2390814.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/zilongshanren/archive/2012/03/11/2390814.html"/><content type="html">&lt;p&gt;&lt;a id="cb_post_title_url" href="http://www.cnblogs.com/andyque/archive/2012/03/11/2390074.html"&gt;cocos2d里面如何实现MVC（一）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a id="cb_post_title_url" href="http://www.cnblogs.com/andyque/archive/2012/03/11/2390082.html"&gt;cocos2d里面如何实现MVC（二）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/andyque/archive/2012/03/18/2390100.html" target="_blank"&gt;cocos2d里面如何实现mvc（三）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/andyque/archive/2012/03/18/2390102.html" target="_blank"&gt;cocos2d里面如何实现mvc（四）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/andyque/archive/2012/03/18/2390106.html" target="_blank"&gt;cocos2d里面如何实现mvc（五）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/andyque/archive/2012/03/18/2390109.html" target="_blank"&gt;cocos2d里面如何实现mvc（六）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/andyque/archive/2012/03/18/2390111.html" target="_blank"&gt;cocos2d里面如何实现mvc（完）&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/zilongshanren/aggbug/2390814.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/zilongshanren/archive/2012/03/11/2390814.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/zilongshanren/archive/2012/03/11/2390082.html</id><title type="text">cocos2d里面如何实现MVC（二）</title><summary type="text">上一篇博文中，我提到了《如何在cocos2d里面实现mvc》，但是，都是一些纯理论的东西，我们需要看一些代码才能理解地更清楚。这篇博文是基于上一篇来写的，所以我建议你先阅读完上一篇再接着往下看。模型类 就像之前所讨论的，GameModel类存储了游戏世界里面的一些属性，比如当前的重力。但是，它同时也负责创建和连接游戏里面的对象，比如Player和Platforms。它们之间的关系如下图所示：（译者：这里采用了针对接口编程的方法，所有的游戏对象都继承至updateable接口，这样就可以在game loop里面更新自己了。同时GameModel类提供了一个工厂方法createGameObje..</summary><published>2012-03-11T15:05:00Z</published><updated>2012-03-11T15:05:00Z</updated><author><name>子龙山人</name><uri>http://www.cnblogs.com/zilongshanren/</uri></author><link rel="alternate" href="http://www.cnblogs.com/zilongshanren/archive/2012/03/11/2390082.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/zilongshanren/archive/2012/03/11/2390082.html"/><content type="html">&lt;p&gt;&amp;nbsp; &amp;nbsp;上一篇博文中，我提到了&lt;a href="http://www.cnblogs.com/andyque/archive/2012/03/11/2390074.html" target="_blank"&gt;《如何在cocos2d里面实现mvc》&lt;/a&gt;，但是，都是一些纯理论的东西，我们需要看一些代码才能理解地更清楚。这篇博文是基于上一篇来写的，所以我建议你先阅读完上一篇再接着往下看。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;模型类&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 就像之前所讨论的，GameModel类存储了游戏世界里面的一些属性，比如当前的重力。但是，它同时也负责创建和连接游戏里面的对象，比如Player和Platforms。它们之间的关系如下图所示：（译者：这里采用了针对接口编程的方法，所有的游戏对象都继承至updateable接口，这样就可以在game loop里面更新自己了。同时GameModel类提供了一个工厂方法createGameObjects，用来创建游戏里面的对象。）&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012031113423594.gif" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; 你可能已经注意到了，所有的model类都实现了updateable protocol，并实现了update方法。这样它们就可以在game loop里面更新自己的状态了。比如，在Player类里面，我们需要根据当前x轴和y轴的速度来更新player的位置信息。在我的游戏里面，我把它委托给Physics组件，它是我实现的一个简单的物理引擎。但是，假如你的游戏很简单的话，你可以不用分开你的物理代码，然后可以直接在update方法里面来做碰撞检测等物理操作。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@implementation Player&lt;br /&gt;- (&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)update:(ccTime)dt&lt;br /&gt;{&lt;br /&gt;    [_physics updateModel:self dt:dt];&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; detect collisions with game objects, etc.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;}&lt;/div&gt;&lt;p&gt;GameModel实现的update方法，不仅仅用来更新自己的状态，同时，它还调用player的update方法和所有platform的update方法。这个update方法，之后会被game loop所调用。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@implementation GameModel&lt;br /&gt;- (&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)update:(ccTime)dt&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; modify game model properties here&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; update player&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    [self.player update:dt];&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; update platforms&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (Platform *platform &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; _platforms) {&lt;br /&gt;        [platform update:dt];&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; ...&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;}&lt;/div&gt;&lt;p&gt;&lt;strong&gt;视图和控制器类&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 对于我的游戏里面的每一个场景（CCScene），都关联了一个Controller类，它负责处理用户交互、创建视图和管理场景的跳转。控制器会schedule一个游戏主循环，在这个loop里面，所有的model和view的update方法都会被调用。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@implementation GameplayController&lt;br /&gt;- (id)init&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;((self=[super init])) {&lt;br /&gt;        GameplayView *view = [[GameplayView alloc] initWithDelegate:self];&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; retain view in controller&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    self.view = view;&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; release view&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    [view release];&lt;br /&gt; &lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; init model&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    GameModel *model = [GameModel sharedModel];&lt;br /&gt;    [model createGameObjects];&lt;br /&gt;    [model.player run];&lt;br /&gt; &lt;br /&gt;    [self scheduleUpdate];&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;- (&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)update:(ccTime) dt&lt;br /&gt;{&lt;br /&gt;    GameModel *model = [GameModel sharedModel];&lt;br /&gt; &lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (model.isGameOver) {&lt;br /&gt;    [[CCDirector sharedDirector] replaceScene:[GameOverController node]];&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; process model&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    [model update:dt];&lt;br /&gt; &lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; update view&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    [self.view update:dt];&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;View主要负责根据model的状态来渲染游戏画面。但是，同时，因为cococs2d的实现方式，我们还需要把touch事件传递给controller类。你应该注意到了，view不并直接依赖controller。view类调用controller的方法是通过GameViewDelegate协议来实现的。这也是为什么我们要在init方法里面传递一个delegate的原因。&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@implementation GameplayView&lt;br /&gt;- (id)initWithDelegate:(id)theDelegate&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; ((self = [super init])) {&lt;br /&gt;        self.&lt;span style="color: #0000ff;"&gt;delegate&lt;/span&gt; = theDelegate;&lt;br /&gt; &lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; initialize layers&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    _backgroundLayer = [GameplayBackgroundLayer node];&lt;br /&gt;    [self.&lt;span style="color: #0000ff;"&gt;delegate&lt;/span&gt; addChild: _backgroundLayer];&lt;br /&gt; &lt;br /&gt;    _platformLayer = [GameplayPlatformLayer node];&lt;br /&gt;    [self.&lt;span style="color: #0000ff;"&gt;delegate&lt;/span&gt; addChild:_platformLayer];&lt;br /&gt; &lt;br /&gt;    _playerLayer = [GameplayPlayerLayer node];&lt;br /&gt;    _playerLayer.&lt;span style="color: #0000ff;"&gt;delegate&lt;/span&gt; = theDelegate;&lt;br /&gt;    [self.&lt;span style="color: #0000ff;"&gt;delegate&lt;/span&gt; addChild: _playerLayer];&lt;br /&gt; &lt;br /&gt;    _hudLayer = [GameplayHudLayer node];&lt;br /&gt;    _hudLayer.&lt;span style="color: #0000ff;"&gt;delegate&lt;/span&gt; = theDelegate;&lt;br /&gt;        [self.&lt;span style="color: #0000ff;"&gt;delegate&lt;/span&gt; addChild:_hudLayer];&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; self;&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&lt;span&gt;// 更新:我忘了告诉大家layer本身是怎么实现的了。其实很简单，就是创建一些sprite、action和animation等。&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@implementation GameplayPlayerLayer&lt;br /&gt;- (id)init&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; ((self = [super init])) {&lt;br /&gt;        self.isTouchEnabled = YES;&lt;br /&gt;    self.isAccelerometerEnabled = YES;&lt;br /&gt;        ResourceManager *resources = [ResourceManager sharedResourceManager];&lt;br /&gt; &lt;br /&gt;    [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:PLAYER_SPRITE_SHEET_PLIST];&lt;br /&gt; &lt;br /&gt;    CCSpriteBatchNode *spriteSheet = [resources playerSpriteSheet];&lt;br /&gt;    [self addChild:spriteSheet];&lt;br /&gt;        &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; ... &lt;br /&gt;       &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; initialize sprites&lt;br /&gt;       &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; initialize animations&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;}&lt;/div&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; 层里面的精灵都会在layer的update方法里面被更新，如下所示：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;- (&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)update:(ccTime)dt &lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; update player sprite based on model&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;    GameModel *model = [GameModel sharedModel];&lt;br /&gt; &lt;br /&gt;    _playerSprite.position = ccp((model.player.position.x - model.viewPort.rect.origin.x) * PPM_RATIO,  (model.player.position.y - model.viewPort.rect.origin.y) * PPM_RATIO);&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; 注意，在渲染player的位置的时候，我们使用了PPM_RATIO，用来把米转换成point。（为什么是point而不是pixel，因为cocos2d使用的是point而不是pixel，不明白的可以看看源代码和官方文档）&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; touch事件被传递给了controller类，如下所示：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@implementation GameplayPlayerLayer&lt;br /&gt;- (&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)&lt;span style="color: #0000ff;"&gt;event&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;    [self.&lt;span style="color: #0000ff;"&gt;delegate&lt;/span&gt; playerBeginJump];&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp; 然后下图就是view和controller交互的完整的UML图：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012031113460123.gif" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;处理模型事件&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 上一篇博文中，我留下了一个问题，就是怎么处理model和controller之间的交互。其它很简单，就是使用观察者模式，controller只要订阅model的事件，然后定义相应的处理方法即可。当model更新的时候，会触发事件，然后所有侦听了该事件的controller都能被通知到。下面给出实现：（译者：很多童靯不知道对象之间该怎么交互，其实使用NSNotification可以大大地解耦对象的交互，使代码更容易维护。）&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@implementation Player&lt;br /&gt;- (&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)beginJump&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; ([_gameModel isOnGround:self]) {&lt;br /&gt;        [[NSNotificationCenter defaultCenter] postNotificationName:EVENT_PLAYER_BEGIN_JUMP &lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;:nil];&lt;br /&gt;    ...&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;controller订阅事件，当事件发生的时候会得到通知，同时相应的事件处理函数将会被调用。&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;@implementation GameplayController&lt;br /&gt;- (id)init&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; ((self = [super init])) {&lt;br /&gt;        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onPlayerBeginJumpNotification:) name:EVENT_PLAYER_BEGIN_JUMP &lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;:nil];&lt;br /&gt;        ...&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;- (&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;)onPlayerBeginJumpNotification:(NSNotification *)notification&lt;br /&gt;{&lt;br /&gt;    [[SimpleAudioEngine sharedEngine] playEffect:PLAYER_JUMP_SOUND];&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;&lt;strong&gt;就这么多！&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 乍一看，可能会觉得有点复杂。而且，要创建这么多类，却只是为了实现一个简单的功能，确实有点划不来。而且，你还记得吗？如果在系统里面添加太多的类，其实是一种反模式（anti-pattern），叫做&lt;a href="http://c2.com/cgi/wiki?FearOfAddingClasses"&gt;Fear of Adding Classes&lt;/a&gt;。但是，从长远的角度来看，从可维护性的角度来看，加这么多类是值得的。后面的教程我将向大家展示出来。如果大家对于如何在cocos2d里面使用mvc有更好的看法，欢迎补充。&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/zilongshanren/aggbug/2390082.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/zilongshanren/archive/2012/03/11/2390082.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/zilongshanren/archive/2012/03/11/2390074.html</id><title type="text">cocos2d里面如何实现MVC（一）</title><summary type="text">前言： 众所周知，现在MVC非常流行。现在只要随便搜索一下，哪里都是MVC的影子。刚开始在j2ee里面，然后是rails，后面居然.net也出来了，ios更不用说，哪里都是mvc，而且强制你必须使用mvc。但是，我们写的那些程序，真正完全符合mvc吗？呵呵，这个不好说，看个人理解程度而异。mvc实在是太火了，马上就有人在cocos2d社区里面讨论，cocos2d该怎么实现mvc呢？大家你一言，我一语，讨论的是热火朝天。有人支持，也有人反对。不管咋样，今天让我们也来见识一下cocos2d里面的mvc，看看到底这玩意儿好使不。 Model-View-Controller (MVC)在web应用开.</summary><published>2012-03-11T14:39:00Z</published><updated>2012-03-11T14:39:00Z</updated><author><name>子龙山人</name><uri>http://www.cnblogs.com/zilongshanren/</uri></author><link rel="alternate" href="http://www.cnblogs.com/zilongshanren/archive/2012/03/11/2390074.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/zilongshanren/archive/2012/03/11/2390074.html"/><content type="html">&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/283130/2012031113405058.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;前言：&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 众所周知，现在MVC非常流行。现在只要随便搜索一下，哪里都是MVC的影子。刚开始在j2ee里面，然后是rails，后面居然.net也出来了，ios更不用说，哪里都是mvc，而且强制你必须使用mvc。但是，我们写的那些程序，真正完全符合mvc吗？呵呵，这个不好说，看个人理解程度而异。mvc实在是太火了，马上就有人在cocos2d社区里面讨论，cocos2d该怎么实现mvc呢？大家你一言，我一语，讨论的是热火朝天。有人支持，也有人反对。不管咋样，今天让我们也来见识一下cocos2d里面的mvc，看看到底这玩意儿好使不。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Model%E2%80%93View%E2%80%93Controller"&gt;Model-View-Controller (MVC)&lt;/a&gt;&amp;nbsp;在web应用开发中非常流行，它是一种组合设计模式，目前被广泛应用于带有图形交互用户界面程序开发中。一些web开发框架，比如&lt;a href="http://rubyonrails.org/"&gt;Ruby On Rails&lt;/a&gt;,&lt;a href="http://www.djangoproject.com/"&gt;Django&lt;/a&gt;&amp;nbsp;和&amp;nbsp;&lt;a href="http://www.asp.net/mvc"&gt;ASP.NET MVC&lt;/a&gt;，&amp;nbsp;它们是不同语言平台上面的web开发框架，但是，它们都共用同样的原则--那就是把用户表示层和逻辑层分离开来。关注点分离（SoC），这个原则在现代软件工程方法中是一个非常重要的设计理念--不要迷失于实现细节，遇到一个实际问题的时候，要划分不同的关注点，且这些关注点必须隔离开来，这样才能达到更好的代码重用度，以获得鲁棒性、可适配性和可维护性。所有这些软件属性对于软件质量来说都是至关重要的。&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;a href="http://www.cocos2d-iphone.org/"&gt;Cocos2d&lt;/a&gt;本身并不是基于mvc的理念来设计的，但是，这并不防碍你在自己的游戏开发中使用mvc。实现方式肯定是多种多样的，在这篇博文中， 我只是向大家分享一下我是怎么在cocos2d里面实现mvc的，同时，在最后，我会写一个简单的游戏demo，当然，里面使用的是cocos2d＋mvc。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;现有问题&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; cocos2d里面有这样一些类，CCSprite，CCLayer，CCScene，所有这些，都是CCNode的子类。基本上，大家在使用cocos2d开发游戏的时候，都会采用下面的步骤来实现游戏逻辑：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;通过应用程序代理类来初始化第一个CCScene（即AppDelegate里面的第一个CCScene）,&lt;/li&gt;&lt;li&gt;CCScene里面实例化一个或者多个CCLayer，并把它们当作孩子添加进去。&lt;/li&gt;&lt;li&gt;CCLayer 里面实例化一个或者多个CCSprite，也调用addChild添加进去&lt;/li&gt;&lt;li&gt;CCScene 处理用户输入（比如touch事件和加速计的改变），同时更新CCLayer和CCSpirte的属性，比如更改CCSprite的position，让sprite运行一个或多个actioin等。&lt;/li&gt;&lt;li&gt;CCScene里在运行一个游戏循环（game loop，一般是1/60更新一次），然后CCLayer和CCSprite就在这个game loop里面做一些更新和游戏逻辑。&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 这个过程看起来非常简单，而且也可以很快地做出游戏来。这也是为什么cocos2d这么流行的原因，它实在是太简单了。但是，当你的游戏逻辑越来越复杂的时候，你的代码会变得越来越难以维护。这里面最突出的问题就是，CCScene这个类负责的事情太多了---同时要处理用户交互，还有负责游戏逻辑（逻辑层）和画面显示（表示层）。（译者：根据SoC的原则，这显然是不合理的，我们应该把职责分离开来，这样代码才更容易维护。同时SRP（单一职责原则）也是这么要求的，一个类只负责一件事情）&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;模型（Model）&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; MVC它会把一个系统划分为以下几个组件：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Model ，它负责与领域相关的逻辑处理代码，也可以说是逻辑层，或者领域层。&lt;/li&gt;&lt;li&gt;View ，只负责界面显示。&lt;/li&gt;&lt;li&gt;Controller ，它负责处理用户交互。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 让我们先从model开始。Model代表了游戏逻辑。因为我现在正在制作一个platform游戏，所以，我讲的一些东西也是与platform游戏相关联的。我的游戏里面的model包含下面一些类（当然，仅仅是一部分类）&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Player,&lt;ul&gt;&lt;li&gt;包含一些属性，比如：player的位置、当前速度（x轴速度、y轴速度）等。&lt;/li&gt;&lt;li&gt;包含一些与player有关的处理逻辑，比如：run，walk，jmup等。&lt;/li&gt;&lt;li&gt;包含一个update方法，该方法会被游戏主循环每一帧刷新时所调用，它主要负责更新player model。&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Platform,&lt;ul&gt;&lt;li&gt;包含一些属性，比如：platform位置、宽度、高度等。&lt;/li&gt;&lt;li&gt;包含一些与platform有关的处理逻辑，比如：倾塌等&lt;/li&gt;&lt;li&gt;包含一个update方法，该方法会被游戏主循环每一帧刷新时所调用，它主要负责更新patform的model。&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;GameModel,&lt;ul&gt;&lt;li&gt;包含一些游戏世界的属性，比如重力等。&lt;/li&gt;&lt;li&gt;包含一些方法来执行游戏逻辑。&lt;/li&gt;&lt;li&gt;包含一个update方法，该方法会在每一帧刷新的时候被game loop所调用，然后它就可以更新自己的状态，同时还会触发游戏世界里面的其它对象也相应地更新自己的状态。&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 你可能会问：有些属性你完全没有必要重复定义，你可以直接从CCSprite里面得到，比如position、width、height等。我想说：有对有错。说对呢，是因为它们确实差不多，可以拿来就用。说不对呢，那是因为，model有可能使用一些不同的计量单位，比如米，而不是像素。（比如box2d这样的，就不是使用像素作为单位）。在我的model里面，我使用的是米，当然，你也可以使用英尺，或者其它单位。渲染引擎对于model来说是透明的，model完全不用关心。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;视图（View）&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 根据mvc的原则，view应该只负责界面显示。它实际上也是在cocos2d里面实现mvc时，最简单的一个。如果你有一个model，你可以使用CCLayer，然后添加一些CCSprite或者其它coocs2d类来处理显示问题。把model和view分开的好处就是，你没必要把model的属性直接映射到view的属性上面去。比如，你的玩家在x轴方向上移动，但是，你想让它总是在距离屏幕左边10px的位置。这时候，你就可以移动CCLayer了，而不是真的在移动sprite。当把model对象显示出来的时候，你必须考虑单位，如果你使用的是米作为计量单位，你在渲染的时候必须转化为像素。（你可以像box2d里面一样，定义一个PTM_RATIO）那么你的model怎么和view打交道呢？你可以从controller里面得到view，或者你可以把game model制作成一个单例，然后使用静态方法来处理它。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;控制器（Controller）&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; controlller负责把view和model联系起来。它的主要职责就是处理用户输入。由于我们需要实例化model和view，我发现在controller里面来做非常合适。我是把controller类继承到CCScene类，然后我们需要建立一个初始的controller类，它由appDelegate来实例化。然而，这里会有一个问题，touch事件是由CCLayer来处理的，而它在我的设计里面的角色是view。而我又不想让view来处理用户输入，所以，我需要传递一个view的引用给controller（不是直接传递，而是通过delegate），然后通过delegate来执行controller的touch事件处理代码，以此来处理view里面的touch事件。好了，现在我的controller类就能够处理来自view的用户事件了。然后，它可以根据用户的输入来操作model，要么通过修改model的属性，或者调用model的方法。再更新完model之后，我们的view也需要得到通知并更新。所有这些，我都在game loop里面完成，实际上它就是一个controller。controller的职责只是负责调用view的update方法，然后剩下的就交给view去完成啦。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;还有一件事情&amp;hellip;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp;游戏并不仅仅是根据model状态的更改来更新一下view就可以了，它还需要播放音乐和音效。由于controller负责处理用户交互，它肯定知道何时该播放什么音效。但是，有些时候也会有例外。如果一个player掉到platform上面，但是controller并不知道，因为这部分逻辑判断在model里面。那我们可以从model里面播放音效吗？。。。不，我们不能这样做。因为这样就破坏了SoC的原则了，model就应该只负责游戏逻辑。那么，我们该怎么做呢？在下一篇博文中，我将向大家展示我是怎么做的，我打赌，你肯定差不多也想到呢，对吧？&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;后记：&lt;a href="http://www.cnblogs.com/andyque/archive/2012/03/11/2390814.html" target="_blank"&gt;cocos2d mvc这个系列&lt;/a&gt;一共有7篇，我会统一更新到这个目录，方便大家索引。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/zilongshanren/aggbug/2390074.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/zilongshanren/archive/2012/03/11/2390074.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
